@tiddlywiki/mws 0.1.8 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -5
- package/dist/metafile-esm.json +1 -1
- package/dist/mws.js +43 -50
- package/dist/mws.js.map +1 -1
- package/editions/mws-docs/tiddlers/$__StoryList.tid +5 -2
- package/editions/mws-docs/tiddlers/$__config_RelinkOnRename.tid +6 -0
- package/editions/mws-docs/tiddlers/2025-05-06 - syncer design.md +5 -1
- package/editions/mws-docs/tiddlers/2025-05-06 - syncer design.md.meta +1 -1
- package/editions/mws-docs/tiddlers/Bag.md +1 -0
- package/editions/mws-docs/tiddlers/Bag.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Bags and Recipes Complex Example.md +11 -0
- package/editions/mws-docs/tiddlers/Bags and Recipes Complex Example.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Bags and Recipes Model.md +14 -0
- package/editions/mws-docs/tiddlers/Bags and Recipes Model.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Bags and Recipes Simple Example.md +13 -0
- package/editions/mws-docs/tiddlers/Bags and Recipes Simple Example.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Code Layout.md +94 -0
- package/editions/mws-docs/tiddlers/Code Layout.md.meta +5 -0
- package/editions/mws-docs/tiddlers/Entity Access Control.md +1 -0
- package/editions/mws-docs/tiddlers/Entity Access Control.md.meta +5 -0
- package/editions/mws-docs/tiddlers/Entity Owner.md +3 -0
- package/editions/mws-docs/tiddlers/Entity Owner.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Entity Permissions.md +7 -0
- package/editions/mws-docs/tiddlers/Entity Permissions.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Entity.md +3 -0
- package/editions/mws-docs/tiddlers/Entity.md.meta +5 -0
- package/editions/mws-docs/tiddlers/HelloThere.tid +2 -2
- package/editions/mws-docs/tiddlers/Installation.md +31 -0
- package/editions/mws-docs/tiddlers/Installation.md.meta +5 -0
- package/editions/mws-docs/tiddlers/MWS Architecture_1.md +2 -0
- package/editions/mws-docs/tiddlers/{MWS Architecture.tid → MWS Architecture_1.md.meta } +2 -4
- package/editions/mws-docs/tiddlers/Recipe Bag Priority.md +5 -0
- package/editions/mws-docs/tiddlers/Recipe Bag Priority.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Recipe.tid +6 -0
- package/editions/mws-docs/tiddlers/Security.md +7 -7
- package/editions/mws-docs/tiddlers/Security.md.meta +1 -1
- package/editions/mws-docs/tiddlers/Server Routes.md +54 -0
- package/editions/mws-docs/tiddlers/Server Routes.md.meta +5 -0
- package/editions/mws-docs/tiddlers/Site Admin.md +3 -0
- package/editions/mws-docs/tiddlers/Site Admin.md.meta +4 -0
- package/editions/mws-docs/tiddlers/Wiki.md +2 -0
- package/editions/mws-docs/tiddlers/Wiki.md.meta +4 -0
- package/editions/mws-docs/tiddlers/system/$__palettes_MUI_styles.css +1 -1
- package/editions/mws-docs/tiddlers/system/$__palettes_MUI_styles.css.meta +1 -1
- package/mws.run.mjs +2 -2
- package/package.json +1 -1
- package/plugins/client/src/multiwikiclientadaptor.ts +16 -9
- package/plugins/client/tiddlers/syncer/multiwikiclientadaptor.js +9 -10
- package/plugins/client/tiddlers/syncer/syncer.js +3 -3
- package/public/react-admin/main.js +10 -10
- package/public/react-admin/main.js.map +3 -3
- package/public/react-admin/stats.json +1 -1
- package/scripts.mjs +4 -5
- package/editions/mws-docs/tiddlers/Bags and Recipes.tid +0 -41
- package/editions/mws-docs/tiddlers/Installation.tid +0 -32
- package/prisma/test.sqlite +0 -0
- package/prisma/test.sqlite-journal +0 -0
|
@@ -12,4 +12,8 @@ There also isn't a good way to move tiddlers between levels. Admins will need to
|
|
|
12
12
|
|
|
13
13
|
I'm not good at wikitext, but I can provide the endpoints for all of these operations as well as the client-side adapters and actions to use them.
|
|
14
14
|
|
|
15
|
-
-- Arlen22
|
|
15
|
+
-- Arlen22
|
|
16
|
+
|
|
17
|
+
## Update 2025-07-09
|
|
18
|
+
|
|
19
|
+
I've come up with a solution for this and opened a PR on GitHub [#9117](https://github.com/TiddlyWiki/TiddlyWiki5/pull/9117). I've also included the changes in the client plugin so MWS wikis can make use of them already. This is temporary and only allowed because the current version of MWS is still considered experimental.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
A bag is an [[Entity]] that stores tiddlers.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
A more complex example might be for a teacher working with a group of students:
|
|
2
|
+
|
|
3
|
+
- **student-{name}** bag for each students work
|
|
4
|
+
- **teacher-course** bag for the coursework, editable by the teacher
|
|
5
|
+
- **teacher-tools** bag for custom tools used by the teacher
|
|
6
|
+
|
|
7
|
+
Those bags would be exposed through the following hosted wikis:
|
|
8
|
+
|
|
9
|
+
- **student-{name}** hosted wiki for each students work, including the coursework material
|
|
10
|
+
- **teacher-course** hosted wiki for the coursework, editable by the teacher
|
|
11
|
+
- **teacher** hosted wiki for the teacher, bringing together all the bags, giving them an overview of all the students work
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
The bags and recipes model is a reference architecture for how tiddlers can be shared between multiple wikis. It was first introduced by TiddlyWeb in 2008.
|
|
2
|
+
|
|
3
|
+
The principles of bags and recipes can be simply stated:
|
|
4
|
+
|
|
5
|
+
1. Tiddlers are stored in named "bags"
|
|
6
|
+
2. Bags have access controls that determines which users can read or write to them
|
|
7
|
+
3. Recipes are named lists of bags, ordered from lowest priority to highest
|
|
8
|
+
4. The tiddlers within a recipe are accumulated in turn from each bag in the recipe in order of increasing priority. Thus, if there are multiple tiddlers with the same title in different bags then the one from the highest priority bag will be used as the recipe tiddler
|
|
9
|
+
5. Wikis are composed by splicing the tiddlers from the corresponding recipe into the standard TW5 HTML template
|
|
10
|
+
|
|
11
|
+
[[Bags and Recipes Simple Example]]
|
|
12
|
+
|
|
13
|
+
[[Bags and Recipes Complex Example]]
|
|
14
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
A very simple example of the recipe/bag model might be for a single user who maintains the following bags:
|
|
2
|
+
|
|
3
|
+
- **recipes** - tiddlers related to cooking recipes
|
|
4
|
+
- **work** - tiddlers related to work
|
|
5
|
+
- **app** - common tiddlers for customising TiddlyWiki
|
|
6
|
+
|
|
7
|
+
Those bags would be used with the following recipes:
|
|
8
|
+
|
|
9
|
+
- **recipes** --> recipes, app - wiki for working with recipes, with common custom components
|
|
10
|
+
- **work** --> work, app - wiki for working with work, with common custom components
|
|
11
|
+
- **app** --> app - wiki for maintaining custom components
|
|
12
|
+
|
|
13
|
+
All of this will work dynamically, so changes to the app bag will instantly ripple into the affected hosted wikis.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
|
|
2
|
+
The MWS repo is divided into separate projects in the `packages` folder. The entry point is in `packages/mws/src/index.ts`. The entry point imports the `server`, `commander`, and `events` projects.
|
|
3
|
+
|
|
4
|
+
The entire server uses Promises and async functions for pretty much everything. Synchronous file system calls should be avoided as much as possible.
|
|
5
|
+
|
|
6
|
+
The `events` project is the foundation of MWS. It contains an `EventEmitter` instance that everything else subscribes to.
|
|
7
|
+
|
|
8
|
+
Events are emitted asyncly. Event listeners are awaited with `Promise.all`, and rejections throw back to the event emit call. This is intentional because it is the heart of the entire server, not just a public event bus, and errors shouldn't be ignored. Errors that come from things like attempting to send SSE events to other clients, however, should not be thrown because they aren't relevent to the source of the event.
|
|
9
|
+
|
|
10
|
+
There should be no singleton references other than the event emitter and event handlers should be as pure as possible, so that in theory it would be possible to run multiple completely separate MWS servers in the same process.
|
|
11
|
+
|
|
12
|
+
The `commander` project handles the CLI parsing code. It exports a default function which MWS calls to execute the CLI. Commander emits several events during execution, which MWS hooks into to scaffold the rest of the server.
|
|
13
|
+
|
|
14
|
+
It also exports the base class for commands to inherit from, and because it instantiates the commands, commands should not specify their own constructor. Additional instance properties may be added to commands in the `cli.execute.before` event.
|
|
15
|
+
|
|
16
|
+
The `server` project handles all web related stuff, but in an MWS-agnostic way. It only requires the `events` project, so it could be used as the foundation for unrelated webservers. Its internal API is directly inspired by the TiddlyWiki server API, with routing and centralized handling of the request body.
|
|
17
|
+
|
|
18
|
+
The `mws` project is the application layer of MWS and ties everything else together. It defines all the commands and web server routes and handles the database connection.
|
|
19
|
+
|
|
20
|
+
The `react-admin` package is the Admin UI. It's based on react, and is built automatically when the dev server is enabled. You can find the server route in `packages/mws/src/services/setupDevServer.ts`
|
|
21
|
+
|
|
22
|
+
## Events
|
|
23
|
+
|
|
24
|
+
If this all sounds a bit confusing, here are the events that are emitted on a normal startup.
|
|
25
|
+
|
|
26
|
+
- `zod.make` - Emitted by `server` to extend the zod global.
|
|
27
|
+
- `cli.register` - Emitted by `commander` to register commands.
|
|
28
|
+
- `cli.commander` - Emitted by `commander` after routes are registered, but before help is printed.
|
|
29
|
+
- `cli.execute.before` - Emitted by `commander` right before the command is executed. This allows adding properties to the command instance for use later in the application.
|
|
30
|
+
|
|
31
|
+
These next ones are attachment points for further extension of MWS. They are emitted in the main `cli.execute.before` listener that MWS attaches.
|
|
32
|
+
|
|
33
|
+
- `mws.cache.init.before`
|
|
34
|
+
- `mws.cache.init.after`
|
|
35
|
+
- `mws.adapter.init.before`
|
|
36
|
+
- `mws.adapter.init.after`
|
|
37
|
+
- `mws.config.init.before`
|
|
38
|
+
- `mws.config.init.after`
|
|
39
|
+
|
|
40
|
+
Next, these are emitted by the listen command, either by `mws` or by `server`.
|
|
41
|
+
|
|
42
|
+
- `listen.router.init`
|
|
43
|
+
- `mws.router.init`
|
|
44
|
+
- `mws.routes.important`
|
|
45
|
+
- `mws.routes`
|
|
46
|
+
- `mws.routes.fallback`
|
|
47
|
+
|
|
48
|
+
And finally the event emitted after the command ends.
|
|
49
|
+
|
|
50
|
+
- `cli.execute.after`
|
|
51
|
+
|
|
52
|
+
## Event nesting
|
|
53
|
+
|
|
54
|
+
Some of them are nested. For instance, if I log the event name when it is emitted, and then how long it took when it completes, this is the output (indented for clarity).
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
zod.make
|
|
58
|
+
zod.make: 0.123ms
|
|
59
|
+
|
|
60
|
+
cli.register
|
|
61
|
+
cli.register: 0.088ms
|
|
62
|
+
|
|
63
|
+
cli.commander
|
|
64
|
+
cli.commander: 0.019ms
|
|
65
|
+
|
|
66
|
+
cli.execute.before
|
|
67
|
+
mws.cache.init.before
|
|
68
|
+
mws.cache.init.before: 0.014ms
|
|
69
|
+
mws.cache.init.after
|
|
70
|
+
mws.cache.init.after: 0.013ms
|
|
71
|
+
mws.adapter.init.before
|
|
72
|
+
mws.adapter.init.before: 0.007ms
|
|
73
|
+
mws.adapter.init.after
|
|
74
|
+
mws.adapter.init.after: 0.006ms
|
|
75
|
+
mws.config.init.before
|
|
76
|
+
mws.config.init.before: 0.008ms
|
|
77
|
+
mws.config.init.after
|
|
78
|
+
mws.config.init.after: 0.009ms
|
|
79
|
+
cli.execute.before: 1.171s
|
|
80
|
+
|
|
81
|
+
listen.router.init
|
|
82
|
+
mws.router.init
|
|
83
|
+
mws.router.init: 0.012ms
|
|
84
|
+
mws.routes.important
|
|
85
|
+
mws.routes.important: 0.006ms
|
|
86
|
+
mws.routes
|
|
87
|
+
mws.routes: 2.754ms
|
|
88
|
+
mws.routes.fallback
|
|
89
|
+
mws.routes.fallback: 0.054ms
|
|
90
|
+
listen.router.init: 4.002ms
|
|
91
|
+
|
|
92
|
+
cli.execute.after
|
|
93
|
+
cli.execute.after: 0.015ms
|
|
94
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Each [[Entity]] has a list of roles and the [[permissions|Entity Permissions]] they have on that entity.
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
When a user creates an [[Entity]], they can optionally become the owner of the entity. Owners have full [[permission|Entity Permissions]] over the entity. There can only be one or no owner of an entity.
|
|
2
|
+
|
|
3
|
+
Entity owners can not transfer ownership to another user. Only [[site admins|Site Admin]] can change ownership.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
There are 3 levels of permissions that can be assigned on the [[Entity Access Control]] list.
|
|
2
|
+
|
|
3
|
+
- **ADMIN** - Update the [[Entity Access Control]] list for this entity. Also granted WRITE and READ.
|
|
4
|
+
- **WRITE** - Create, update, and delete tiddlers. Also granted READ.
|
|
5
|
+
- **READ** - List and read tiddlers.
|
|
6
|
+
|
|
7
|
+
The [[Entity Owner]] and the [[site admins|Site Admin]] have full permissions over the [[entity]].
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
created: 20250417170314382
|
|
2
|
-
modified:
|
|
2
|
+
modified: 20250717214743442
|
|
3
3
|
tags: TableOfContents
|
|
4
4
|
title: HelloThere
|
|
5
5
|
type: text/vnd.tiddlywiki
|
|
@@ -11,7 +11,7 @@ type: text/vnd.tiddlywiki
|
|
|
11
11
|
|
|
12
12
|
Planned features include:
|
|
13
13
|
|
|
14
|
-
* Hosting multiple wikis at once, using the [[Bags and Recipes]]
|
|
14
|
+
* Hosting multiple wikis at once, using the [[Bags and Recipes Model]] for sharing data between them
|
|
15
15
|
* Full support for SQLite, as well as MariaDB/MySQL, Postgres, and Microsoft SQL Server
|
|
16
16
|
* Robust built-in synchronisation handlers for syncing data to the filesystem
|
|
17
17
|
* Flexible authentication and authorisation options
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
These instructions require minimal knowledge of the terminal and require NodeJS to be installed.
|
|
2
|
+
|
|
3
|
+
- Open a terminal window and set the current directory to the folder you want to create the project folder in.
|
|
4
|
+
- The init command creates the project folder and installs the required dependencies and config files. You can change the name to whatever you like.
|
|
5
|
+
<<.copy-code-to-clipboard """npm init @tiddlywiki/mws@latest "new_folder_name" """>>
|
|
6
|
+
- Set the current directory to the project folder that was just created:
|
|
7
|
+
<<.copy-code-to-clipboard """cd "new_folder_name" """>>
|
|
8
|
+
- Initialize the database
|
|
9
|
+
<<.copy-code-to-clipboard "npx mws init-store">>
|
|
10
|
+
- Start MWS:
|
|
11
|
+
<<.copy-code-to-clipboard "npx mws listen --listener">>
|
|
12
|
+
- Visit [[http://localhost:8080/]] in a browser on the same computer.
|
|
13
|
+
- When you have finished using MWS, stop the server with <kbd>ctrl-C</kbd>
|
|
14
|
+
|
|
15
|
+
See [[Troubleshooting]] if you encounter any errors.
|
|
16
|
+
|
|
17
|
+
### Updating MWS
|
|
18
|
+
|
|
19
|
+
To update your copy of MWS in the future with newer changes will require re-downloading the code, taking care not to lose any changes you might have made.
|
|
20
|
+
|
|
21
|
+
- Make a backup: Copy or zip your project folder to a safe backup folder. <<.copy-code-to-clipboard """tar -cf archive.tar "new_folder_name" """>>
|
|
22
|
+
- Get the latest version. Notice that the second word is `install` instead of `init`. This pulls the latest version from NPM and installs it. <<.copy-code-to-clipboard "npm install @tiddlywiki/mws@latest --save-exact">>
|
|
23
|
+
- Run MWS. On startup, MWS checks the database schema and updates it automatically if there are changes. Normally this works just fine, but it can fail, which is why it's important to save a backup first.
|
|
24
|
+
|
|
25
|
+
### Git repo
|
|
26
|
+
|
|
27
|
+
It is recommended to save a history of your project configuration using git,
|
|
28
|
+
|
|
29
|
+
- On Windows you can use [[GitHub Desktop|https://github.com/apps/desktop]].
|
|
30
|
+
- On Linux, git is usually preinstalled or available via the default package manager for your distro.
|
|
31
|
+
|
|
@@ -11,17 +11,17 @@ The primary use cases for MWS are
|
|
|
11
11
|
|
|
12
12
|
While these are the goals of MWS, it is still in early development, so none of these security restraints have actually been put in place yet. This is a work in progress, and the direction we're headed.
|
|
13
13
|
|
|
14
|
-
## Potential weaknesses
|
|
15
|
-
|
|
16
|
-
- **Not using HTTPS**
|
|
17
|
-
- **Oracles** that leak information through observable side-effects, such as network traffic, without directly revealing the contents.
|
|
18
|
-
- **Multi-user**: Users with write access can modify bags to gain access to other tiddlers in a different recipe that are supposed to be private.
|
|
19
|
-
|
|
20
14
|
## Don't add untrusted bags to your recipe.
|
|
21
15
|
|
|
22
16
|
Generally speaking, wiki text is quite powerful, almost as powerful as JavaScript. Button clicks can run widget actions, which can read and change any tiddler in the current recipe. Any user could easily cause TiddlyWiki to write tiddlers to other bags via actions.
|
|
23
17
|
|
|
24
|
-
A
|
|
18
|
+
A user can also modify a bag they have write access to so that when a different user loads that bag in their own recipe it gives the first user access to tiddlers that the second user would consider private. This flaw is almost inherent to the idea of bags and recipes and cannot be avoided.
|
|
19
|
+
|
|
20
|
+
## Potential weaknesses
|
|
21
|
+
|
|
22
|
+
- **Not using HTTPS** is always the number one weakness. If you're on an open WIFI network, your session info can be read by anyone within 100 meters.
|
|
23
|
+
- **Oracles** that leak information through observable side-effects, such as network traffic, without directly revealing the contents.
|
|
24
|
+
- **Multi-user**: Users with write access can modify bags to gain access to other tiddlers in a different recipe that are supposed to be private.
|
|
25
25
|
|
|
26
26
|
## Protection strategies
|
|
27
27
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
The routing for the server uses the same concept of routes as the TiddlyWiki core server, but significantly enhanced with TypeScript types and request helpers and primitives, including request validation.
|
|
2
|
+
|
|
3
|
+
## Server Routing
|
|
4
|
+
|
|
5
|
+
Routes are registered as a tree. The router starts at the root node and works its way down, using the regex and method of each route to check if the request matches. Once it finds a match, it recursively checks the children of those matches.
|
|
6
|
+
|
|
7
|
+
- The request method is "narrowed". Parent routes restrict the methods their child routes can accept.
|
|
8
|
+
|
|
9
|
+
Once the full route is determined, it handles the request body based on the options of the matched route, then it calls each handler, starting with the root handler, and continuing down.
|
|
10
|
+
|
|
11
|
+
- The request body format is determined by the parent routes, and child routes cannot change the body format if a parent route sets it.
|
|
12
|
+
|
|
13
|
+
In the example below, if the request matches child 2a, the router calls the root handler, then the child 2 handler, then the child 2a handler.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
[root]
|
|
18
|
+
|
|
19
|
+
- child 1
|
|
20
|
+
- child 1a
|
|
21
|
+
- child 2
|
|
22
|
+
- child 2a
|
|
23
|
+
- child 2b
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Server Route Definition
|
|
28
|
+
|
|
29
|
+
The type definitions for this interface contains comments with more details. Please see that for more info.
|
|
30
|
+
|
|
31
|
+
- **path**: A regular expression (must start with `^` to match the start of the path)
|
|
32
|
+
- **pathParams**: Keys for the Regex match params. The object is added to the request state.
|
|
33
|
+
- **method**: Array of methods supported by this route.
|
|
34
|
+
- **bodyFormat**: The desired body format for this route. Ignored if the parent also specifies a body format.
|
|
35
|
+
- **denyFinal**: Parent routes can set this so the request is rejected if no child routes are matched.
|
|
36
|
+
- **securityChecks**: additional security checks for the server to perform.
|
|
37
|
+
- **requestedWithHeader**: requires a custom `X-Requested-With` header to be set to one of the valid values (`fetch`, `XMLHttpRequest`, `TiddlyWiki`) in order to prevent form and `no-cors` requests.
|
|
38
|
+
|
|
39
|
+
## Request Validation
|
|
40
|
+
|
|
41
|
+
The `zodRoute` helper function implements validation checks and additional typing for the request object. See the comments and types in the `zodRoute` file for further information.
|
|
42
|
+
|
|
43
|
+
The zod options accept a function which returns a zod schema (or a hashmap of keys to zod schemas).
|
|
44
|
+
|
|
45
|
+
- **zodPathParams**: the path params object
|
|
46
|
+
- **zodQueryParams**: the query params object
|
|
47
|
+
- **zodRequestBody**: the request body
|
|
48
|
+
- The **path** is a string instead of a regex. The path is split on the `/` and names starting with a colon become path params.
|
|
49
|
+
- The **method**, **body format**, and **security checks** are same as above.
|
|
50
|
+
- **registerError**: An error instance to capture a stack trace in case it's needed for any reason. Note that in most runtimes the performance penalty is incurred when the stack trace is read, not when the error instance is created.
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
@@ -145,7 +145,7 @@ type: text/css
|
|
|
145
145
|
/* --------------------------------------------------------------------- */
|
|
146
146
|
/* Typography */
|
|
147
147
|
/* --------------------------------------------------------------------- */
|
|
148
|
-
--foreground: var(--color-grey-
|
|
148
|
+
--foreground: var(--color-grey-800);
|
|
149
149
|
/* text.primary */
|
|
150
150
|
--muted-foreground: var(--color-grey-700);
|
|
151
151
|
/* text.secondary */
|
package/mws.run.mjs
CHANGED
|
@@ -19,7 +19,7 @@ if(!pkg?.dependencies?.["@tiddlywiki/mws"] || pkg.name !== "@tiddlywiki/mws-inst
|
|
|
19
19
|
process.exit(1);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
import(
|
|
22
|
+
import(`file://${cwd}/node_modules/@tiddlywiki/mws/dist/mws.js`).then(mws => mws.default()).catch(console.error);
|
|
23
23
|
|
|
24
24
|
function tryParseJSON(file) {
|
|
25
25
|
try {
|
|
@@ -27,4 +27,4 @@ function tryParseJSON(file) {
|
|
|
27
27
|
} catch(e) {
|
|
28
28
|
return undefined;
|
|
29
29
|
}
|
|
30
|
-
}
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -124,6 +124,8 @@ interface SyncAdaptor<AD> {
|
|
|
124
124
|
|
|
125
125
|
isReady?(): boolean;
|
|
126
126
|
|
|
127
|
+
registerSyncer?(syncer: Syncer<AD>): void;
|
|
128
|
+
|
|
127
129
|
getStatus?(
|
|
128
130
|
cb: ServerStatusCallback
|
|
129
131
|
): void;
|
|
@@ -190,6 +192,7 @@ interface SyncAdaptor<AD> {
|
|
|
190
192
|
displayLoginPrompt?(syncer: Syncer<AD>): void;
|
|
191
193
|
login?(username: string, password: string, cb: (err: any) => void): void;
|
|
192
194
|
logout?(cb: (err: any) => void): any;
|
|
195
|
+
|
|
193
196
|
}
|
|
194
197
|
interface SyncerTiddlerInfo<AD> {
|
|
195
198
|
/** this comes from the wiki changeCount record */
|
|
@@ -249,7 +252,7 @@ class MultiWikiClientAdaptor implements SyncAdaptor<MWSAdaptorInfo> {
|
|
|
249
252
|
private serverUpdateConnectionStatus!: string;
|
|
250
253
|
private isDevMode: boolean;
|
|
251
254
|
private useGzipStream: boolean;
|
|
252
|
-
private
|
|
255
|
+
private syncer: Syncer<MWSAdaptorInfo> | null = null;
|
|
253
256
|
|
|
254
257
|
name = "multiwikiclient";
|
|
255
258
|
private supportsLazyLoading = true;
|
|
@@ -283,15 +286,21 @@ class MultiWikiClientAdaptor implements SyncAdaptor<MWSAdaptorInfo> {
|
|
|
283
286
|
setLoggerSaveBuffer(loggerForSaving: Logger) {
|
|
284
287
|
this.logger.setSaveBuffer(loggerForSaving);
|
|
285
288
|
}
|
|
289
|
+
|
|
286
290
|
isReady() {
|
|
287
291
|
return true;
|
|
288
292
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
this.
|
|
293
|
-
|
|
293
|
+
|
|
294
|
+
registerSyncer(syncer: Syncer<MWSAdaptorInfo>): void {
|
|
295
|
+
this.syncer = syncer;
|
|
296
|
+
if (this.useServerSentEvents)
|
|
297
|
+
this.connectRecipeEvents();
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
triggerPoll() {
|
|
301
|
+
this.syncer?.syncFromServer();
|
|
294
302
|
}
|
|
303
|
+
|
|
295
304
|
private getHost() {
|
|
296
305
|
var text = this.wiki.getTiddlerText(CONFIG_HOST_TIDDLER, DEFAULT_HOST_TIDDLER), substitutions = [
|
|
297
306
|
{ name: "protocol", value: document.location.protocol },
|
|
@@ -540,9 +549,7 @@ class MultiWikiClientAdaptor implements SyncAdaptor<MWSAdaptorInfo> {
|
|
|
540
549
|
// this.syncer && this.syncer.enqueueLoadTiddler(title);
|
|
541
550
|
// }
|
|
542
551
|
}
|
|
543
|
-
|
|
544
|
-
if ($tw.syncadaptor === this) return $tw.syncer as Syncer<MWSAdaptorInfo>;
|
|
545
|
-
}
|
|
552
|
+
|
|
546
553
|
async loadTiddlers(options: {
|
|
547
554
|
syncer: Syncer<MWSAdaptorInfo>;
|
|
548
555
|
titles: string[];
|
|
@@ -31,7 +31,7 @@ var CONFIG_HOST_TIDDLER = "$:/config/multiwikiclient/host", DEFAULT_HOST_TIDDLER
|
|
|
31
31
|
var SERVER_NOT_CONNECTED = "NOT CONNECTED", SERVER_CONNECTING_SSE = "CONNECTING SSE", SERVER_CONNECTED_SSE = "CONNECTED SSE", SERVER_POLLING = "SERVER POLLING";
|
|
32
32
|
class MultiWikiClientAdaptor {
|
|
33
33
|
constructor(options) {
|
|
34
|
-
this.
|
|
34
|
+
this.syncer = null;
|
|
35
35
|
this.name = "multiwikiclient";
|
|
36
36
|
this.supportsLazyLoading = true;
|
|
37
37
|
this.error = null;
|
|
@@ -66,11 +66,14 @@ class MultiWikiClientAdaptor {
|
|
|
66
66
|
isReady() {
|
|
67
67
|
return true;
|
|
68
68
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
69
|
+
registerSyncer(syncer) {
|
|
70
|
+
this.syncer = syncer;
|
|
71
|
+
if (this.useServerSentEvents)
|
|
72
|
+
this.connectRecipeEvents();
|
|
73
|
+
}
|
|
74
|
+
triggerPoll() {
|
|
75
|
+
var _a;
|
|
76
|
+
(_a = this.syncer) === null || _a === void 0 ? void 0 : _a.syncFromServer();
|
|
74
77
|
}
|
|
75
78
|
getHost() {
|
|
76
79
|
var text = this.wiki.getTiddlerText(CONFIG_HOST_TIDDLER, DEFAULT_HOST_TIDDLER), substitutions = [
|
|
@@ -295,10 +298,6 @@ class MultiWikiClientAdaptor {
|
|
|
295
298
|
// this.syncer && this.syncer.enqueueLoadTiddler(title);
|
|
296
299
|
// }
|
|
297
300
|
}
|
|
298
|
-
get syncer() {
|
|
299
|
-
if ($tw.syncadaptor === this)
|
|
300
|
-
return $tw.syncer;
|
|
301
|
-
}
|
|
302
301
|
loadTiddlers(options) {
|
|
303
302
|
return __awaiter(this, void 0, void 0, function* () {
|
|
304
303
|
const { syncer, titles, onNext, onDone, onError } = options;
|
|
@@ -139,9 +139,9 @@ function Syncer(options) {
|
|
|
139
139
|
self.handleLazyLoadEvent(title);
|
|
140
140
|
});
|
|
141
141
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
|
|
143
|
+
if(this.syncadaptor.registerSyncer)
|
|
144
|
+
this.syncadaptor.registerSyncer(this);
|
|
145
145
|
|
|
146
146
|
// Get the login status
|
|
147
147
|
this.getStatus(function(err,isLoggedIn) {
|