dsh-tiddlywiki 0.5.0 → 0.6.0
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 +22 -5
- package/lib/client.bundle.js +5 -3
- package/lib/client.js +5 -3
- package/lib/index.js +133 -3
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/note-widget.ts +5 -1
- package/src/client/panel.ts +20 -6
- package/src/host/routes.ts +80 -8
- package/src/host/wiki.ts +12 -0
- package/src/index.ts +34 -2
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
| 能力 | 说明 |
|
|
16
16
|
|---|---|
|
|
17
17
|
| 🤖 **Agent 工具** | `tiddlywiki_search` / `get` / `put` / `batch_put` / `rename` / `delete` / `recent` / `list_tags` / `git_sync` / `git_resolve` 十个工具:检索、读写、批量、重命名、删除、git 同步与冲突解决 |
|
|
18
|
-
| 🧭 **内嵌编辑器** | 侧边栏「TiddlyWiki」入口 → 中央列内嵌完整 TW 5
|
|
18
|
+
| 🧭 **内嵌编辑器** | 侧边栏「TiddlyWiki」入口 → 中央列内嵌完整 TW 5 编辑器(**同源代理**,经 DSH origin 访问,Tailscale/内网/域名/HTTPS 均可用) |
|
|
19
19
|
| 📝 **快速笔记** | 右下角「知识库」悬浮按钮 → 快速笔记卡片:**CodeMirror 6** Markdown 编辑器(语法高亮 + 撤销/重做)、文件上传、多选/自动补全 tag、**草稿自动保存(刷新不丢)**、**「🕘 最近」一键载入旧笔记**,Ctrl+Enter 保存;可整体隐藏 |
|
|
20
20
|
| 🔄 **一键同步** | 「知识库」按钮 →「🔁 同步」:pull → commit → push;FAB 上的状态点实时反映 git 状态(已同步/待提交/可更新/离线) |
|
|
21
21
|
| ⚙️ **设置页** | DSH 设置 →「TiddlyWiki 知识库」:插件/主题/语言管理与运行配置,应用后自动重启 TW |
|
|
@@ -86,13 +86,13 @@ dsh plugin --profile web add link:/path/to/your/dsh-tiddlywiki
|
|
|
86
86
|
|
|
87
87
|
### 🧑💻 给人:界面操作
|
|
88
88
|
|
|
89
|
-
**🧭 中央列编辑器** — 侧边栏「TiddlyWiki
|
|
89
|
+
**🧭 中央列编辑器** — 侧边栏「TiddlyWiki」按钮开关中央编辑器面板(**同源代理**:iframe 指向 `<DSH origin>/dsh-tiddlywiki/tw/`,由 DSH 转发到回环上的 TW 服务),完整 TW 5 编辑器。
|
|
90
90
|
|
|
91
91
|
**📝 快速笔记** — 右下角「**知识库**」悬浮按钮 →「📝 快速笔记」(可折叠):
|
|
92
92
|
- **CodeMirror 6 编辑器**:真正的 Markdown 语法树高亮(标题/列表/代码/链接/表格/任务清单/删除线等,GFM),支持撤销/重做与行内编辑体验;
|
|
93
93
|
- **草稿自动保存**:正文/标题/标签 500ms 防抖写入本地,关掉卡片或刷新页面都不丢;重开自动恢复,可一键「丢弃」;
|
|
94
94
|
- **🕘 最近**:一键列出最近修改的笔记,点标题直接载入编辑器继续改(不需要开完整 TW 去找);
|
|
95
|
-
- **文件上传**:点「📎 上传」或直接把文件拖进编辑器——文件存到 wiki 的 `files/` 文件夹并随 git 同步;图片插入 ``、其它文件插入 `[名](/files/名)
|
|
95
|
+
- **文件上传**:点「📎 上传」或直接把文件拖进编辑器——文件存到 wiki 的 `files/` 文件夹并随 git 同步;图片插入 ``、其它文件插入 `[名](/dsh-tiddlywiki/tw/files/名)`(**同源代理 URL**,在 TW 与快速笔记预览里都能打开);
|
|
96
96
|
- **Ctrl+Enter 保存**为独立 tiddler;笔记 `type` 自动设为 `text/markdown`,所以上传的图片/链接在 TW 里按 Markdown 正常渲染;
|
|
97
97
|
- 点「**✏️ 在 TW 中编辑**」→ 保存后弹出**独立小窗**(可拖动/缩放)加载 TW 原生编辑器编辑该条。
|
|
98
98
|
|
|
@@ -134,6 +134,20 @@ TW 的界面语言由**语言插件**决定,不是某个配置字符串。tidd
|
|
|
134
134
|
- **配置自动应用**:在常规配置写入 `uiLanguage: "zh-Hans"`,每次启动 dsh web 时自动启用该语言并固定 `$:/language`(若尚未启用)。留空则不干预。
|
|
135
135
|
- **想换繁中**:语言管理里改勾 `zh-Hant` / `zh-TW` 再应用。
|
|
136
136
|
|
|
137
|
+
### 🌐 远程访问(Tailscale / 内网 / 域名 / HTTPS)
|
|
138
|
+
|
|
139
|
+
TW 子进程只监听 **127.0.0.1 回环**(更安全),**agent 工具、快速笔记、git 同步本来就全程走 DSH 宿主进程→回环 TW**,所以无论你从哪个入口访问 DSH,这些能力都不受影响。唯一受影响的是**浏览器里的 TW 编辑器 iframe**:早期版本让 iframe 直接指向 `http://127.0.0.1:<port>`——只有浏览器和 DSH 在同一台机器时才行;一旦通过 Tailscale / 内网 IP / 域名访问 DSH,`127.0.0.1` 会指向浏览器自己那台机器,编辑器就加载不出来了。
|
|
140
|
+
|
|
141
|
+
从 **v0.6.0** 起,内嵌编辑器改为**同源代理**:
|
|
142
|
+
|
|
143
|
+
- 浏览器里的 TW 编辑器 iframe 指向 `<DSH origin>/dsh-tiddlywiki/tw/`(与 DSH 同源),DSH 把整个 TW 前端(页面 + `/files/*` + TiddlyWeb API)透传到回环上的 TW 服务;
|
|
144
|
+
- TW 前端的 API 基址由 wiki 内的 `$:/config/tiddlyweb/host` 控制,插件启动时把它固定为 `/dsh-tiddlywiki/tw/`(仅当缺失或仍是旧默认值时写入,用户自定义会被保留);
|
|
145
|
+
- 因为代理 URL 与端口无关,TW 重启也不会让编辑器 iframe 重新加载,编辑中的内容不丢。
|
|
146
|
+
|
|
147
|
+
效果:**DSH 跑在服务器上、你用 Tailscale / 域名 / 内网 IP 从任意设备打开 DSH Web 时,中央列编辑器和「在 TW 中编辑」弹窗都正常工作**;以后 DSH 挂到域名 + HTTPS 反向代理后面也同样成立(同源、无 mixed-content、无 CORS)。
|
|
148
|
+
|
|
149
|
+
> ⚠️ 迁移说明:v0.6.0 之前上传的文件在笔记里写的是根路径 `/files/名`,本插件**不再**占用 DSH 根命名空间(避免与其他插件冲突),所以这些旧链接在嵌入编辑器里会失效;新上传的文件使用 `/dsh-tiddlywiki/tw/files/名` 前缀 URL,可直接打开。若需要旧链接,可在 TW 里把对应笔记的 `/files/` 前缀改回 `/dsh-tiddlywiki/tw/files/`。
|
|
150
|
+
|
|
137
151
|
---
|
|
138
152
|
|
|
139
153
|
## 🔄 同步与数据
|
|
@@ -174,6 +188,8 @@ TW 的界面语言由**语言插件**决定,不是某个配置字符串。tidd
|
|
|
174
188
|
|
|
175
189
|
> **运行时配置**:设置页写入的 `$:/plugins/dsh-tiddlywiki/config` tiddler 是 `config:` 块之上的覆盖层(tiddler 优先、随 wiki 的 git 同步)。无需改动 cordis 也能改 note tag / git 开关 / ui 开关等。
|
|
176
190
|
> `config:` 块随 profile 被 dsh-market 带走;wiki 数据走 git,不走 dsh-market。
|
|
191
|
+
>
|
|
192
|
+
> **远程访问(v0.6.0)**:TW 前端的 API 基址来自 `$:/config/tiddlyweb/host`,插件启动时固定为 `/dsh-tiddlywiki/tw/`(同源代理)。TW 子进程始终只监听 `127.0.0.1`;`auth.username/password` 仅在你想把 TW 直接暴露到非回环地址(绕过 DSH)时才需要,正常情况下无需配置。
|
|
177
193
|
|
|
178
194
|
---
|
|
179
195
|
|
|
@@ -208,6 +224,7 @@ npm run selftest # headless:spawn TW → REST 读写 → git → 退出
|
|
|
208
224
|
| `/dsh-tiddlywiki/upload` | POST | 文件上传到 `files/`(原始 body + `X-Filename`) |
|
|
209
225
|
| `/dsh-tiddlywiki/restart` | POST | 重启 TW 子进程 |
|
|
210
226
|
| `/dsh-tiddlywiki/api/*` | any | 透传到 TW 服务(JSON) |
|
|
227
|
+
| `/dsh-tiddlywiki/tw/*` | any | **同源 TW 代理**:整个 TW 前端(index + `/files/*` + TiddlyWeb API)→ 回环 TW(v0.6.0,远程访问核心) |
|
|
211
228
|
|
|
212
229
|
---
|
|
213
230
|
|
|
@@ -229,10 +246,10 @@ src/
|
|
|
229
246
|
├── index.ts # host 入口:装配 WikiServer/路由/工具/prompt/自动 commit
|
|
230
247
|
├── sdk.ts # 自包含 defineTool + dshHomePath(零 @deepseek-ai 运行时依赖)
|
|
231
248
|
├── host/
|
|
232
|
-
│ ├── wiki.ts # WikiServer:spawn/kill
|
|
249
|
+
│ ├── wiki.ts # WikiServer:spawn/kill/自愈/端口探测/就绪轮询;TW_PROXY_PATH 同源代理路径
|
|
233
250
|
│ ├── tw-api.ts # TiddlyWeb REST 客户端
|
|
234
251
|
│ ├── git.ts # git init/commit/pull/push/sync/status + AutoCommitter
|
|
235
|
-
│ ├── routes.ts # /status /note /edit /tags /sync /upload /restart /api/* 路由
|
|
252
|
+
│ ├── routes.ts # /status /note /edit /tags /sync /upload /restart /api/* /tw/* 路由
|
|
236
253
|
│ ├── admin.ts # 设置页后台:tiddlywiki.info 读写 + 目录枚举 + /admin/* 路由
|
|
237
254
|
│ ├── config.ts # ConfigStore:cordis config 基底 + 配置 tiddler 覆盖层
|
|
238
255
|
│ ├── seed-notes.ts # 首次启动一次性写入「插件说明」笔记
|
package/lib/client.bundle.js
CHANGED
|
@@ -827,9 +827,11 @@ function mountPanel(state) {
|
|
|
827
827
|
showError("无法访问 /dsh-tiddlywiki/status");
|
|
828
828
|
return;
|
|
829
829
|
}
|
|
830
|
-
if (payload.status === "running"
|
|
830
|
+
if (payload.status === "running") {
|
|
831
831
|
refreshAttempts = 0;
|
|
832
|
-
showFrame(payload.
|
|
832
|
+
if (typeof payload.twProxy === "string") showFrame(new URL(payload.twProxy, window.location.origin).href);
|
|
833
|
+
else if (typeof payload.url === "string") showFrame(payload.url);
|
|
834
|
+
else showError("服务未返回编辑器地址");
|
|
833
835
|
return;
|
|
834
836
|
}
|
|
835
837
|
if (payload.status === "starting") {
|
|
@@ -27088,7 +27090,7 @@ function createNoteWidget() {
|
|
|
27088
27090
|
}
|
|
27089
27091
|
clearDraft();
|
|
27090
27092
|
hideDraftBanner();
|
|
27091
|
-
openEditorPopup(`${payload.twUrl}#${encodeURIComponent(payload.draftTitle)}`, payload.title ?? title);
|
|
27093
|
+
openEditorPopup(`${new URL(payload.twUrl, location.origin).href}#${encodeURIComponent(payload.draftTitle)}`, payload.title ?? title);
|
|
27092
27094
|
toast(`已在弹出窗口打开「${payload.title ?? title}」编辑器`);
|
|
27093
27095
|
} catch (err) {
|
|
27094
27096
|
toast(`打开失败:${err instanceof Error ? err.message : String(err)}`);
|
package/lib/client.js
CHANGED
|
@@ -833,9 +833,11 @@ function mountPanel(state) {
|
|
|
833
833
|
showError("无法访问 /dsh-tiddlywiki/status");
|
|
834
834
|
return;
|
|
835
835
|
}
|
|
836
|
-
if (payload.status === "running"
|
|
836
|
+
if (payload.status === "running") {
|
|
837
837
|
refreshAttempts = 0;
|
|
838
|
-
showFrame(payload.
|
|
838
|
+
if (typeof payload.twProxy === "string") showFrame(new URL(payload.twProxy, window.location.origin).href);
|
|
839
|
+
else if (typeof payload.url === "string") showFrame(payload.url);
|
|
840
|
+
else showError("服务未返回编辑器地址");
|
|
839
841
|
return;
|
|
840
842
|
}
|
|
841
843
|
if (payload.status === "starting") {
|
|
@@ -27094,7 +27096,7 @@ function createNoteWidget() {
|
|
|
27094
27096
|
}
|
|
27095
27097
|
clearDraft();
|
|
27096
27098
|
hideDraftBanner();
|
|
27097
|
-
openEditorPopup(`${payload.twUrl}#${encodeURIComponent(payload.draftTitle)}`, payload.title ?? title);
|
|
27099
|
+
openEditorPopup(`${new URL(payload.twUrl, location.origin).href}#${encodeURIComponent(payload.draftTitle)}`, payload.title ?? title);
|
|
27098
27100
|
toast(`已在弹出窗口打开「${payload.title ?? title}」编辑器`);
|
|
27099
27101
|
} catch (err) {
|
|
27100
27102
|
toast(`打开失败:${err instanceof Error ? err.message : String(err)}`);
|
package/lib/index.js
CHANGED
|
@@ -451,6 +451,16 @@ var AutoCommitter = class {
|
|
|
451
451
|
*/
|
|
452
452
|
/** The DSH webserver route prefix (NOT a TW path-prefix; see module header). */
|
|
453
453
|
const PATH_PREFIX = "/dsh-tiddlywiki";
|
|
454
|
+
/**
|
|
455
|
+
* Same-origin TW proxy route on the DSH webserver (remote-access mode, R1).
|
|
456
|
+
* The browser only ever talks to the DSH origin — which it already reaches
|
|
457
|
+
* over loopback, LAN, Tailscale, a domain or HTTPS — and DSH proxies to the
|
|
458
|
+
* loopback TW child. TW's frontend is pointed at this prefix via the
|
|
459
|
+
* `$:/config/tiddlyweb/host` tiddler so every API call stays same-origin.
|
|
460
|
+
*/
|
|
461
|
+
const TW_PROXY_PREFIX = `${PATH_PREFIX}/tw`;
|
|
462
|
+
/** The proxy base path (trailing slash) handed to browsers / TW's frontend. */
|
|
463
|
+
const TW_PROXY_PATH = `${TW_PROXY_PREFIX}/`;
|
|
454
464
|
/** How long to wait for the wiki to answer /status. */
|
|
455
465
|
const READY_TIMEOUT_MS = 2e4;
|
|
456
466
|
/** Poll cadence while waiting for readiness. */
|
|
@@ -720,6 +730,29 @@ function readBodyBuffer(req, limit = MAX_UPLOAD_BYTES) {
|
|
|
720
730
|
req.on("error", rejectP);
|
|
721
731
|
});
|
|
722
732
|
}
|
|
733
|
+
/** Header names forwarded to the upstream TW service by the proxy routes. */
|
|
734
|
+
const FORWARD_HEADER_NAMES = [
|
|
735
|
+
"accept",
|
|
736
|
+
"accept-encoding",
|
|
737
|
+
"content-type",
|
|
738
|
+
"cookie",
|
|
739
|
+
"authorization",
|
|
740
|
+
"if-none-match",
|
|
741
|
+
"if-modified-since",
|
|
742
|
+
"origin",
|
|
743
|
+
"referer",
|
|
744
|
+
"user-agent"
|
|
745
|
+
];
|
|
746
|
+
/** Copy a safe, string-valued subset of the request headers upstream. */
|
|
747
|
+
function forwardHeaders(headers) {
|
|
748
|
+
const out = {};
|
|
749
|
+
for (const name of FORWARD_HEADER_NAMES) {
|
|
750
|
+
const value = headers[name];
|
|
751
|
+
if (typeof value === "string") out[name] = value;
|
|
752
|
+
else if (Array.isArray(value) && value.length > 0) out[name] = value.join(", ");
|
|
753
|
+
}
|
|
754
|
+
return out;
|
|
755
|
+
}
|
|
723
756
|
/**
|
|
724
757
|
* Sanitize an uploaded filename into a safe bare name (no path separators,
|
|
725
758
|
* no `..`, no control characters). Returns '' when nothing usable remains.
|
|
@@ -813,6 +846,7 @@ function registerRoutes(ctx, deps) {
|
|
|
813
846
|
json$1(res, {
|
|
814
847
|
ok: true,
|
|
815
848
|
...view,
|
|
849
|
+
twProxy: TW_PROXY_PATH,
|
|
816
850
|
git: gitSummary,
|
|
817
851
|
note: { tag: deps.noteDefaults().tag },
|
|
818
852
|
ui: deps.uiDefaults()
|
|
@@ -879,7 +913,7 @@ function registerRoutes(ctx, deps) {
|
|
|
879
913
|
json$1(res, {
|
|
880
914
|
ok: true,
|
|
881
915
|
...result,
|
|
882
|
-
twUrl:
|
|
916
|
+
twUrl: TW_PROXY_PATH
|
|
883
917
|
});
|
|
884
918
|
} catch (err) {
|
|
885
919
|
json$1(res, {
|
|
@@ -1109,7 +1143,7 @@ function registerRoutes(ctx, deps) {
|
|
|
1109
1143
|
ok: true,
|
|
1110
1144
|
name: candidate,
|
|
1111
1145
|
path: `files/${candidate}`,
|
|
1112
|
-
url:
|
|
1146
|
+
url: `${TW_PROXY_PATH}files/${encodeURIComponent(candidate)}`,
|
|
1113
1147
|
size: buf.length,
|
|
1114
1148
|
type: req.headers["content-type"] ?? "application/octet-stream"
|
|
1115
1149
|
});
|
|
@@ -1157,6 +1191,62 @@ function registerRoutes(ctx, deps) {
|
|
|
1157
1191
|
}, 502);
|
|
1158
1192
|
}
|
|
1159
1193
|
};
|
|
1194
|
+
/**
|
|
1195
|
+
* SAME-ORIGIN proxy /dsh-tiddlywiki/tw/<rest> → TW root /<rest>. Serves the
|
|
1196
|
+
* ENTIRE TW frontend (index HTML, /files/*, the TiddlyWeb API) to the
|
|
1197
|
+
* browser through the DSH origin, so the embedded editor works from any
|
|
1198
|
+
* host/domain the user reaches DSH on (loopback, LAN, Tailscale, domain,
|
|
1199
|
+
* HTTPS). The browser never talks to the loopback TW child directly; DSH
|
|
1200
|
+
* does, on the same machine. Binary responses are buffered losslessly
|
|
1201
|
+
* (arrayBuffer) — unlike the /api JSON proxy, this route must never .text().
|
|
1202
|
+
*/
|
|
1203
|
+
const handleTwProxy = async (req, res) => {
|
|
1204
|
+
if (deps.getClient() === void 0) {
|
|
1205
|
+
json$1(res, {
|
|
1206
|
+
ok: false,
|
|
1207
|
+
error: "wiki service is not running"
|
|
1208
|
+
}, 503);
|
|
1209
|
+
return;
|
|
1210
|
+
}
|
|
1211
|
+
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
1212
|
+
const rest = url.pathname.replace(new RegExp(`^${TW_PROXY_PREFIX}(?=/|$)`), "") || "/";
|
|
1213
|
+
try {
|
|
1214
|
+
const method = (req.method ?? "GET").toUpperCase();
|
|
1215
|
+
const headers = forwardHeaders(req.headers);
|
|
1216
|
+
if (method === "PUT" || method === "DELETE" || method === "POST") headers["x-requested-with"] = "TiddlyWiki";
|
|
1217
|
+
const init = {
|
|
1218
|
+
method,
|
|
1219
|
+
headers,
|
|
1220
|
+
signal: AbortSignal.timeout(3e4)
|
|
1221
|
+
};
|
|
1222
|
+
if (method === "PUT" || method === "POST") init.body = await readBodyBuffer(req, MAX_UPLOAD_BYTES);
|
|
1223
|
+
const upstream = await fetch(`${deps.server.url}${rest}${url.search}`, init);
|
|
1224
|
+
const data = Buffer.from(await upstream.arrayBuffer());
|
|
1225
|
+
const responseHeaders = {
|
|
1226
|
+
"content-type": upstream.headers.get("content-type") ?? "application/octet-stream",
|
|
1227
|
+
"cache-control": upstream.headers.get("cache-control") ?? "no-store"
|
|
1228
|
+
};
|
|
1229
|
+
for (const name of [
|
|
1230
|
+
"etag",
|
|
1231
|
+
"last-modified",
|
|
1232
|
+
"content-disposition"
|
|
1233
|
+
]) {
|
|
1234
|
+
const value = upstream.headers.get(name);
|
|
1235
|
+
if (value !== null) responseHeaders[name] = value;
|
|
1236
|
+
}
|
|
1237
|
+
res.writeHead(upstream.status, responseHeaders);
|
|
1238
|
+
res.end(data);
|
|
1239
|
+
} catch (err) {
|
|
1240
|
+
if (res.headersSent) {
|
|
1241
|
+
res.end();
|
|
1242
|
+
return;
|
|
1243
|
+
}
|
|
1244
|
+
json$1(res, {
|
|
1245
|
+
ok: false,
|
|
1246
|
+
error: err instanceof Error ? err.message : String(err)
|
|
1247
|
+
}, 502);
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1160
1250
|
const disposers = [
|
|
1161
1251
|
ctx.webServer.register({
|
|
1162
1252
|
kind: "exact",
|
|
@@ -1227,6 +1317,13 @@ function registerRoutes(ctx, deps) {
|
|
|
1227
1317
|
handler: (req, res) => {
|
|
1228
1318
|
handleApiProxy(req, res);
|
|
1229
1319
|
}
|
|
1320
|
+
}),
|
|
1321
|
+
ctx.webServer.register({
|
|
1322
|
+
kind: "prefix",
|
|
1323
|
+
path: `${TW_PROXY_PREFIX}`,
|
|
1324
|
+
handler: (req, res) => {
|
|
1325
|
+
handleTwProxy(req, res);
|
|
1326
|
+
}
|
|
1230
1327
|
})
|
|
1231
1328
|
];
|
|
1232
1329
|
return () => {
|
|
@@ -2834,6 +2931,34 @@ const DEFAULTS = {
|
|
|
2834
2931
|
password: ""
|
|
2835
2932
|
}
|
|
2836
2933
|
};
|
|
2934
|
+
/** Config tiddler steering TW's frontend API base (tiddlywebadaptor). */
|
|
2935
|
+
const TW_WEB_HOST_TIDDLER = "$:/config/tiddlyweb/host";
|
|
2936
|
+
/** The legacy default value this plugin replaces with the same-origin proxy. */
|
|
2937
|
+
const TW_WEB_HOST_DEFAULT = "$protocol$//$host$/";
|
|
2938
|
+
/**
|
|
2939
|
+
* Point TW's frontend at the same-origin DSH proxy (remote-access mode, R1).
|
|
2940
|
+
* The tiddlywebadaptor builds every API URL from $:/config/tiddlyweb/host; its
|
|
2941
|
+
* default `$protocol$//$host$/` resolves to the iframe's origin ROOT, which
|
|
2942
|
+
* 404s whenever the browser is not on the same machine as TW. Written only
|
|
2943
|
+
* when the tiddler is missing or still the legacy default — a user override is
|
|
2944
|
+
* honored (e.g. someone who really does expose TW on a dedicated origin).
|
|
2945
|
+
*/
|
|
2946
|
+
async function ensureTwWebHost(client) {
|
|
2947
|
+
if (client === void 0) return;
|
|
2948
|
+
let current;
|
|
2949
|
+
try {
|
|
2950
|
+
current = (await client.get(TW_WEB_HOST_TIDDLER))?.text;
|
|
2951
|
+
} catch {
|
|
2952
|
+
current = void 0;
|
|
2953
|
+
}
|
|
2954
|
+
if (current !== void 0 && current.trim() !== TW_WEB_HOST_DEFAULT) return;
|
|
2955
|
+
await client.put({
|
|
2956
|
+
title: TW_WEB_HOST_TIDDLER,
|
|
2957
|
+
text: TW_PROXY_PATH,
|
|
2958
|
+
type: "text/plain",
|
|
2959
|
+
tags: []
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2837
2962
|
/** Expand $VAR / ${VAR} / %VAR% from process.env (config uses $DSH_HOME). */
|
|
2838
2963
|
function expandEnvPath(input) {
|
|
2839
2964
|
return input.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_, k) => process.env[k] ?? "").replace(/\$([A-Za-z_][A-Za-z0-9_]*)/g, (_, k) => process.env[k] ?? "").replace(/%([A-Za-z_][A-Za-z0-9_]*%)/g, (_, k) => process.env[k.slice(0, -1)] ?? "");
|
|
@@ -3006,6 +3131,11 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3006
3131
|
try {
|
|
3007
3132
|
await server.start();
|
|
3008
3133
|
await configStore.load(client());
|
|
3134
|
+
try {
|
|
3135
|
+
await ensureTwWebHost(client());
|
|
3136
|
+
} catch (err) {
|
|
3137
|
+
console.warn("[dsh-tiddlywiki] ensuring $:/config/tiddlyweb/host:", err);
|
|
3138
|
+
}
|
|
3009
3139
|
try {
|
|
3010
3140
|
const seedClient = client();
|
|
3011
3141
|
if (seedClient !== void 0) await seedDocNote(seedClient);
|
|
@@ -3066,6 +3196,6 @@ function apply(ctx, rawConfig = {}) {
|
|
|
3066
3196
|
}, "dsh-tiddlywiki: host teardown");
|
|
3067
3197
|
}
|
|
3068
3198
|
//#endregion
|
|
3069
|
-
export { AutoCommitter, ConfigStore, DOC_NOTE_TAG, DOC_NOTE_TEXT, DOC_NOTE_TITLE, GitFace, PATH_PREFIX, TiddlyWebClient, WikiServer, apply, bundledCatalog, deepMerge, defineTool, dshHomePath, ensureLanguage, inject, name, normalizeThemes, openInTwEditor, readWikiInfo, registerAdminRoutes, registerRoutes, resolveTwRoot, seedDocNote, writeWikiInfo };
|
|
3199
|
+
export { AutoCommitter, ConfigStore, DOC_NOTE_TAG, DOC_NOTE_TEXT, DOC_NOTE_TITLE, GitFace, PATH_PREFIX, TW_PROXY_PATH, TW_PROXY_PREFIX, TW_WEB_HOST_TIDDLER, TiddlyWebClient, WikiServer, apply, bundledCatalog, deepMerge, defineTool, dshHomePath, ensureLanguage, ensureTwWebHost, inject, name, normalizeThemes, openInTwEditor, readWikiInfo, registerAdminRoutes, registerRoutes, resolveTwRoot, seedDocNote, writeWikiInfo };
|
|
3070
3200
|
|
|
3071
3201
|
//# sourceMappingURL=index.js.map
|