Further iteration
This commit is contained in:
parent
cbc00b73a0
commit
75da8e7ca9
@ -10,6 +10,7 @@ import { path } from "../common/deps.ts";
|
|||||||
|
|
||||||
Deno.test("Test plug run", async () => {
|
Deno.test("Test plug run", async () => {
|
||||||
// const tempDir = await Deno.makeTempDir();
|
// const tempDir = await Deno.makeTempDir();
|
||||||
|
const tempDbFile = await Deno.makeTempFile({ suffix: ".db" });
|
||||||
|
|
||||||
const assetBundle = new AssetBundle(assets);
|
const assetBundle = new AssetBundle(assets);
|
||||||
|
|
||||||
@ -26,6 +27,7 @@ Deno.test("Test plug run", async () => {
|
|||||||
assertEquals(
|
assertEquals(
|
||||||
await runPlug(
|
await runPlug(
|
||||||
testSpaceFolder,
|
testSpaceFolder,
|
||||||
|
tempDbFile,
|
||||||
"test.run",
|
"test.run",
|
||||||
[],
|
[],
|
||||||
assetBundle,
|
assetBundle,
|
||||||
@ -35,4 +37,5 @@ Deno.test("Test plug run", async () => {
|
|||||||
|
|
||||||
// await Deno.remove(tempDir, { recursive: true });
|
// await Deno.remove(tempDir, { recursive: true });
|
||||||
esbuild.stop();
|
esbuild.stop();
|
||||||
|
await Deno.remove(tempDbFile);
|
||||||
});
|
});
|
||||||
|
@ -9,16 +9,13 @@ import { AssetBundlePlugSpacePrimitives } from "../common/spaces/asset_bundle_sp
|
|||||||
|
|
||||||
export async function runPlug(
|
export async function runPlug(
|
||||||
spacePath: string,
|
spacePath: string,
|
||||||
|
dbPath: string,
|
||||||
functionName: string | undefined,
|
functionName: string | undefined,
|
||||||
args: string[] = [],
|
args: string[] = [],
|
||||||
builtinAssetBundle: AssetBundle,
|
builtinAssetBundle: AssetBundle,
|
||||||
indexFirst = false,
|
|
||||||
httpServerPort = 3123,
|
httpServerPort = 3123,
|
||||||
httpHostname = "127.0.0.1",
|
httpHostname = "127.0.0.1",
|
||||||
) {
|
) {
|
||||||
spacePath = path.resolve(spacePath);
|
|
||||||
const tempFile = Deno.makeTempFileSync({ suffix: ".db" });
|
|
||||||
console.log("Tempt db file", tempFile);
|
|
||||||
const serverController = new AbortController();
|
const serverController = new AbortController();
|
||||||
const app = new Application();
|
const app = new Application();
|
||||||
|
|
||||||
@ -27,7 +24,7 @@ export async function runPlug(
|
|||||||
new DiskSpacePrimitives(spacePath),
|
new DiskSpacePrimitives(spacePath),
|
||||||
builtinAssetBundle,
|
builtinAssetBundle,
|
||||||
),
|
),
|
||||||
tempFile,
|
dbPath,
|
||||||
app,
|
app,
|
||||||
);
|
);
|
||||||
await serverSystem.init();
|
await serverSystem.init();
|
||||||
@ -37,13 +34,6 @@ export async function runPlug(
|
|||||||
signal: serverController.signal,
|
signal: serverController.signal,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (indexFirst) {
|
|
||||||
await serverSystem.system.loadedPlugs.get("index")!.invoke(
|
|
||||||
"reindexSpace",
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (functionName) {
|
if (functionName) {
|
||||||
const [plugName, funcName] = functionName.split(".");
|
const [plugName, funcName] = functionName.split(".");
|
||||||
|
|
||||||
@ -54,7 +44,6 @@ export async function runPlug(
|
|||||||
const result = await plug.invoke(funcName, args);
|
const result = await plug.invoke(funcName, args);
|
||||||
await serverSystem.close();
|
await serverSystem.close();
|
||||||
serverSystem.denoKv.close();
|
serverSystem.denoKv.close();
|
||||||
await Deno.remove(tempFile);
|
|
||||||
serverController.abort();
|
serverController.abort();
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
|
1
cmd/constants.ts
Normal file
1
cmd/constants.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export const silverBulletDbFile = ".silverbullet.db";
|
@ -4,14 +4,15 @@ import assets from "../dist/plug_asset_bundle.json" assert {
|
|||||||
type: "json",
|
type: "json",
|
||||||
};
|
};
|
||||||
import { AssetBundle } from "../plugos/asset_bundle/bundle.ts";
|
import { AssetBundle } from "../plugos/asset_bundle/bundle.ts";
|
||||||
|
import { silverBulletDbFile } from "./constants.ts";
|
||||||
|
|
||||||
export async function plugRunCommand(
|
export async function plugRunCommand(
|
||||||
{
|
{
|
||||||
noIndex,
|
db,
|
||||||
hostname,
|
hostname,
|
||||||
port,
|
port,
|
||||||
}: {
|
}: {
|
||||||
noIndex: boolean;
|
db?: string;
|
||||||
hostname?: string;
|
hostname?: string;
|
||||||
port?: number;
|
port?: number;
|
||||||
},
|
},
|
||||||
@ -21,14 +22,18 @@ export async function plugRunCommand(
|
|||||||
) {
|
) {
|
||||||
spacePath = path.resolve(spacePath);
|
spacePath = path.resolve(spacePath);
|
||||||
console.log("Space path", spacePath);
|
console.log("Space path", spacePath);
|
||||||
|
let dbPath = path.resolve(spacePath, silverBulletDbFile);
|
||||||
|
if (db) {
|
||||||
|
dbPath = path.resolve(db);
|
||||||
|
}
|
||||||
console.log("Function to run:", functionName, "with arguments", args);
|
console.log("Function to run:", functionName, "with arguments", args);
|
||||||
try {
|
try {
|
||||||
const result = await runPlug(
|
const result = await runPlug(
|
||||||
spacePath,
|
spacePath,
|
||||||
|
dbPath,
|
||||||
functionName,
|
functionName,
|
||||||
args,
|
args,
|
||||||
new AssetBundle(assets),
|
new AssetBundle(assets),
|
||||||
!noIndex,
|
|
||||||
port,
|
port,
|
||||||
hostname,
|
hostname,
|
||||||
);
|
);
|
||||||
|
@ -17,6 +17,7 @@ import { ServerSystem } from "../server/server_system.ts";
|
|||||||
import { sleep } from "$sb/lib/async.ts";
|
import { sleep } from "$sb/lib/async.ts";
|
||||||
import { SilverBulletHooks } from "../common/manifest.ts";
|
import { SilverBulletHooks } from "../common/manifest.ts";
|
||||||
import { System } from "../plugos/system.ts";
|
import { System } from "../plugos/system.ts";
|
||||||
|
import { silverBulletDbFile } from "./constants.ts";
|
||||||
|
|
||||||
export async function serveCommand(
|
export async function serveCommand(
|
||||||
options: {
|
options: {
|
||||||
@ -28,7 +29,7 @@ export async function serveCommand(
|
|||||||
key?: string;
|
key?: string;
|
||||||
reindex?: boolean;
|
reindex?: boolean;
|
||||||
db?: string;
|
db?: string;
|
||||||
serverProcessing?: boolean;
|
storeOnly?: boolean;
|
||||||
},
|
},
|
||||||
folder?: string,
|
folder?: string,
|
||||||
) {
|
) {
|
||||||
@ -36,11 +37,13 @@ export async function serveCommand(
|
|||||||
"127.0.0.1";
|
"127.0.0.1";
|
||||||
const port = options.port ||
|
const port = options.port ||
|
||||||
(Deno.env.get("SB_PORT") && +Deno.env.get("SB_PORT")!) || 3000;
|
(Deno.env.get("SB_PORT") && +Deno.env.get("SB_PORT")!) || 3000;
|
||||||
|
const storeOnly = options.storeOnly || Deno.env.get("SB_STORE_ONLY");
|
||||||
let dbFile = options.db || Deno.env.get("SB_DB_FILE") || ".silverbullet.db";
|
let dbFile = options.db || Deno.env.get("SB_DB_FILE") || silverBulletDbFile;
|
||||||
|
|
||||||
const app = new Application();
|
const app = new Application();
|
||||||
|
|
||||||
|
console.log(options);
|
||||||
|
|
||||||
if (!folder) {
|
if (!folder) {
|
||||||
folder = Deno.env.get("SB_FOLDER");
|
folder = Deno.env.get("SB_FOLDER");
|
||||||
if (!folder) {
|
if (!folder) {
|
||||||
@ -84,7 +87,8 @@ To allow outside connections, pass -L 0.0.0.0 as a flag, and put a TLS terminato
|
|||||||
);
|
);
|
||||||
|
|
||||||
let system: System<SilverBulletHooks> | undefined;
|
let system: System<SilverBulletHooks> | undefined;
|
||||||
if (options.serverProcessing) {
|
// system = undefined in storeOnly mode (no PlugOS instance on the server)
|
||||||
|
if (!storeOnly) {
|
||||||
// Enable server-side processing
|
// Enable server-side processing
|
||||||
dbFile = path.resolve(folder, dbFile);
|
dbFile = path.resolve(folder, dbFile);
|
||||||
console.log(
|
console.log(
|
||||||
|
@ -1,97 +0,0 @@
|
|||||||
import type {
|
|
||||||
ProxyFetchRequest,
|
|
||||||
ProxyFetchResponse,
|
|
||||||
} from "../../common/proxy_fetch.ts";
|
|
||||||
import {
|
|
||||||
base64Decode,
|
|
||||||
base64Encode,
|
|
||||||
} from "../../plugos/asset_bundle/base64.ts";
|
|
||||||
|
|
||||||
async function readStream(
|
|
||||||
stream: ReadableStream<Uint8Array>,
|
|
||||||
): Promise<Uint8Array> {
|
|
||||||
const arrays: Uint8Array[] = [];
|
|
||||||
let totalRead = 0;
|
|
||||||
const reader = stream.getReader();
|
|
||||||
while (true) {
|
|
||||||
// The `read()` method returns a promise that
|
|
||||||
// resolves when a value has been received.
|
|
||||||
const { done, value } = await reader.read();
|
|
||||||
// Result objects contain two properties:
|
|
||||||
// `done` - `true` if the stream has already given you all its data.
|
|
||||||
// `value` - Some data. Always `undefined` when `done` is `true`.
|
|
||||||
if (done) {
|
|
||||||
const resultArray = new Uint8Array(totalRead);
|
|
||||||
let offset = 0;
|
|
||||||
for (const array of arrays) {
|
|
||||||
resultArray.set(array, offset);
|
|
||||||
offset += array.length;
|
|
||||||
}
|
|
||||||
return resultArray;
|
|
||||||
}
|
|
||||||
arrays.push(value);
|
|
||||||
totalRead += value.length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function sandboxFetch(
|
|
||||||
reqInfo: RequestInfo,
|
|
||||||
options?: ProxyFetchRequest,
|
|
||||||
): Promise<ProxyFetchResponse> {
|
|
||||||
if (typeof reqInfo !== "string") {
|
|
||||||
const body = new Uint8Array(await reqInfo.arrayBuffer());
|
|
||||||
const encodedBody = body.length > 0 ? base64Encode(body) : undefined;
|
|
||||||
options = {
|
|
||||||
method: reqInfo.method,
|
|
||||||
headers: Object.fromEntries(reqInfo.headers.entries()),
|
|
||||||
base64Body: encodedBody,
|
|
||||||
};
|
|
||||||
reqInfo = reqInfo.url;
|
|
||||||
}
|
|
||||||
// @ts-ignore: monkey patching fetch
|
|
||||||
return syscall("sandboxFetch.fetch", reqInfo, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function bodyInitToUint8Array(init: BodyInit): Promise<Uint8Array> {
|
|
||||||
if (init instanceof Blob) {
|
|
||||||
const buffer = await init.arrayBuffer();
|
|
||||||
return new Uint8Array(buffer);
|
|
||||||
} else if (init instanceof ArrayBuffer) {
|
|
||||||
return new Uint8Array(init);
|
|
||||||
} else if (init instanceof ReadableStream) {
|
|
||||||
return readStream(init);
|
|
||||||
} else if (typeof init === "string") {
|
|
||||||
return new TextEncoder().encode(init);
|
|
||||||
} else {
|
|
||||||
throw new Error("Unknown body init type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function monkeyPatchFetch() {
|
|
||||||
// @ts-ignore: monkey patching fetch
|
|
||||||
globalThis.nativeFetch = globalThis.fetch;
|
|
||||||
// @ts-ignore: monkey patching fetch
|
|
||||||
globalThis.fetch = async function (
|
|
||||||
reqInfo: RequestInfo,
|
|
||||||
init?: RequestInit,
|
|
||||||
): Promise<Response> {
|
|
||||||
const encodedBody = init && init.body
|
|
||||||
? base64Encode(
|
|
||||||
new Uint8Array(await (new Response(init.body)).arrayBuffer()),
|
|
||||||
)
|
|
||||||
: undefined;
|
|
||||||
// console.log("Encoded this body", encodedBody);
|
|
||||||
const r = await sandboxFetch(
|
|
||||||
reqInfo,
|
|
||||||
init && {
|
|
||||||
method: init.method,
|
|
||||||
headers: init.headers as Record<string, string>,
|
|
||||||
base64Body: encodedBody,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return new Response(r.base64Body ? base64Decode(r.base64Body) : null, {
|
|
||||||
status: r.status,
|
|
||||||
headers: r.headers,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,7 +1,9 @@
|
|||||||
// This is the runtime imported from the compiled plug worker code
|
// This is the runtime imported from the compiled plug worker code
|
||||||
|
|
||||||
import type { ControllerMessage, WorkerMessage } from "./protocol.ts";
|
import type { ControllerMessage, WorkerMessage } from "./protocol.ts";
|
||||||
import type { Manifest } from "../common/manifest.ts";
|
import type {
|
||||||
|
ProxyFetchRequest,
|
||||||
|
ProxyFetchResponse,
|
||||||
|
} from "../common/proxy_fetch.ts";
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
function syscall(name: string, ...args: any[]): Promise<any>;
|
function syscall(name: string, ...args: any[]): Promise<any>;
|
||||||
@ -53,7 +55,7 @@ self.syscall = async (name: string, ...args: any[]) => {
|
|||||||
export function setupMessageListener(
|
export function setupMessageListener(
|
||||||
// deno-lint-ignore ban-types
|
// deno-lint-ignore ban-types
|
||||||
functionMapping: Record<string, Function>,
|
functionMapping: Record<string, Function>,
|
||||||
manifest: Manifest,
|
manifest: any,
|
||||||
) {
|
) {
|
||||||
self.addEventListener("message", (event: { data: WorkerMessage }) => {
|
self.addEventListener("message", (event: { data: WorkerMessage }) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
@ -81,7 +83,6 @@ export function setupMessageListener(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case "sysr":
|
case "sysr":
|
||||||
{
|
{
|
||||||
@ -109,6 +110,72 @@ export function setupMessageListener(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function base64Decode(s: string): Uint8Array {
|
||||||
|
const binString = atob(s);
|
||||||
|
const len = binString.length;
|
||||||
|
const bytes = new Uint8Array(len);
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
bytes[i] = binString.charCodeAt(i);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function base64Encode(buffer: Uint8Array | string): string {
|
||||||
|
if (typeof buffer === "string") {
|
||||||
|
buffer = new TextEncoder().encode(buffer);
|
||||||
|
}
|
||||||
|
let binary = "";
|
||||||
|
const len = buffer.byteLength;
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
binary += String.fromCharCode(buffer[i]);
|
||||||
|
}
|
||||||
|
return btoa(binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function sandboxFetch(
|
||||||
|
reqInfo: RequestInfo,
|
||||||
|
options?: ProxyFetchRequest,
|
||||||
|
): Promise<ProxyFetchResponse> {
|
||||||
|
if (typeof reqInfo !== "string") {
|
||||||
|
const body = new Uint8Array(await reqInfo.arrayBuffer());
|
||||||
|
const encodedBody = body.length > 0 ? base64Encode(body) : undefined;
|
||||||
|
options = {
|
||||||
|
method: reqInfo.method,
|
||||||
|
headers: Object.fromEntries(reqInfo.headers.entries()),
|
||||||
|
base64Body: encodedBody,
|
||||||
|
};
|
||||||
|
reqInfo = reqInfo.url;
|
||||||
|
}
|
||||||
|
return syscall("sandboxFetch.fetch", reqInfo, options);
|
||||||
|
}
|
||||||
|
|
||||||
// Monkey patch fetch()
|
// Monkey patch fetch()
|
||||||
import { monkeyPatchFetch } from "../plug-api/plugos-syscall/fetch.ts";
|
|
||||||
|
export function monkeyPatchFetch() {
|
||||||
|
globalThis.nativeFetch = globalThis.fetch;
|
||||||
|
// @ts-ignore: monkey patching fetch
|
||||||
|
globalThis.fetch = async function (
|
||||||
|
reqInfo: RequestInfo,
|
||||||
|
init?: RequestInit,
|
||||||
|
): Promise<Response> {
|
||||||
|
const encodedBody = init && init.body
|
||||||
|
? base64Encode(
|
||||||
|
new Uint8Array(await (new Response(init.body)).arrayBuffer()),
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
const r = await sandboxFetch(
|
||||||
|
reqInfo,
|
||||||
|
init && {
|
||||||
|
method: init.method,
|
||||||
|
headers: init.headers as Record<string, string>,
|
||||||
|
base64Body: encodedBody,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return new Response(r.base64Body ? base64Decode(r.base64Body) : null, {
|
||||||
|
status: r.status,
|
||||||
|
headers: r.headers,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
monkeyPatchFetch();
|
monkeyPatchFetch();
|
||||||
|
@ -104,7 +104,6 @@ functions:
|
|||||||
command:
|
command:
|
||||||
name: "Text: Strikethrough"
|
name: "Text: Strikethrough"
|
||||||
key: "Ctrl-Shift-s"
|
key: "Ctrl-Shift-s"
|
||||||
mac: "Cmd-Shift-s"
|
|
||||||
wrapper: "~~"
|
wrapper: "~~"
|
||||||
marker:
|
marker:
|
||||||
path: ./text.ts:wrapSelection
|
path: ./text.ts:wrapSelection
|
||||||
|
@ -45,9 +45,7 @@ export async function renamePageCommand(cmdDef: any) {
|
|||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const updatedReferences = await renamePage(oldName, newName);
|
const updatedReferences = await renamePage(oldName, newName, true);
|
||||||
console.log("Navigating to new page");
|
|
||||||
await editor.navigate(newName, 0, true);
|
|
||||||
|
|
||||||
await editor.flashNotification(
|
await editor.flashNotification(
|
||||||
`Renamed page, and updated ${updatedReferences} references`,
|
`Renamed page, and updated ${updatedReferences} references`,
|
||||||
@ -57,12 +55,21 @@ export async function renamePageCommand(cmdDef: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function renamePage(oldName: string, newName: string): Promise<number> {
|
async function renamePage(
|
||||||
|
oldName: string,
|
||||||
|
newName: string,
|
||||||
|
navigateThere = false,
|
||||||
|
): Promise<number> {
|
||||||
const text = await space.readPage(oldName);
|
const text = await space.readPage(oldName);
|
||||||
|
|
||||||
console.log("Writing new page to space");
|
console.log("Writing new page to space");
|
||||||
const newPageMeta = await space.writePage(newName, text);
|
const newPageMeta = await space.writePage(newName, text);
|
||||||
|
|
||||||
|
if (navigateThere) {
|
||||||
|
console.log("Navigating to new page");
|
||||||
|
await editor.navigate(newName, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
const pagesToUpdate = await getBackLinks(oldName);
|
const pagesToUpdate = await getBackLinks(oldName);
|
||||||
console.log("All pages containing backlinks", pagesToUpdate);
|
console.log("All pages containing backlinks", pagesToUpdate);
|
||||||
|
|
||||||
|
@ -70,8 +70,8 @@ export class HttpServer {
|
|||||||
this.options.pagesPath.replaceAll("\\", "\\\\"),
|
this.options.pagesPath.replaceAll("\\", "\\\\"),
|
||||||
// );
|
// );
|
||||||
).replaceAll(
|
).replaceAll(
|
||||||
"{{SUPPORT_ONLINE_MODE}}",
|
"{{SYNC_ONLY}}",
|
||||||
this.system ? "true" : "false",
|
this.system ? "false" : "true",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ await new Command()
|
|||||||
"Path to TLS key",
|
"Path to TLS key",
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
"--no-server-processing [type:boolean]",
|
"--store-only",
|
||||||
"Disable online mode (no server-side processing)",
|
"Run the server as a pure space (file) store only without any backend processing (this disables 'server mode' in the client)",
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
"--reindex [type:boolean]",
|
"--reindex",
|
||||||
"Reindex space on startup",
|
"Reindex space on startup",
|
||||||
)
|
)
|
||||||
.option(
|
.option(
|
||||||
@ -60,8 +60,8 @@ await new Command()
|
|||||||
// plug:compile
|
// plug:compile
|
||||||
.command("plug:compile", "Bundle (compile) one or more plug manifests")
|
.command("plug:compile", "Bundle (compile) one or more plug manifests")
|
||||||
.arguments("<...name.plug.yaml:string>")
|
.arguments("<...name.plug.yaml:string>")
|
||||||
.option("--debug [type:boolean]", "Do not minifiy code", { default: false })
|
.option("--debug", "Do not minifiy code", { default: false })
|
||||||
.option("--info [type:boolean]", "Print out size info per function", {
|
.option("--info", "Print out size info per function", {
|
||||||
default: false,
|
default: false,
|
||||||
})
|
})
|
||||||
.option("--watch, -w [type:boolean]", "Watch for changes and rebuild", {
|
.option("--watch, -w [type:boolean]", "Watch for changes and rebuild", {
|
||||||
@ -78,14 +78,15 @@ await new Command()
|
|||||||
// plug:run
|
// plug:run
|
||||||
.command("plug:run", "Run a PlugOS function from the CLI")
|
.command("plug:run", "Run a PlugOS function from the CLI")
|
||||||
.arguments("<spacePath> [function] [...args:string]")
|
.arguments("<spacePath> [function] [...args:string]")
|
||||||
.option("--noIndex [type:boolean]", "Do not run a full space index first", {
|
|
||||||
default: false,
|
|
||||||
})
|
|
||||||
.option(
|
.option(
|
||||||
"--hostname, -L <hostname:string>",
|
"--hostname, -L <hostname:string>",
|
||||||
"Hostname or address to listen on",
|
"Hostname or address to listen on",
|
||||||
)
|
)
|
||||||
.option("-p, --port <port:number>", "Port to listen on")
|
.option("-p, --port <port:number>", "Port to listen on")
|
||||||
|
.option(
|
||||||
|
"--db <db:string>",
|
||||||
|
"Path to database file",
|
||||||
|
)
|
||||||
.action(plugRunCommand)
|
.action(plugRunCommand)
|
||||||
.command("user:add", "Add a new user to an authentication file")
|
.command("user:add", "Add a new user to an authentication file")
|
||||||
.arguments("[username:string]")
|
.arguments("[username:string]")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { safeRun } from "../common/util.ts";
|
import { safeRun } from "../common/util.ts";
|
||||||
import { Client } from "./client.ts";
|
import { Client } from "./client.ts";
|
||||||
|
|
||||||
const syncMode = window.silverBulletConfig.supportOnlineMode !== "true" ||
|
const syncMode = window.silverBulletConfig.syncOnly ||
|
||||||
!!localStorage.getItem("syncMode");
|
!!localStorage.getItem("syncMode");
|
||||||
|
|
||||||
safeRun(async () => {
|
safeRun(async () => {
|
||||||
|
@ -52,7 +52,7 @@ declare global {
|
|||||||
// Injected via index.html
|
// Injected via index.html
|
||||||
silverBulletConfig: {
|
silverBulletConfig: {
|
||||||
spaceFolderPath: string;
|
spaceFolderPath: string;
|
||||||
supportOnlineMode: string;
|
syncOnly: boolean;
|
||||||
};
|
};
|
||||||
client: Client;
|
client: Client;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,6 @@ export function TopBar({
|
|||||||
lhs?: ComponentChildren;
|
lhs?: ComponentChildren;
|
||||||
rhs?: ComponentChildren;
|
rhs?: ComponentChildren;
|
||||||
}) {
|
}) {
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
|
||||||
|
|
||||||
// Another one of my less proud moments:
|
// Another one of my less proud moments:
|
||||||
// Somehow I cannot seem to proerply limit the width of the page name, so I'm doing
|
// Somehow I cannot seem to proerply limit the width of the page name, so I'm doing
|
||||||
// it this way. If you have a better way to do this, please let me know!
|
// it this way. If you have a better way to do this, please let me know!
|
||||||
@ -66,7 +64,7 @@ export function TopBar({
|
|||||||
|
|
||||||
// Then calculate a new width
|
// Then calculate a new width
|
||||||
currentPageElement.style.width = `${
|
currentPageElement.style.width = `${
|
||||||
Math.min(editorWidth - 150, innerDiv.clientWidth - 150)
|
Math.min(editorWidth - 170, innerDiv.clientWidth - 170)
|
||||||
}px`;
|
}px`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +204,8 @@ export class MainUI {
|
|||||||
editor.focus();
|
editor.focus();
|
||||||
}}
|
}}
|
||||||
actionButtons={[
|
actionButtons={[
|
||||||
...window.silverBulletConfig.supportOnlineMode === "true"
|
...!window.silverBulletConfig.syncOnly
|
||||||
|
// If we support syncOnly, don't show this toggle button
|
||||||
? [{
|
? [{
|
||||||
icon: RefreshCwIcon,
|
icon: RefreshCwIcon,
|
||||||
description: this.editor.syncMode
|
description: this.editor.syncMode
|
||||||
|
@ -35,13 +35,13 @@
|
|||||||
window.silverBulletConfig = {
|
window.silverBulletConfig = {
|
||||||
// These {{VARIABLES}} are replaced by http_server.ts
|
// These {{VARIABLES}} are replaced by http_server.ts
|
||||||
spaceFolderPath: "{{SPACE_PATH}}",
|
spaceFolderPath: "{{SPACE_PATH}}",
|
||||||
supportOnlineMode: "{{SUPPORT_ONLINE_MODE}}",
|
syncOnly: "{{SYNC_ONLY}}" === "true",
|
||||||
};
|
};
|
||||||
// But in case these variables aren't replaced by the server, fall back fully static mode (no sync)
|
// But in case these variables aren't replaced by the server, fall back sync only mode
|
||||||
if (window.silverBulletConfig.spaceFolderPath.includes("{{")) {
|
if (window.silverBulletConfig.spaceFolderPath.includes("{{")) {
|
||||||
window.silverBulletConfig = {
|
window.silverBulletConfig = {
|
||||||
spaceFolderPath: "",
|
spaceFolderPath: "",
|
||||||
supportOnlineMode: false,
|
syncOnly: true,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -121,7 +121,9 @@ body {
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: -6px;
|
top: -6px;
|
||||||
padding-right: 6px;
|
padding: 4px;
|
||||||
|
background-color: var(--top-background-color);
|
||||||
|
margin-right: -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.progress-bar {
|
.progress-bar {
|
||||||
|
@ -130,6 +130,7 @@ You can configure SB with environment variables instead of flags as well. The fo
|
|||||||
* `SB_PORT`: Sets the port to listen to, e.g. `SB_PORT=1234`
|
* `SB_PORT`: Sets the port to listen to, e.g. `SB_PORT=1234`
|
||||||
* `SB_FOLDER`: Sets the folder to expose, e.g. `SB_FOLDER=/space`
|
* `SB_FOLDER`: Sets the folder to expose, e.g. `SB_FOLDER=/space`
|
||||||
* `SB_AUTH`: Loads an [[Authentication]] database from a (JSON encoded) string, e.g. `SB_AUTH=$(cat /path/to/.auth.json)`
|
* `SB_AUTH`: Loads an [[Authentication]] database from a (JSON encoded) string, e.g. `SB_AUTH=$(cat /path/to/.auth.json)`
|
||||||
|
* `SB_STORE_ONLY`: Runs the server in a "dumb" space store only mode (not indexing content or keeping other state), e.g. `SB_STORE_ONLY=1`
|
||||||
|
|
||||||
## Using Authelia
|
## Using Authelia
|
||||||
You need to adjust a few configuration options in [[Authelia]] in order for SilverBullet to work as intended.
|
You need to adjust a few configuration options in [[Authelia]] in order for SilverBullet to work as intended.
|
||||||
|
Loading…
Reference in New Issue
Block a user