Skip to content

Commit

Permalink
feat: Add a button to restore the default plugin, which will also upd…
Browse files Browse the repository at this point in the history
…ate the default plugin contents with new Thorium Nova versions.
  • Loading branch information
alexanderson1993 committed Feb 16, 2023
1 parent 2c562b8 commit 82388a8
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 75 deletions.
18 changes: 18 additions & 0 deletions client/src/data/server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import {initDefaultPlugin} from "@server/init/initDefaultPlugin";
import {t} from "@server/init/t";
import path from "path";
import fs from "fs/promises";
import {pubsub} from "@server/init/pubsub";

export const server = t.router({
snapshot: t.procedure.send(({ctx}) => {
Expand All @@ -10,4 +14,18 @@ export const server = t.router({
const flight = ctx.flight;
flight?.writeFile(true);
}),
restoreDefaultPlugin: t.procedure.send(async ({ctx}) => {
// Delete any default plugins
const defaultPlugins = ctx.server.plugins.filter(p => p.default);
await Promise.all(
defaultPlugins.map(p =>
fs.rm(path.dirname(p.filePath), {recursive: true, force: true})
)
);
await initDefaultPlugin();
pubsub.publish.plugin.all();
defaultPlugins.forEach(plugin =>
pubsub.publish.plugin.get({pluginId: plugin.id})
);
}),
});
152 changes: 87 additions & 65 deletions client/src/pages/Config/PluginEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -186,84 +186,106 @@ function PluginDetails() {
});
}}
/>
{plugin?.active ? (
<div className="grid grid-cols-2 w-full gap-2">
{plugin?.active ? (
<Button
className="w-full btn-outline btn-warning"
disabled={!pluginId}
onClick={async () => {
if (!pluginId) return;
q.plugin.update.netSend({pluginId, active: false});
}}
>
Deactivate Plugin
</Button>
) : (
<Button
className="w-full btn-outline btn-success"
disabled={!pluginId}
onClick={async () => {
if (!pluginId) return;
q.plugin.update.netSend({pluginId, active: true});
}}
>
Activate Plugin
</Button>
)}
<Button
className="w-full btn-outline btn-warning"
className="w-full btn-outline btn-error"
disabled={!pluginId}
onClick={async () => {
if (!pluginId) return;
q.plugin.update.netSend({pluginId, active: false});
if (
!pluginId ||
!(await confirm({
header: "Are you sure you want to delete this plugin?",
body: "All content in this plugin, including images and other assets, will be gone forever.",
}))
)
return;
q.plugin.update.netSend({pluginId});
navigate("/config");
}}
>
Deactivate Plugin
Delete Plugin
</Button>
) : (
<Button
className="w-full btn-outline btn-success"
className="w-full btn-outline btn-notice"
disabled={!pluginId}
onClick={async () => {
if (!pluginId) return;
q.plugin.update.netSend({pluginId, active: true});
}}
>
Activate Plugin
</Button>
)}
<Button
className="w-full btn-outline btn-error"
disabled={!pluginId}
onClick={async () => {
if (
!pluginId ||
!(await confirm({
header: "Are you sure you want to delete this plugin?",
body: "All content in this plugin, including images and other assets, will be gone forever.",
}))
)
return;
q.plugin.update.netSend({pluginId});
navigate("/config");
}}
>
Delete Plugin
</Button>
<Button
className="w-full btn-outline btn-notice"
disabled={!pluginId}
onClick={async () => {
if (!pluginId) return;
const name = await prompt({
header: "What is the name of the duplicated plugin?",
});
if (!name || typeof name !== "string") return;
try {
const result = await q.plugin.update.netSend({
pluginId: pluginId,
name,
const name = await prompt({
header: "What is the name of the duplicated plugin?",
});
navigate(`/config/${result.pluginId}`);
} catch (err) {
if (err instanceof Error) {
toast({
title: "Error duplicating plugin",
body: err.message,
color: "error",
if (!name || typeof name !== "string") return;
try {
const result = await q.plugin.update.netSend({
pluginId: pluginId,
name,
});
return;
navigate(`/config/${result.pluginId}`);
} catch (err) {
if (err instanceof Error) {
toast({
title: "Error duplicating plugin",
body: err.message,
color: "error",
});
return;
}
}
}
}}
>
Duplicate Plugin
</Button>
<Link
className={`btn w-full btn-outline btn-warning ${
!pluginId ? "btn-disabled" : ""
}`}
to={`/config/${pluginId}/list`}
>
Edit Plugin
</Link>
}}
>
Duplicate Plugin
</Button>
<Link
className={`btn w-full btn-outline btn-warning ${
!pluginId ? "btn-disabled" : ""
}`}
to={`/config/${pluginId}/list`}
>
Edit Plugin
</Link>
{plugin?.default ? (
<Button
className="w-full btn-outline btn-info"
disabled={!pluginId}
onClick={async () => {
if (!pluginId) return;
if (
await confirm({
header:
"Are you sure you want to restore the default plugin?",
body: "Any changes that you've made to the default plugin will be overwritten.",
})
) {
await q.server.restoreDefaultPlugin.netSend();
}
}}
>
Restore Plugin
</Button>
) : null}
</div>
</div>
<div>
<label>
Expand Down
11 changes: 2 additions & 9 deletions server/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,21 @@ import {setBasePath} from "@thorium/db-fs";
import buildHTTPServer from "./init/httpServer";
import path from "path";
import {promises as fs, existsSync} from "fs";
import {unzip} from "./utils/unzipFolder";
import {liveQueryPlugin} from "@thorium/live-query/adapters/fastify-adapter";
import {rootPath, thoriumPath} from "./utils/appPaths";
import {buildDatabase} from "./init/buildDatabase";
import {createContext, createWSContext} from "./init/liveQuery";
import {router} from "./init/router";
import {startServer} from "./init/startServer";
import {exitHandler} from "./init/exitHandler";
import {initDefaultPlugin} from "./init/initDefaultPlugin";

setBasePath(thoriumPath);
const isHeadless = !process.env.FORK;

export async function init() {
// Initialize the database if it doesn't exist
if (!existsSync(thoriumPath)) {
await fs.mkdir(thoriumPath, {recursive: true});
await fs.mkdir(path.join(thoriumPath, "plugins"), {recursive: true});
// Initialize the default plugin
await unzip(
path.join(rootPath, isHeadless ? "./" : "../../app", "defaultPlugin.zip"),
path.join(thoriumPath, "plugins/")
);
await initDefaultPlugin();
}

const database = await buildDatabase();
Expand Down
17 changes: 17 additions & 0 deletions server/src/init/initDefaultPlugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {promises as fs} from "fs";
import path from "path";
import {rootPath, thoriumPath} from "@server/utils/appPaths";
import {unzip} from "@server/utils/unzipFolder";

const isHeadless = !process.env.FORK;

export async function initDefaultPlugin() {
await fs.mkdir(thoriumPath, {recursive: true});
await fs.mkdir(path.join(thoriumPath, "plugins"), {recursive: true});

// Initialize the default plugin
await unzip(
path.join(rootPath, isHeadless ? "./" : "../../app", "defaultPlugin.zip"),
path.join(thoriumPath, "plugins/")
);
}
4 changes: 3 additions & 1 deletion shared/db-fs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ export abstract class FSDataStore {
return;
}
await fs.mkdir(path.dirname(this.filePath), {recursive: true});
let data = stringify(this.serialize());
const serialized = this.serialize();
delete serialized.initialData;
let data = stringify(serialized);

await fs.writeFile(this.filePath, data, {mode: 0o0600});
} catch (e: any) {
Expand Down

0 comments on commit 82388a8

Please sign in to comment.