@tiddlywiki/mws 0.0.12 → 0.0.13
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 -1
- package/dist/server.d.ts +923 -0
- package/dist/server.js +1763 -1415
- package/dist/server.js.map +1 -1
- package/editions/mws-docs/tiddlers/$__StoryList.tid +3 -3
- package/editions/mws-docs/tiddlers/MWS and SQLite.md +11 -0
- package/editions/mws-docs/tiddlers/Request Server.md +20 -0
- package/editions/mws-docs/tiddlers/Request Server.md.meta +5 -0
- package/package.json +16 -10
- package/prisma/schema.prisma +1 -0
- package/react-user-mgmt/package-lock.json +76 -321
- package/react-user-mgmt/package.json +2 -5
- package/react-user-mgmt/public/chunk-YALWN5OT.js +2 -0
- package/react-user-mgmt/public/chunk-YALWN5OT.js.map +7 -0
- package/react-user-mgmt/public/esm-QKDFEP3B.js +3 -0
- package/react-user-mgmt/public/esm-QKDFEP3B.js.map +7 -0
- package/react-user-mgmt/public/index.html +1 -26
- package/react-user-mgmt/public/main.js +68 -109
- package/react-user-mgmt/public/main.js.map +4 -4
- package/react-user-mgmt/public/stats.css +597 -0
- package/react-user-mgmt/public/stats.html +59 -0
- package/react-user-mgmt/public/stats.js +2013 -0
- package/react-user-mgmt/public/stats.json +1 -0
- package/react-user-mgmt/public/stats.svg +4 -0
- package/react-user-mgmt/tsconfig.json +3 -0
- package/dist/server.cjs +0 -16677
- package/dist/server.cjs.map +0 -1
- package/src/StateObject.ts +0 -316
- package/src/commander.ts +0 -417
- package/src/commands/divider.ts +0 -20
- package/src/commands/index.ts +0 -24
- package/src/commands/mws-init-store.ts +0 -77
- package/src/commands/mws-listen.ts +0 -136
- package/src/commands/mws-load-archive.ts +0 -281
- package/src/commands/mws-load-plugin-bags.ts +0 -151
- package/src/commands/mws-load-tiddlers.ts +0 -37
- package/src/commands/mws-load-wiki-folder.ts +0 -124
- package/src/commands/mws-render-tiddlywiki5.ts +0 -55
- package/src/commands/mws-save-archive.ts +0 -111
- package/src/commands/mws-save-tiddler-text.ts +0 -33
- package/src/commands/tests-complete.ts +0 -21
- package/src/global.ts +0 -247
- package/src/routes/TiddlerStore.ts +0 -722
- package/src/routes/bag-file-server.ts +0 -340
- package/src/routes/cache.ts +0 -25
- package/src/routes/index.ts +0 -138
- package/src/routes/managers/index.ts +0 -17
- package/src/routes/managers/manager-recipes.ts +0 -438
- package/src/routes/managers/manager-users.ts +0 -201
- package/src/routes/managers/router-tiddlers.ts +0 -313
- package/src/routes/router.ts +0 -429
- package/src/routes/services/PasswordService.ts +0 -178
- package/src/routes/services/attachments.ts +0 -259
- package/src/routes/services/sessions.ts +0 -166
- package/src/routes/tw-test.ts +0 -65
- package/src/server.ts +0 -151
- package/src/setupDevServer.ts +0 -71
- package/src/streamer.ts +0 -430
- package/src/tiddlywiki.ts +0 -94
- package/src/utils/data-checks.ts +0 -172
- package/src/utils/index.ts +0 -4
- package/src/utils/rootRoute.ts +0 -237
- package/src/utils/utils.ts +0 -403
- package/src/utils/zodAssert.ts +0 -269
- /package/prisma/{migrations/notes.md → notes.md} +0 -0
|
@@ -1,281 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { Commander, CommandInfo } from "../commander";
|
|
3
|
-
import { TiddlerStore } from "../routes/TiddlerStore";
|
|
4
|
-
import { join, resolve } from "path";
|
|
5
|
-
import { Prisma } from "@prisma/client";
|
|
6
|
-
import { Command as SaveArchiveCommand } from "./mws-save-archive";
|
|
7
|
-
import * as _fsp from "fs/promises";
|
|
8
|
-
import { createStrictAwaitProxy } from "../utils";
|
|
9
|
-
import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
|
|
10
|
-
import { existsSync } from "fs";
|
|
11
|
-
const fsp = createStrictAwaitProxy(_fsp);
|
|
12
|
-
|
|
13
|
-
export const info: CommandInfo = {
|
|
14
|
-
name: "mws-load-archive",
|
|
15
|
-
synchronous: true
|
|
16
|
-
};
|
|
17
|
-
export class Command {
|
|
18
|
-
|
|
19
|
-
constructor(
|
|
20
|
-
public params: string[],
|
|
21
|
-
public commander: Commander,
|
|
22
|
-
public callback: (err?: any) => void
|
|
23
|
-
) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async execute() {
|
|
29
|
-
if (this.params.length < 1) throw "Missing pathname";
|
|
30
|
-
const archivePath = this.params[0] as string;
|
|
31
|
-
|
|
32
|
-
const index: { version: number } = existsSync(resolve(archivePath, "index.json"))
|
|
33
|
-
? JSON.parse(await fsp.readFile(resolve(archivePath, "index.json"), "utf8"))
|
|
34
|
-
: { version: 1 };
|
|
35
|
-
// this is all the versions in this repo.
|
|
36
|
-
// the multi-wiki-support branch from the TW5 repo is not supported.
|
|
37
|
-
switch (index.version) {
|
|
38
|
-
case 1:
|
|
39
|
-
await new Archiver1(this.commander).loadArchive(archivePath);
|
|
40
|
-
break;
|
|
41
|
-
case 2:
|
|
42
|
-
await new Archiver2(this.commander).loadArchive(archivePath);
|
|
43
|
-
break;
|
|
44
|
-
default:
|
|
45
|
-
throw new Error(`Unsupported archive version ${index.version}`);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
this.commander.setupRequired = false;
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
class Archiver {
|
|
55
|
-
constructor(
|
|
56
|
-
public commander: Commander,
|
|
57
|
-
) {
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
63
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
64
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
65
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
66
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
67
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
68
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
69
|
-
|
|
70
|
-
class Archiver1 extends Archiver {
|
|
71
|
-
|
|
72
|
-
async loadArchive(archivePath: string) {
|
|
73
|
-
await this.commander.$transaction(async (prisma) => {
|
|
74
|
-
// load roles from roles/roles.json
|
|
75
|
-
const roles = JSON.parse(await fsp.readFile(resolve(archivePath, "roles", "roles.json"), "utf8"));
|
|
76
|
-
await prisma.roles.createMany({ data: roles });
|
|
77
|
-
// load users from users/{user_id}.json
|
|
78
|
-
const userFiles = await fsp.readdir(resolve(archivePath, "users"));
|
|
79
|
-
const users = await Promise.all(userFiles.map(async (userFile) => {
|
|
80
|
-
return JSON.parse(await fsp.readFile(resolve(archivePath, "users", userFile), "utf8"));
|
|
81
|
-
}));
|
|
82
|
-
await prisma.users.createMany({ data: users });
|
|
83
|
-
// Iterate the bags
|
|
84
|
-
const bagNames = await fsp.readdir(resolve(archivePath, "bags"));
|
|
85
|
-
for (const bagFilename of bagNames) {
|
|
86
|
-
const stat = await fsp.stat(resolve(archivePath, "bags", bagFilename));
|
|
87
|
-
if (!stat.isDirectory()) continue;
|
|
88
|
-
console.log(`Reading bag ${decodeURIComponent(bagFilename)}`);
|
|
89
|
-
await this.restoreBag(resolve(archivePath, "bags", bagFilename), prisma);
|
|
90
|
-
}
|
|
91
|
-
// Iterate the recipes
|
|
92
|
-
const recipeNames = await fsp.readdir(resolve(archivePath, "recipes"));
|
|
93
|
-
for (const recipeFilename of recipeNames) {
|
|
94
|
-
if (!recipeFilename.endsWith(".json")) continue;
|
|
95
|
-
console.log(`Reading recipe ${decodeURIComponent(recipeFilename)}`);
|
|
96
|
-
await this.restoreRecipe(resolve(archivePath, "recipes", recipeFilename), prisma);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
}).catch(e => {
|
|
100
|
-
if (e instanceof PrismaClientKnownRequestError) {
|
|
101
|
-
console.log(e.code, e.meta, e.message);
|
|
102
|
-
throw e.message;
|
|
103
|
-
} else {
|
|
104
|
-
throw e;
|
|
105
|
-
}
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
private async restoreRecipe(file: string, prisma: PrismaTxnClient) {
|
|
109
|
-
type RecipeInfo = Awaited<ReturnType<SaveArchiveCommand["getRecipes"]>>[number];
|
|
110
|
-
const recipeInfo: RecipeInfo = JSON.parse(await fsp.readFile(file, "utf8"));
|
|
111
|
-
await prisma.recipes.create({
|
|
112
|
-
data: {
|
|
113
|
-
recipe_id: recipeInfo.recipe_id,
|
|
114
|
-
recipe_name: recipeInfo.recipe_name,
|
|
115
|
-
description: recipeInfo.description,
|
|
116
|
-
owner_id: recipeInfo.owner_id,
|
|
117
|
-
acl: { createMany: { data: recipeInfo.acl } },
|
|
118
|
-
recipe_bags: {
|
|
119
|
-
createMany: {
|
|
120
|
-
data: recipeInfo.recipe_bags.map(e => ({
|
|
121
|
-
bag_id: e.bag_id,
|
|
122
|
-
position: e.position,
|
|
123
|
-
with_acl: e.with_acl,
|
|
124
|
-
}))
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
private async restoreBag(folder: string, prisma: PrismaTxnClient) {
|
|
131
|
-
type BagInfo = Awaited<ReturnType<SaveArchiveCommand["getBags"]>>[number];
|
|
132
|
-
const bagInfo: BagInfo = JSON.parse(await fsp.readFile(join(folder, "meta.json"), "utf8"));
|
|
133
|
-
await prisma.bags.create({
|
|
134
|
-
data: {
|
|
135
|
-
bag_id: bagInfo.bag_id,
|
|
136
|
-
bag_name: bagInfo.bag_name,
|
|
137
|
-
description: bagInfo.description,
|
|
138
|
-
owner_id: bagInfo.owner_id,
|
|
139
|
-
is_plugin: bagInfo.bag_name.startsWith("$:/"),
|
|
140
|
-
acl: { createMany: { data: bagInfo.acl } },
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
type TiddlerData = Awaited<ReturnType<SaveArchiveCommand["getBags"]>>[number]["tiddlers"][number];
|
|
144
|
-
const tiddlerFiles = await fsp.readdir(join(folder, "tiddlers"));
|
|
145
|
-
const tiddlers: TiddlerData[] = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
|
|
146
|
-
if (!tiddlerFilename.endsWith(".json")) return;
|
|
147
|
-
const value = await fsp.readFile(join(folder, "tiddlers", tiddlerFilename), "utf8");
|
|
148
|
-
return JSON.parse(value);
|
|
149
|
-
}));
|
|
150
|
-
await prisma.tiddlers.createMany({
|
|
151
|
-
data: tiddlers.flatMap((tiddler): Prisma.TiddlersCreateManyInput => ({
|
|
152
|
-
bag_id: bagInfo.bag_id,
|
|
153
|
-
title: tiddler.title,
|
|
154
|
-
is_deleted: tiddler.is_deleted,
|
|
155
|
-
attachment_hash: tiddler.attachment_hash,
|
|
156
|
-
tiddler_id: tiddler.tiddler_id,
|
|
157
|
-
}))
|
|
158
|
-
});
|
|
159
|
-
await prisma.fields.createMany({
|
|
160
|
-
data: tiddlers.flatMap(({ tiddler_id, fields }) => Object.entries(fields)
|
|
161
|
-
.map(([field_name, field_value]): Prisma.FieldsCreateManyInput =>
|
|
162
|
-
({ tiddler_id, field_name, field_value, })
|
|
163
|
-
)
|
|
164
|
-
)
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
171
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
172
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
173
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
174
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
175
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
176
|
-
////////////////////////////////////////////////////////////////////////////////////////
|
|
177
|
-
|
|
178
|
-
class Archiver2 extends Archiver {
|
|
179
|
-
|
|
180
|
-
async loadArchive(archivePath: string) {
|
|
181
|
-
await this.commander.$transaction(async (prisma) => {
|
|
182
|
-
const roles = JSON.parse(await fsp.readFile(resolve(archivePath, "roles.json"), "utf8"));
|
|
183
|
-
await prisma.roles.createMany({ data: roles });
|
|
184
|
-
const users: Awaited<ReturnType<SaveArchiveCommand["getUsers"]>> = JSON.parse(await fsp.readFile(resolve(archivePath, "users.json"), "utf8"));
|
|
185
|
-
await Promise.all(users.map(e => prisma.users.create({
|
|
186
|
-
data: ({
|
|
187
|
-
user_id: e.user_id,
|
|
188
|
-
email: e.email,
|
|
189
|
-
password: e.password,
|
|
190
|
-
username: e.username,
|
|
191
|
-
created_at: e.created_at,
|
|
192
|
-
last_login: e.last_login,
|
|
193
|
-
roles: ({ connect: e.roles.map(e => ({ role_id: e.role_id })) }),
|
|
194
|
-
} satisfies Prisma.UsersUncheckedCreateInput)
|
|
195
|
-
})));
|
|
196
|
-
|
|
197
|
-
// Iterate the bags
|
|
198
|
-
const bagNames = await fsp.readdir(resolve(archivePath, "bags"));
|
|
199
|
-
for (const bagFilename of bagNames) {
|
|
200
|
-
const stat = await fsp.stat(resolve(archivePath, "bags", bagFilename));
|
|
201
|
-
if (!stat.isDirectory()) continue;
|
|
202
|
-
console.log(`Reading bag ${decodeURIComponent(bagFilename)}`);
|
|
203
|
-
await this.restoreBag(resolve(archivePath, "bags", bagFilename), prisma);
|
|
204
|
-
}
|
|
205
|
-
// Iterate the recipes
|
|
206
|
-
const recipeNames = await fsp.readdir(resolve(archivePath, "recipes"));
|
|
207
|
-
for (const recipeFilename of recipeNames) {
|
|
208
|
-
if (!recipeFilename.endsWith(".json")) continue;
|
|
209
|
-
console.log(`Reading recipe ${decodeURIComponent(recipeFilename)}`);
|
|
210
|
-
await this.restoreRecipe(resolve(archivePath, "recipes", recipeFilename), prisma);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
}).catch(e => {
|
|
214
|
-
if (e instanceof PrismaClientKnownRequestError) {
|
|
215
|
-
console.log(e.code, e.meta, e.message);
|
|
216
|
-
throw e.message;
|
|
217
|
-
} else {
|
|
218
|
-
throw e;
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
private async restoreRecipe(file: string, prisma: PrismaTxnClient) {
|
|
223
|
-
type RecipeInfo = Awaited<ReturnType<SaveArchiveCommand["getRecipes"]>>[number];
|
|
224
|
-
const recipeInfo: RecipeInfo = JSON.parse(await fsp.readFile(file, "utf8"));
|
|
225
|
-
await prisma.recipes.create({
|
|
226
|
-
data: {
|
|
227
|
-
recipe_id: recipeInfo.recipe_id,
|
|
228
|
-
recipe_name: recipeInfo.recipe_name,
|
|
229
|
-
description: recipeInfo.description,
|
|
230
|
-
owner_id: recipeInfo.owner_id,
|
|
231
|
-
acl: { createMany: { data: recipeInfo.acl } },
|
|
232
|
-
recipe_bags: {
|
|
233
|
-
createMany: {
|
|
234
|
-
data: recipeInfo.recipe_bags.map(e => ({
|
|
235
|
-
bag_id: e.bag_id,
|
|
236
|
-
position: e.position,
|
|
237
|
-
with_acl: e.with_acl,
|
|
238
|
-
}))
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
private async restoreBag(folder: string, prisma: PrismaTxnClient) {
|
|
245
|
-
type BagInfo = Awaited<ReturnType<SaveArchiveCommand["getBags"]>>[number];
|
|
246
|
-
const bagInfo: BagInfo = JSON.parse(await fsp.readFile(join(folder, "meta.json"), "utf8"));
|
|
247
|
-
await prisma.bags.create({
|
|
248
|
-
data: {
|
|
249
|
-
bag_id: bagInfo.bag_id,
|
|
250
|
-
bag_name: bagInfo.bag_name,
|
|
251
|
-
description: bagInfo.description,
|
|
252
|
-
owner_id: bagInfo.owner_id,
|
|
253
|
-
is_plugin: bagInfo.is_plugin,
|
|
254
|
-
acl: { createMany: { data: bagInfo.acl } },
|
|
255
|
-
}
|
|
256
|
-
});
|
|
257
|
-
type TiddlerData = Awaited<ReturnType<SaveArchiveCommand["getBags"]>>[number]["tiddlers"][number];
|
|
258
|
-
const tiddlerFiles = await fsp.readdir(join(folder, "tiddlers"));
|
|
259
|
-
const tiddlers: TiddlerData[] = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
|
|
260
|
-
if (!tiddlerFilename.endsWith(".json")) return;
|
|
261
|
-
const value = await fsp.readFile(join(folder, "tiddlers", tiddlerFilename), "utf8");
|
|
262
|
-
return JSON.parse(value);
|
|
263
|
-
}));
|
|
264
|
-
await prisma.tiddlers.createMany({
|
|
265
|
-
data: tiddlers.flatMap((tiddler): Prisma.TiddlersCreateManyInput => ({
|
|
266
|
-
bag_id: bagInfo.bag_id,
|
|
267
|
-
title: tiddler.title,
|
|
268
|
-
is_deleted: tiddler.is_deleted,
|
|
269
|
-
attachment_hash: tiddler.attachment_hash,
|
|
270
|
-
tiddler_id: tiddler.tiddler_id,
|
|
271
|
-
}))
|
|
272
|
-
});
|
|
273
|
-
await prisma.fields.createMany({
|
|
274
|
-
data: tiddlers.flatMap(({ tiddler_id, fields }) => Object.entries(fields)
|
|
275
|
-
.map(([field_name, field_value]): Prisma.FieldsCreateManyInput =>
|
|
276
|
-
({ tiddler_id, field_name, field_value, })
|
|
277
|
-
)
|
|
278
|
-
)
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { resolve } from "node:path";
|
|
2
|
-
|
|
3
|
-
import { Commander, CommandInfo } from "../commander";
|
|
4
|
-
import { TiddlerStore } from "../routes/TiddlerStore";
|
|
5
|
-
import { TiddlerFields } from "../routes/services/attachments";
|
|
6
|
-
import { truthy, tryParseJSON } from "../utils";
|
|
7
|
-
import { Prisma, PrismaClient, PrismaPromise } from "@prisma/client";
|
|
8
|
-
|
|
9
|
-
export const info: CommandInfo = {
|
|
10
|
-
name: "mws-load-plugin-bags",
|
|
11
|
-
synchronous: true,
|
|
12
|
-
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export class Command {
|
|
17
|
-
|
|
18
|
-
get $tw() { return this.commander.$tw; }
|
|
19
|
-
constructor(
|
|
20
|
-
public params: string[],
|
|
21
|
-
public commander: Commander,
|
|
22
|
-
public callback: (err?: any) => void
|
|
23
|
-
) {
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
async execute() {
|
|
27
|
-
console.time(`${info.name} complete`);
|
|
28
|
-
await loadPluginBags(
|
|
29
|
-
this.$tw,
|
|
30
|
-
new TiddlerStore(this.commander, this.commander.engine),
|
|
31
|
-
this.commander.engine
|
|
32
|
-
);
|
|
33
|
-
console.timeEnd(`${info.name} complete`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
async function loadPluginBags($tw: any, store: TiddlerStore, engine: PrismaClient) {
|
|
39
|
-
|
|
40
|
-
// Copy plugins
|
|
41
|
-
function makePluginBagName(type: string, publisher: string | undefined, name: string) {
|
|
42
|
-
return "$:/" + type + "/" + (publisher ? publisher + "/" : "") + name;
|
|
43
|
-
}
|
|
44
|
-
function savePlugin(
|
|
45
|
-
pluginFields: TiddlerFields,
|
|
46
|
-
// tiddlers: Record<string, TiddlerFields>,
|
|
47
|
-
type: string,
|
|
48
|
-
publisher: string | undefined,
|
|
49
|
-
name: string
|
|
50
|
-
) {
|
|
51
|
-
|
|
52
|
-
const bagName = makePluginBagName(type, publisher, name) as PrismaField<"Bags", "bag_name">;
|
|
53
|
-
const description = (pluginFields.description ?? "(no description)") as PrismaField<"Bags", "description">;
|
|
54
|
-
const is_plugin = true as PrismaField<"Bags", "is_plugin">;
|
|
55
|
-
// await store.saveBagTiddler(pluginFields, bagName);
|
|
56
|
-
return [
|
|
57
|
-
store.upsertBag_PrismaPromise(bagName, description, is_plugin, { allowPrivilegedCharacters: true }),
|
|
58
|
-
...store.saveBagTiddlerFields_PrismaArray(pluginFields, bagName, null),
|
|
59
|
-
// ...Object.values(tiddlers).flatMap((fields) => store.saveBagTiddlerFields_PrismaArray(fields, bagName, null))
|
|
60
|
-
].filter(truthy);
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
function collectPlugins(folder: string, type: string, publisher?: string | undefined) {
|
|
64
|
-
var pluginFolders = $tw.utils.getSubdirectories(folder) || [];
|
|
65
|
-
const prismaPromiseArray: PrismaPromise<any>[] = [];
|
|
66
|
-
for (var p = 0; p < pluginFolders.length; p++) {
|
|
67
|
-
const pluginFolderName = pluginFolders[p];
|
|
68
|
-
if ($tw.boot.excludeRegExp.test(pluginFolderName)) continue;
|
|
69
|
-
|
|
70
|
-
const pluginFields: TiddlerFields = $tw.loadPluginFolder(resolve(folder, pluginFolderName));
|
|
71
|
-
if (!pluginFields?.title) continue;
|
|
72
|
-
|
|
73
|
-
// const { tiddlers = {} } = tryParseJSON<{
|
|
74
|
-
// tiddlers: Record<string, TiddlerFields>
|
|
75
|
-
// }>(pluginFields.text) ?? {};
|
|
76
|
-
// delete pluginFields.text;
|
|
77
|
-
|
|
78
|
-
prismaPromiseArray.push(...savePlugin(pluginFields, type, publisher, pluginFolderName));
|
|
79
|
-
|
|
80
|
-
// console.log(`Import plugin ${pluginFields.title}`);
|
|
81
|
-
}
|
|
82
|
-
prismaPromiseArray.forEach(e => {
|
|
83
|
-
if (e[Symbol.toStringTag] !== "PrismaPromise") console.log(e)
|
|
84
|
-
})
|
|
85
|
-
return prismaPromiseArray;
|
|
86
|
-
}
|
|
87
|
-
function collectPublisherPlugins(folder: string, type: string) {
|
|
88
|
-
var publisherFolders: string[] = $tw.utils.getSubdirectories(folder) || [];
|
|
89
|
-
return publisherFolders.flatMap((publisherFolderName) => {
|
|
90
|
-
if ($tw.boot.excludeRegExp.test(publisherFolderName)) return [];
|
|
91
|
-
return collectPlugins(resolve(folder, publisherFolderName), type, publisherFolderName);
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
const plugins = $tw.getLibraryItemSearchPaths($tw.config.pluginsPath, $tw.config.pluginsEnvVar);
|
|
95
|
-
const themes = $tw.getLibraryItemSearchPaths($tw.config.themesPath, $tw.config.themesEnvVar);
|
|
96
|
-
const languages = $tw.getLibraryItemSearchPaths($tw.config.languagesPath, $tw.config.languagesEnvVar);
|
|
97
|
-
const prismaPromiseArray = [
|
|
98
|
-
...plugins.flatMap((folder: string) => collectPublisherPlugins(folder, "plugins")),
|
|
99
|
-
...themes.flatMap((folder: string) => collectPublisherPlugins(folder, "themes")),
|
|
100
|
-
...languages.flatMap((folder: string) => collectPlugins(folder, "languages")),
|
|
101
|
-
];
|
|
102
|
-
prismaPromiseArray.forEach(e => {
|
|
103
|
-
if (e[Symbol.toStringTag] !== "PrismaPromise") {
|
|
104
|
-
if (Array.isArray(e)) console.log(e.length);
|
|
105
|
-
else console.log(e);
|
|
106
|
-
}
|
|
107
|
-
})
|
|
108
|
-
await engine.$transaction(prismaPromiseArray);
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
// // these are the main type definitions for the generator function.
|
|
115
|
-
// // Modify these if you use a typed sql framework.
|
|
116
|
-
// type YieldInput = Prisma.PrismaPromise<any>;
|
|
117
|
-
// type YieldOutput<Input extends YieldInput> = Awaited<Input>;
|
|
118
|
-
// // this is the generator type
|
|
119
|
-
// type PrismaGenerator<T> = Generator<YieldInput[], T, YieldOutput<YieldInput>[]>;
|
|
120
|
-
|
|
121
|
-
// const prisma = new PrismaClient();
|
|
122
|
-
// prisma.bagAcl.aggregate
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
// type MapInputToOutput<T extends YieldInput[]> = T extends [
|
|
126
|
-
// infer First extends YieldInput,
|
|
127
|
-
// ...infer Rest extends YieldInput[]
|
|
128
|
-
// ] ? [YieldOutput<First>, ...MapInputToOutput<Rest>] : [];
|
|
129
|
-
|
|
130
|
-
// /** This just types the yield output according to the input. Make sure you call it with `yield*` */
|
|
131
|
-
// function* Yielder<const I extends YieldInput[]>(...input: I)
|
|
132
|
-
// : PrismaGenerator<MapInputToOutput<I>> { return (yield input) as MapInputToOutput<I>; }
|
|
133
|
-
|
|
134
|
-
// function prismaYielder(prisma: PrismaClient) {
|
|
135
|
-
// return function* yielder<const I extends YieldInput[]>(...input: I)
|
|
136
|
-
// : PrismaGenerator<MapInputToOutput<I>> { return (yield input) as MapInputToOutput<I>; }
|
|
137
|
-
// }
|
|
138
|
-
|
|
139
|
-
// // this section is an example usage of the above functions
|
|
140
|
-
|
|
141
|
-
// function* prismaBatchTransaction(yielder: typeof Yielder): PrismaGenerator<{ titles: string[] }> {
|
|
142
|
-
// // yield* is essentially a spread operator for generators
|
|
143
|
-
// // yielder yeilds one value then returns the result.
|
|
144
|
-
// // this just gives us a way to type the output of a yield according to the input
|
|
145
|
-
// // so if we give it a typed sql query input, it can return a typed result
|
|
146
|
-
|
|
147
|
-
// const [result1] = yield* yielder(prisma.bagAcl.aggregate({}));
|
|
148
|
-
|
|
149
|
-
// return { titles: [] };
|
|
150
|
-
|
|
151
|
-
// }
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { resolve } from "path";
|
|
2
|
-
import { CommandInfo, Commander } from "../commander";
|
|
3
|
-
import { TiddlerStore } from "../routes/TiddlerStore";
|
|
4
|
-
import { SiteConfig } from "../routes/router";
|
|
5
|
-
import { TiddlerFields } from "../routes/services/attachments";
|
|
6
|
-
|
|
7
|
-
export const info: CommandInfo = {
|
|
8
|
-
name: "mws-load-tiddlers",
|
|
9
|
-
synchronous: true
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export class Command {
|
|
13
|
-
get $tw() { return this.commander.$tw; }
|
|
14
|
-
config: SiteConfig;
|
|
15
|
-
tiddlersPath: string;
|
|
16
|
-
bagName: PrismaField<"Bags", "bag_name">;
|
|
17
|
-
constructor(
|
|
18
|
-
public params: string[],
|
|
19
|
-
public commander: Commander,
|
|
20
|
-
public callback: (err?: any) => void
|
|
21
|
-
) {
|
|
22
|
-
this.config = this.commander.siteConfig;
|
|
23
|
-
this.tiddlersPath = resolve(this.params[0] as string);
|
|
24
|
-
this.bagName = this.params[1] as PrismaField<"Bags", "bag_name">;
|
|
25
|
-
}
|
|
26
|
-
async execute() {
|
|
27
|
-
if (this.params.length < 2) return "Missing pathname and/or bag name";
|
|
28
|
-
await this.commander.$transaction(async (prisma) => {
|
|
29
|
-
const store = new TiddlerStore(this.commander, prisma);
|
|
30
|
-
var tiddlersFromPath = this.$tw.loadTiddlersFromPath(this.tiddlersPath);
|
|
31
|
-
//@ts-ignore
|
|
32
|
-
await store.saveTiddlersFromPath(tiddlersFromPath, this.bagName);
|
|
33
|
-
});
|
|
34
|
-
return null;
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
/*\
|
|
2
|
-
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-load-wiki-folder.js
|
|
3
|
-
type: application/javascript
|
|
4
|
-
module-type: command
|
|
5
|
-
|
|
6
|
-
Command to create and load a bag for the specified core editions
|
|
7
|
-
|
|
8
|
-
--mws-load-wiki-folder <path> <bag-name> <bag-description> <recipe-name> <recipe-description>
|
|
9
|
-
|
|
10
|
-
\*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { resolve } from "path";
|
|
14
|
-
import { Commander, CommandInfo } from "../commander";
|
|
15
|
-
import { TiddlerStore } from "../routes/TiddlerStore";
|
|
16
|
-
import { TiddlerFields } from "../routes/services/attachments";
|
|
17
|
-
import { Prisma, PrismaClient } from "@prisma/client";
|
|
18
|
-
|
|
19
|
-
export const info: CommandInfo = {
|
|
20
|
-
name: "mws-load-wiki-folder",
|
|
21
|
-
synchronous: true
|
|
22
|
-
};
|
|
23
|
-
// tiddlywiki --load ./mywiki.html --savewikifolder ./mywikifolder
|
|
24
|
-
export class Command {
|
|
25
|
-
constructor(
|
|
26
|
-
public params: string[],
|
|
27
|
-
public commander: Commander,
|
|
28
|
-
public callback: (err?: any) => void
|
|
29
|
-
) {
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
async execute() {
|
|
33
|
-
|
|
34
|
-
// Check parameters
|
|
35
|
-
if (this.params.length < 5) {
|
|
36
|
-
return "Missing parameters for --mws-load-wiki-folder command";
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
await this.commander.engine.$transaction(loadWikiFolder({
|
|
40
|
-
wikiPath: this.params[0] as string,
|
|
41
|
-
bagName: this.params[1] as PrismaField<"Bags", "bag_name">,
|
|
42
|
-
bagDescription: this.params[2] as PrismaField<"Bags", "description">,
|
|
43
|
-
recipeName: this.params[3] as PrismaField<"Recipes", "recipe_name">,
|
|
44
|
-
recipeDescription: this.params[4] as PrismaField<"Recipes", "description">,
|
|
45
|
-
store: new TiddlerStore(this.commander, this.commander.engine),
|
|
46
|
-
$tw: this.commander.$tw
|
|
47
|
-
}));
|
|
48
|
-
console.log(info.name, "complete:", this.params[0])
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
// Function to convert a plugin name to a bag name
|
|
55
|
-
function makePluginBagName(type: string, publisher: string | undefined, name: string) {
|
|
56
|
-
return "$:/" + type + "/" + (publisher ? publisher + "/" : "") + name;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Copy TiddlyWiki core editions
|
|
60
|
-
function loadWikiFolder({ $tw, store, ...options }: {
|
|
61
|
-
wikiPath: string,
|
|
62
|
-
bagName: PrismaField<"Bags", "bag_name">,
|
|
63
|
-
bagDescription: PrismaField<"Bags", "description">,
|
|
64
|
-
recipeName: PrismaField<"Recipes", "recipe_name">,
|
|
65
|
-
recipeDescription: PrismaField<"Recipes", "description">,
|
|
66
|
-
store: TiddlerStore,
|
|
67
|
-
$tw: any
|
|
68
|
-
}) {
|
|
69
|
-
const path = require("path"),
|
|
70
|
-
fs = require("fs");
|
|
71
|
-
// Read the tiddlywiki.info file
|
|
72
|
-
const wikiInfoPath = path.resolve(options.wikiPath, $tw.config.wikiInfo);
|
|
73
|
-
let wikiInfo;
|
|
74
|
-
if (fs.existsSync(wikiInfoPath)) {
|
|
75
|
-
wikiInfo = $tw.utils.parseJSONSafe(fs.readFileSync(wikiInfoPath, "utf8"), function () { return null; });
|
|
76
|
-
}
|
|
77
|
-
if (!wikiInfo) return [];
|
|
78
|
-
// Add plugins to the recipe list
|
|
79
|
-
const recipeList = [];
|
|
80
|
-
const processPlugins = function (type: string, plugins: string[]) {
|
|
81
|
-
$tw.utils.each(plugins, function (pluginName: string) {
|
|
82
|
-
const parts = pluginName.split("/");
|
|
83
|
-
let publisher, name;
|
|
84
|
-
if (parts.length === 2) {
|
|
85
|
-
publisher = parts[0];
|
|
86
|
-
name = parts[1];
|
|
87
|
-
} else {
|
|
88
|
-
name = parts[0];
|
|
89
|
-
}
|
|
90
|
-
recipeList.push({ bag_name: makePluginBagName(type, publisher, name as string), with_acl: false });
|
|
91
|
-
});
|
|
92
|
-
};
|
|
93
|
-
processPlugins("plugins", wikiInfo.plugins);
|
|
94
|
-
processPlugins("themes", wikiInfo.themes);
|
|
95
|
-
processPlugins("languages", wikiInfo.languages);
|
|
96
|
-
// Create the recipe
|
|
97
|
-
recipeList.push({
|
|
98
|
-
bag_name: options.bagName,
|
|
99
|
-
with_acl: true as PrismaField<"Recipe_bags", "with_acl">,
|
|
100
|
-
});
|
|
101
|
-
recipeList.reverse()
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const tiddler_files_path = path.resolve(options.wikiPath, $tw.config.wikiTiddlersSubDir)
|
|
105
|
-
const tiddlersFromPath: TiddlerInfo[] = $tw.loadTiddlersFromPath(
|
|
106
|
-
resolve($tw.boot.corePath, $tw.config.editionsPath, tiddler_files_path)
|
|
107
|
-
);
|
|
108
|
-
|
|
109
|
-
const is_plugin = false as PrismaField<"Bags", "is_plugin">;
|
|
110
|
-
return [
|
|
111
|
-
// create the bag
|
|
112
|
-
store.upsertBag_PrismaPromise(options.bagName, options.bagDescription, is_plugin),
|
|
113
|
-
// create the recipe and recipe_bags entries
|
|
114
|
-
...store.upsertRecipe_PrismaArray(
|
|
115
|
-
options.recipeName,
|
|
116
|
-
options.recipeDescription,
|
|
117
|
-
recipeList,
|
|
118
|
-
),
|
|
119
|
-
// save the tiddlers (this will skip attachments)
|
|
120
|
-
...store.saveTiddlersFromPath_PrismaArray(tiddlersFromPath, options.bagName)
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
interface TiddlerInfo { tiddlers: TiddlerFields[], filepath: string, type: string, hasMetaFile: boolean }
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/*\
|
|
2
|
-
title: $:/plugins/tiddlywiki/multiwikiserver/commands/mws-render-tiddler.js
|
|
3
|
-
type: application/javascript
|
|
4
|
-
module-type: command
|
|
5
|
-
|
|
6
|
-
Command to create and load a bag for the specified core editions
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
\*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
import { resolve } from "node:path";
|
|
14
|
-
import { Commander, CommandInfo } from "../commander";
|
|
15
|
-
|
|
16
|
-
const { writeFileSync } = require("fs");
|
|
17
|
-
|
|
18
|
-
export const info: CommandInfo = {
|
|
19
|
-
name: "mws-render-tiddlywiki5",
|
|
20
|
-
synchronous: true
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export class Command {
|
|
24
|
-
|
|
25
|
-
constructor(
|
|
26
|
-
public params: string[],
|
|
27
|
-
public commander: Commander,
|
|
28
|
-
public callback: (err?: any) => void
|
|
29
|
-
) {
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
async execute() {
|
|
33
|
-
|
|
34
|
-
const result = this.commander.$tw.wiki.renderTiddler("text/plain", "$:/core/templates/tiddlywiki5.html", {
|
|
35
|
-
variables: {
|
|
36
|
-
saveTiddlerFilter: `
|
|
37
|
-
$:/boot/boot.css
|
|
38
|
-
$:/boot/boot.js
|
|
39
|
-
$:/boot/bootprefix.js
|
|
40
|
-
$:/core
|
|
41
|
-
$:/library/sjcl.js
|
|
42
|
-
$:/plugins/tiddlywiki/tiddlyweb
|
|
43
|
-
$:/plugins/tiddlywiki/multiwikiclient
|
|
44
|
-
$:/themes/tiddlywiki/snowwhite
|
|
45
|
-
$:/themes/tiddlywiki/vanilla
|
|
46
|
-
`
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
const filepath = resolve(this.commander.wikiPath, "tiddlywiki5.html")
|
|
51
|
-
|
|
52
|
-
writeFileSync(filepath, result);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|