2023-06-22 08:36:25 +00:00
/ * \
2023-06-23 15:58:46 +00:00
title : $ : / p l u g i n s / t i d d l y w i k i / s q l i t e 3 s t o r e / s q l - w i k i - s t o r e . j s
type : application / javascript
2023-06-22 08:36:25 +00:00
2023-06-23 15:58:46 +00:00
A sqlite3 implementation of a wiki store object
This file is spliced into the HTML file to be executed before the boot kernel has been loaded .
2023-06-22 08:36:25 +00:00
\ * /
( function ( ) {
$tw . Wiki = function ( options ) {
options = options || { } ;
2023-06-29 06:55:59 +00:00
this . sqlFunctions = new $tw . SqlFunctions ( ) ;
2023-10-24 17:41:34 +00:00
this . sqlFunctions . sqlSetPluginPriorities ( [ ] ) ;
2023-06-29 06:55:59 +00:00
// Adapted version of the boot.js wiki store implementation follows
2023-06-22 08:36:25 +00:00
var self = this ,
getTiddlerTitles = function ( ) {
2023-06-29 06:55:59 +00:00
return self . sqlFunctions . sqlAllTitles ( ) ;
2023-06-22 08:36:25 +00:00
} ,
pluginTiddlers = [ ] , // Array of tiddlers containing registered plugins, ordered by priority
pluginInfo = Object . create ( null ) , // Hashmap of parsed plugin content
getShadowTiddlerTitles = function ( ) {
2023-06-29 06:55:59 +00:00
return self . sqlFunctions . sqlAllShadowTitles ( ) ;
2023-10-25 16:49:13 +00:00
} ,
enableIndexers = options . enableIndexers || null ,
indexers = [ ] ,
indexersByName = Object . create ( null ) ;
this . addIndexer = function ( indexer , name ) {
// We stub out this method because this store doesn't support external indexers
} ;
this . addInternalIndexer = function ( indexer , name ) {
// Bail if this indexer is not enabled
if ( enableIndexers && enableIndexers . indexOf ( name ) === - 1 ) {
return ;
}
console . log ( "Added indexer" , name )
indexers . push ( indexer ) ;
indexersByName [ name ] = indexer ;
indexer . init ( ) ;
2023-06-25 16:03:28 +00:00
} ;
2023-10-25 16:49:13 +00:00
this . getIndexer = function ( name ) {
return indexersByName [ name ] || null ;
} ;
2023-06-27 18:10:42 +00:00
// $tw.utils replacements
2023-06-22 08:36:25 +00:00
var eachObj = function ( object , callback ) {
var next , f , length ;
if ( object ) {
if ( Object . prototype . toString . call ( object ) == "[object Array]" ) {
for ( f = 0 , length = object . length ; f < length ; f ++ ) {
next = callback ( object [ f ] , f , object ) ;
if ( next === false ) {
break ;
}
}
} else {
var keys = Object . keys ( object ) ;
for ( f = 0 , length = keys . length ; f < length ; f ++ ) {
var key = keys [ f ] ;
next = callback ( object [ key ] , key , object ) ;
if ( next === false ) {
break ;
}
}
}
}
} ,
hop = function ( object , property ) {
return object ? Object . prototype . hasOwnProperty . call ( object , property ) : false ;
} ,
insertSortedArray = function ( array , value ) {
var low = 0 , high = array . length - 1 , mid , cmp ;
while ( low <= high ) {
mid = ( low + high ) >> 1 ;
cmp = value . localeCompare ( array [ mid ] ) ;
if ( cmp > 0 ) {
low = mid + 1 ;
} else if ( cmp < 0 ) {
high = mid - 1 ;
} else {
return array ;
}
}
array . splice ( low , 0 , value ) ;
return array ;
} ,
parseJSONSafe = function ( text , defaultJSON ) {
try {
return JSON . parse ( text ) ;
} catch ( e ) {
if ( typeof defaultJSON === "function" ) {
return defaultJSON ( e ) ;
} else {
return defaultJSON || { } ;
}
}
} ;
2023-07-06 10:53:41 +00:00
this . logTables = function ( ) {
self . sqlFunctions . sqlLogTables ( ) ;
}
2023-06-22 08:36:25 +00:00
// Add a tiddler to the store
this . addTiddler = function ( tiddler ) {
if ( ! ( tiddler instanceof $tw . Tiddler ) ) {
tiddler = new $tw . Tiddler ( tiddler ) ;
}
// Save the tiddler
if ( tiddler ) {
var title = tiddler . fields . title ;
if ( title ) {
// Save the new tiddler
2023-10-24 17:41:34 +00:00
self . sqlFunctions . sqlSaveTiddler ( tiddler . fields ) ;
2023-06-25 16:03:28 +00:00
// Update caches
2023-06-22 08:36:25 +00:00
this . clearCache ( title ) ;
this . clearGlobalCache ( ) ;
2023-10-25 16:49:13 +00:00
$tw . utils . each ( indexers , function ( indexer ) {
indexer . update ( ) ;
} ) ;
2023-06-22 08:36:25 +00:00
// Queue a change event
this . enqueueTiddlerEvent ( title ) ;
}
}
} ;
// Delete a tiddler
this . deleteTiddler = function ( title ) {
// Uncomment the following line for detailed logs of all tiddler deletions
// console.log("Deleting",title)
2023-06-25 20:05:28 +00:00
if ( self . tiddlerExists ( title ) ) {
2023-06-22 08:36:25 +00:00
// Delete the tiddler
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlDeleteTiddler ( title ) ;
2023-06-25 16:03:28 +00:00
// Update caches
2023-06-22 08:36:25 +00:00
this . clearCache ( title ) ;
this . clearGlobalCache ( ) ;
2023-10-25 16:49:13 +00:00
$tw . utils . each ( indexers , function ( indexer ) {
indexer . update ( ) ;
} ) ;
2023-06-22 08:36:25 +00:00
// Queue a change event
this . enqueueTiddlerEvent ( title , true ) ;
}
} ;
// Get a tiddler from the store
this . getTiddler = function ( title ) {
if ( title ) {
2023-06-29 06:55:59 +00:00
var t = self . sqlFunctions . sqlGetTiddler ( title ) ;
2023-06-22 08:36:25 +00:00
if ( t !== undefined ) {
2023-06-25 20:05:28 +00:00
return new $tw . Tiddler ( t ) ;
2023-06-22 08:36:25 +00:00
}
}
return undefined ;
} ;
// Get an array of all tiddler titles
this . allTitles = function ( ) {
2023-06-25 16:03:28 +00:00
return getTiddlerTitles ( ) ;
2023-06-22 08:36:25 +00:00
} ;
// Iterate through all tiddler titles
this . each = function ( callback ) {
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlEachTiddler ( function ( tiddlerFields , title ) {
2023-06-27 18:10:42 +00:00
callback ( new $tw . Tiddler ( tiddlerFields ) , title ) ;
} ) ;
2023-06-22 08:36:25 +00:00
} ;
// Get an array of all shadow tiddler titles
this . allShadowTitles = function ( ) {
2023-06-25 16:03:28 +00:00
return getShadowTiddlerTitles ( ) ;
2023-06-22 08:36:25 +00:00
} ;
// Iterate through all shadow tiddler titles
this . eachShadow = function ( callback ) {
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlEachShadowTiddler ( function ( tiddlerFields , title ) {
2023-06-27 18:10:42 +00:00
callback ( new $tw . Tiddler ( tiddlerFields ) , title ) ;
} ) ;
2023-06-22 08:36:25 +00:00
} ;
// Iterate through all tiddlers and then the shadows
this . eachTiddlerPlusShadows = function ( callback ) {
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlEachTiddlerPlusShadows ( function ( tiddlerFields , title ) {
2023-06-27 18:10:42 +00:00
callback ( new $tw . Tiddler ( tiddlerFields ) , title ) ;
} ) ;
2023-06-22 08:36:25 +00:00
} ;
// Iterate through all the shadows and then the tiddlers
this . eachShadowPlusTiddlers = function ( callback ) {
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlEachShadowPlusTiddlers ( function ( tiddlerFields , title ) {
2023-06-27 18:10:42 +00:00
callback ( new $tw . Tiddler ( tiddlerFields ) , title ) ;
} ) ;
2023-06-22 08:36:25 +00:00
} ;
this . tiddlerExists = function ( title ) {
2023-06-29 06:55:59 +00:00
return self . sqlFunctions . sqlTiddlerExists ( title ) ;
2023-06-22 08:36:25 +00:00
} ;
this . isShadowTiddler = function ( title ) {
2023-06-29 06:55:59 +00:00
return ! ! self . sqlFunctions . sqlGetShadowSource ( title ) ;
2023-06-22 08:36:25 +00:00
} ;
this . getShadowSource = function ( title ) {
2023-06-29 06:55:59 +00:00
return self . sqlFunctions . sqlGetShadowSource ( title ) ;
2023-06-22 08:36:25 +00:00
} ;
// Get an array of all the currently recognised plugin types
this . getPluginTypes = function ( ) {
var types = [ ] ;
eachObj ( pluginTiddlers , function ( pluginTiddler ) {
var pluginType = pluginTiddler . fields [ "plugin-type" ] ;
if ( pluginType && types . indexOf ( pluginType ) === - 1 ) {
types . push ( pluginType ) ;
}
} ) ;
return types ;
} ;
// Read plugin info for all plugins, or just an array of titles. Returns the number of plugins updated or deleted
this . readPluginInfo = function ( titles ) {
var results = {
modifiedPlugins : [ ] ,
deletedPlugins : [ ]
} ;
eachObj ( titles || getTiddlerTitles ( ) , function ( title ) {
2023-06-25 16:03:28 +00:00
var tiddler = self . getTiddler ( title ) ;
2023-06-22 08:36:25 +00:00
if ( tiddler ) {
if ( tiddler . fields . type === "application/json" && tiddler . hasField ( "plugin-type" ) && tiddler . fields . text ) {
pluginInfo [ tiddler . fields . title ] = parseJSONSafe ( tiddler . fields . text ) ;
results . modifiedPlugins . push ( tiddler . fields . title ) ;
}
} else {
if ( pluginInfo [ title ] ) {
delete pluginInfo [ title ] ;
results . deletedPlugins . push ( title ) ;
}
}
} ) ;
return results ;
} ;
// Get plugin info for a plugin
this . getPluginInfo = function ( title ) {
return pluginInfo [ title ] ;
} ;
// Register the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting registration to an array of tiddler titles. Return the array of titles affected
this . registerPluginTiddlers = function ( pluginType , titles ) {
var self = this ,
registeredTitles = [ ] ,
checkTiddler = function ( tiddler , title ) {
if ( tiddler && tiddler . fields . type === "application/json" && tiddler . fields [ "plugin-type" ] && ( ! pluginType || tiddler . fields [ "plugin-type" ] === pluginType ) ) {
var disablingTiddler = self . getTiddler ( "$:/config/Plugins/Disabled/" + title ) ;
if ( title === "$:/core" || ! disablingTiddler || ( disablingTiddler . fields . text || "" ) . trim ( ) !== "yes" ) {
self . unregisterPluginTiddlers ( null , [ title ] ) ; // Unregister the plugin if it's already registered
pluginTiddlers . push ( tiddler ) ;
registeredTitles . push ( tiddler . fields . title ) ;
}
}
} ;
if ( titles ) {
eachObj ( titles , function ( title ) {
checkTiddler ( self . getTiddler ( title ) , title ) ;
} ) ;
} else {
this . each ( function ( tiddler , title ) {
checkTiddler ( tiddler , title ) ;
} ) ;
}
return registeredTitles ;
} ;
// Unregister the plugin tiddlers of a particular type, or null/undefined for any type, optionally restricting unregistering to an array of tiddler titles. Returns an array of the titles affected
this . unregisterPluginTiddlers = function ( pluginType , titles ) {
var self = this ,
unregisteredTitles = [ ] ;
// Remove any previous registered plugins of this type
for ( var t = pluginTiddlers . length - 1 ; t >= 0 ; t -- ) {
var tiddler = pluginTiddlers [ t ] ;
if ( tiddler . fields [ "plugin-type" ] && ( ! pluginType || tiddler . fields [ "plugin-type" ] === pluginType ) && ( ! titles || titles . indexOf ( tiddler . fields . title ) !== - 1 ) ) {
unregisteredTitles . push ( tiddler . fields . title ) ;
pluginTiddlers . splice ( t , 1 ) ;
}
}
return unregisteredTitles ;
} ;
// Unpack the currently registered plugins, creating shadow tiddlers for their constituent tiddlers
this . unpackPluginTiddlers = function ( ) {
var self = this ;
// Sort the plugin titles by the `plugin-priority` field
pluginTiddlers . sort ( function ( a , b ) {
if ( "plugin-priority" in a . fields && "plugin-priority" in b . fields ) {
return a . fields [ "plugin-priority" ] - b . fields [ "plugin-priority" ] ;
} else if ( "plugin-priority" in a . fields ) {
return - 1 ;
} else if ( "plugin-priority" in b . fields ) {
return + 1 ;
} else if ( a . fields . title < b . fields . title ) {
return - 1 ;
} else if ( a . fields . title === b . fields . title ) {
return 0 ;
} else {
return + 1 ;
}
} ) ;
// Now go through the plugins in ascending order and assign the shadows
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlClearShadows ( ) ;
2023-10-21 11:00:51 +00:00
self . sqlFunctions . sqlSetPluginPriorities ( pluginTiddlers . map ( tiddler => tiddler . fields . title ) ) ;
2023-06-22 08:36:25 +00:00
eachObj ( pluginTiddlers , function ( tiddler ) {
// Extract the constituent tiddlers
if ( hop ( pluginInfo , tiddler . fields . title ) ) {
eachObj ( pluginInfo [ tiddler . fields . title ] . tiddlers , function ( constituentTiddler , constituentTitle ) {
// Save the tiddler object
if ( constituentTitle ) {
2023-06-27 18:10:42 +00:00
var shadowTiddler = Object . assign ( { } , constituentTiddler , { title : constituentTitle } )
2023-06-29 06:55:59 +00:00
self . sqlFunctions . sqlSaveTiddler ( shadowTiddler , tiddler . fields . title ) ;
2023-06-22 08:36:25 +00:00
}
} ) ;
}
} ) ;
this . clearCache ( null ) ;
this . clearGlobalCache ( ) ;
2023-10-25 16:49:13 +00:00
$tw . utils . each ( indexers , function ( indexer ) {
indexer . update ( ) ;
} ) ;
2023-06-22 08:36:25 +00:00
} ;
2023-07-19 20:52:28 +00:00
2023-07-21 12:21:04 +00:00
this . optimiseFilter = function ( filterString ) {
2023-10-21 11:00:51 +00:00
// switch($tw.utils.trim(filterString)) {
// case "[all[shadows+tiddlers]prefix[$:/language/Docs/Types/]get[name]length[]maxall[]]":
// return [this.sqlFunctions.sqlQuickFilterAllShadowsTiddlersPrefixDocTypeMaxLength()];
// break;
// }
2023-07-21 12:21:04 +00:00
return undefined ;
} ;
2023-10-25 16:49:13 +00:00
function TagSubIndexer ( indexer , iteratorMethod ) {
this . indexer = indexer ;
this . iteratorMethod = iteratorMethod ;
this . cache = Object . create ( null ) ; // Hashmap by title containing arrays of titles
2023-07-19 20:52:28 +00:00
}
2023-10-25 16:49:13 +00:00
TagSubIndexer . prototype . addIndexMethod = function ( ) {
var self = this ;
this . indexer . wiki [ this . iteratorMethod ] . byTag = function ( tag ) {
return self . lookup ( tag ) . slice ( 0 ) ;
} ;
} ;
TagSubIndexer . prototype . update = function ( ) {
this . cache = Object . create ( null ) ;
} ;
TagSubIndexer . prototype . lookup = function ( tag ) {
var cachedResult = this . cache [ tag ] ;
if ( cachedResult ) {
return cachedResult ;
}
var listing = self . sqlFunctions . sqlGetTiddlersWithTag ( tag , this . iteratorMethod ) ;
if ( this . indexer . wiki . sortByList ) {
listing = this . indexer . wiki . sortByList ( listing , tag ) ;
}
this . cache [ tag ] = listing ;
return listing ;
} ;
function TagIndexer ( wiki ) {
this . wiki = wiki ;
this . subIndexers = [
new TagSubIndexer ( this , "each" ) ,
new TagSubIndexer ( this , "eachShadow" ) ,
new TagSubIndexer ( this , "eachTiddlerPlusShadows" ) ,
new TagSubIndexer ( this , "eachShadowPlusTiddlers" )
] ;
$tw . utils . each ( this . subIndexers , function ( subIndexer ) {
subIndexer . addIndexMethod ( ) ;
} ) ;
}
TagIndexer . prototype . init = function ( ) {
} ;
TagIndexer . prototype . update = function ( ) {
$tw . utils . each ( this . subIndexers , function ( subIndexer ) {
subIndexer . update ( ) ;
} ) ;
} ;
this . addInternalIndexer ( new TagIndexer ( this ) , "TagIndexer" ) ;
2023-06-22 08:36:25 +00:00
} ;
} ) ( ) ;
2023-06-23 15:58:46 +00:00
//# sourceURL=$:/plugins/tiddlywiki/sqlite3store/sql-wiki-store.js