@deskwork/studio 0.9.5
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/dist/build-client-assets.d.ts +51 -0
- package/dist/build-client-assets.d.ts.map +1 -0
- package/dist/build-client-assets.js +341 -0
- package/dist/build-client-assets.js.map +1 -0
- package/dist/components/scrapbook-item.d.ts +108 -0
- package/dist/components/scrapbook-item.d.ts.map +1 -0
- package/dist/components/scrapbook-item.js +205 -0
- package/dist/components/scrapbook-item.js.map +1 -0
- package/dist/lib/editorial-skills-catalogue.d.ts +33 -0
- package/dist/lib/editorial-skills-catalogue.d.ts.map +1 -0
- package/dist/lib/editorial-skills-catalogue.js +211 -0
- package/dist/lib/editorial-skills-catalogue.js.map +1 -0
- package/dist/lib/override-render.d.ts +41 -0
- package/dist/lib/override-render.d.ts.map +1 -0
- package/dist/lib/override-render.js +80 -0
- package/dist/lib/override-render.js.map +1 -0
- package/dist/listen.d.ts +78 -0
- package/dist/listen.d.ts.map +1 -0
- package/dist/listen.js +155 -0
- package/dist/listen.js.map +1 -0
- package/dist/pages/chrome.d.ts +26 -0
- package/dist/pages/chrome.d.ts.map +1 -0
- package/dist/pages/chrome.js +50 -0
- package/dist/pages/chrome.js.map +1 -0
- package/dist/pages/content-detail.d.ts +14 -0
- package/dist/pages/content-detail.d.ts.map +1 -0
- package/dist/pages/content-detail.js +279 -0
- package/dist/pages/content-detail.js.map +1 -0
- package/dist/pages/content.d.ts +39 -0
- package/dist/pages/content.d.ts.map +1 -0
- package/dist/pages/content.js +414 -0
- package/dist/pages/content.js.map +1 -0
- package/dist/pages/dashboard.d.ts +32 -0
- package/dist/pages/dashboard.d.ts.map +1 -0
- package/dist/pages/dashboard.js +803 -0
- package/dist/pages/dashboard.js.map +1 -0
- package/dist/pages/help.d.ts +24 -0
- package/dist/pages/help.d.ts.map +1 -0
- package/dist/pages/help.js +433 -0
- package/dist/pages/help.js.map +1 -0
- package/dist/pages/html.d.ts +35 -0
- package/dist/pages/html.d.ts.map +1 -0
- package/dist/pages/html.js +73 -0
- package/dist/pages/html.js.map +1 -0
- package/dist/pages/index.d.ts +21 -0
- package/dist/pages/index.d.ts.map +1 -0
- package/dist/pages/index.js +174 -0
- package/dist/pages/index.js.map +1 -0
- package/dist/pages/layout.d.ts +33 -0
- package/dist/pages/layout.d.ts.map +1 -0
- package/dist/pages/layout.js +50 -0
- package/dist/pages/layout.js.map +1 -0
- package/dist/pages/review-scrapbook-drawer.d.ts +20 -0
- package/dist/pages/review-scrapbook-drawer.d.ts.map +1 -0
- package/dist/pages/review-scrapbook-drawer.js +98 -0
- package/dist/pages/review-scrapbook-drawer.js.map +1 -0
- package/dist/pages/review.d.ts +68 -0
- package/dist/pages/review.d.ts.map +1 -0
- package/dist/pages/review.js +434 -0
- package/dist/pages/review.js.map +1 -0
- package/dist/pages/scrapbook.d.ts +21 -0
- package/dist/pages/scrapbook.d.ts.map +1 -0
- package/dist/pages/scrapbook.js +250 -0
- package/dist/pages/scrapbook.js.map +1 -0
- package/dist/pages/shortform.d.ts +17 -0
- package/dist/pages/shortform.d.ts.map +1 -0
- package/dist/pages/shortform.js +142 -0
- package/dist/pages/shortform.js.map +1 -0
- package/dist/request-context.d.ts +52 -0
- package/dist/request-context.d.ts.map +1 -0
- package/dist/request-context.js +84 -0
- package/dist/request-context.js.map +1 -0
- package/dist/routes/api.d.ts +36 -0
- package/dist/routes/api.d.ts.map +1 -0
- package/dist/routes/api.js +175 -0
- package/dist/routes/api.js.map +1 -0
- package/dist/routes/scrapbook-file.d.ts +19 -0
- package/dist/routes/scrapbook-file.d.ts.map +1 -0
- package/dist/routes/scrapbook-file.js +77 -0
- package/dist/routes/scrapbook-file.js.map +1 -0
- package/dist/routes/scrapbook-mutations.d.ts +33 -0
- package/dist/routes/scrapbook-mutations.d.ts.map +1 -0
- package/dist/routes/scrapbook-mutations.js +310 -0
- package/dist/routes/scrapbook-mutations.js.map +1 -0
- package/dist/server.d.ts +52 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +581 -0
- package/dist/server.js.map +1 -0
- package/dist/tailscale.d.ts +63 -0
- package/dist/tailscale.d.ts.map +1 -0
- package/dist/tailscale.js +118 -0
- package/dist/tailscale.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrapbook-mutations.js","sourceRoot":"","sources":["../../src/routes/scrapbook-mutations.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @deskwork/studio — local web server for the editorial review surface.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* deskwork-studio [--project-root <path>] [--port <n>] [--host <addr>]
|
|
7
|
+
*
|
|
8
|
+
* Defaults:
|
|
9
|
+
* --project-root process.cwd()
|
|
10
|
+
* --port 47321 (avoids the Astro dev server's default 4321)
|
|
11
|
+
* --host 127.0.0.1 (loopback only — see security note in main())
|
|
12
|
+
*
|
|
13
|
+
* The server reads .deskwork/config.json from the project root, then
|
|
14
|
+
* exposes:
|
|
15
|
+
* - GET /dev/editorial-studio — dashboard
|
|
16
|
+
* - GET /dev/editorial-review/<slug> — per-post review page
|
|
17
|
+
* - GET /dev/editorial-review-shortform — shortform review
|
|
18
|
+
* - POST /api/dev/editorial-review/* — 6 mutation endpoints
|
|
19
|
+
* - GET /api/dev/editorial-review/* — 2 read endpoints
|
|
20
|
+
* - GET /static/* — UI assets (HTML/CSS/JS)
|
|
21
|
+
*
|
|
22
|
+
* The handlers live in @deskwork/core/review/handlers and produce
|
|
23
|
+
* exactly the JSON shapes audiocontrol's Astro routes used to produce.
|
|
24
|
+
* The browser-side client code (ported from
|
|
25
|
+
* audiocontrol/src/shared/editorial-*) speaks to those endpoints
|
|
26
|
+
* unchanged.
|
|
27
|
+
*/
|
|
28
|
+
import { Hono } from 'hono';
|
|
29
|
+
import { type StudioContext } from './routes/api.ts';
|
|
30
|
+
interface CliArgs {
|
|
31
|
+
projectRoot: string;
|
|
32
|
+
port: number;
|
|
33
|
+
/**
|
|
34
|
+
* True when the operator passed `--port` (or `-p`). When true, the
|
|
35
|
+
* listener refuses to auto-increment on EADDRINUSE — the operator
|
|
36
|
+
* asked for a specific port, so failure is surfaced loudly.
|
|
37
|
+
*/
|
|
38
|
+
portExplicit: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Bind address explicitly requested by the operator via --host.
|
|
41
|
+
* `null` means "use the default policy" — bind to loopback AND any
|
|
42
|
+
* detected Tailscale interface (unless `--no-tailscale` was passed,
|
|
43
|
+
* in which case loopback only).
|
|
44
|
+
*/
|
|
45
|
+
hostOverride: string | null;
|
|
46
|
+
/** When true, skip Tailscale auto-detection even if it's running. */
|
|
47
|
+
noTailscale: boolean;
|
|
48
|
+
}
|
|
49
|
+
export declare function parseCliArgs(argv: string[]): CliArgs;
|
|
50
|
+
export declare function createApp(ctx: StudioContext): Hono;
|
|
51
|
+
export {};
|
|
52
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAW5B,OAAO,EAAmB,KAAK,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAsBtE,UAAU,OAAO;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,YAAY,EAAE,OAAO,CAAC;IACtB;;;;;OAKG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,qEAAqE;IACrE,WAAW,EAAE,OAAO,CAAC;CACtB;AAKD,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CA8CpD;AAuJD,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAuOlD"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @deskwork/studio — local web server for the editorial review surface.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* deskwork-studio [--project-root <path>] [--port <n>] [--host <addr>]
|
|
7
|
+
*
|
|
8
|
+
* Defaults:
|
|
9
|
+
* --project-root process.cwd()
|
|
10
|
+
* --port 47321 (avoids the Astro dev server's default 4321)
|
|
11
|
+
* --host 127.0.0.1 (loopback only — see security note in main())
|
|
12
|
+
*
|
|
13
|
+
* The server reads .deskwork/config.json from the project root, then
|
|
14
|
+
* exposes:
|
|
15
|
+
* - GET /dev/editorial-studio — dashboard
|
|
16
|
+
* - GET /dev/editorial-review/<slug> — per-post review page
|
|
17
|
+
* - GET /dev/editorial-review-shortform — shortform review
|
|
18
|
+
* - POST /api/dev/editorial-review/* — 6 mutation endpoints
|
|
19
|
+
* - GET /api/dev/editorial-review/* — 2 read endpoints
|
|
20
|
+
* - GET /static/* — UI assets (HTML/CSS/JS)
|
|
21
|
+
*
|
|
22
|
+
* The handlers live in @deskwork/core/review/handlers and produce
|
|
23
|
+
* exactly the JSON shapes audiocontrol's Astro routes used to produce.
|
|
24
|
+
* The browser-side client code (ported from
|
|
25
|
+
* audiocontrol/src/shared/editorial-*) speaks to those endpoints
|
|
26
|
+
* unchanged.
|
|
27
|
+
*/
|
|
28
|
+
import { Hono } from 'hono';
|
|
29
|
+
import { serve } from '@hono/node-server';
|
|
30
|
+
import { serveStatic } from '@hono/node-server/serve-static';
|
|
31
|
+
import { listenWithAutoIncrement } from "./listen.js";
|
|
32
|
+
import { existsSync, realpathSync } from 'node:fs';
|
|
33
|
+
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
34
|
+
import { fileURLToPath } from 'node:url';
|
|
35
|
+
import { readConfig } from '@deskwork/core/config';
|
|
36
|
+
import { readCalendar } from '@deskwork/core/calendar';
|
|
37
|
+
import { resolveCalendarPath } from '@deskwork/core/paths';
|
|
38
|
+
import { readWorkflow } from '@deskwork/core/review/pipeline';
|
|
39
|
+
import { createApiRouter } from "./routes/api.js";
|
|
40
|
+
import { serveScrapbookFile } from "./routes/scrapbook-file.js";
|
|
41
|
+
import { createScrapbookMutationsRouter } from "./routes/scrapbook-mutations.js";
|
|
42
|
+
import { buildClientAssets } from "./build-client-assets.js";
|
|
43
|
+
import { renderDashboard } from "./pages/dashboard.js";
|
|
44
|
+
import { renderReviewPage } from "./pages/review.js";
|
|
45
|
+
import { renderShortformPage } from "./pages/shortform.js";
|
|
46
|
+
import { renderHelpPage } from "./pages/help.js";
|
|
47
|
+
import { renderScrapbookPage } from "./pages/scrapbook.js";
|
|
48
|
+
import { renderContentTopLevel, renderContentProject, } from "./pages/content.js";
|
|
49
|
+
import { renderStudioIndex } from "./pages/index.js";
|
|
50
|
+
import { detectTailscale } from "./tailscale.js";
|
|
51
|
+
import { contentIndexMiddleware, getRequestContentIndex, } from "./request-context.js";
|
|
52
|
+
import { runTemplateOverride } from "./lib/override-render.js";
|
|
53
|
+
import { createOverrideResolver } from '@deskwork/core/overrides';
|
|
54
|
+
const DEFAULT_PORT = 47321;
|
|
55
|
+
const LOOPBACK = '127.0.0.1';
|
|
56
|
+
export function parseCliArgs(argv) {
|
|
57
|
+
let projectRoot = process.cwd();
|
|
58
|
+
let port = DEFAULT_PORT;
|
|
59
|
+
let portExplicit = false;
|
|
60
|
+
let hostOverride = null;
|
|
61
|
+
let noTailscale = false;
|
|
62
|
+
for (let i = 0; i < argv.length; i++) {
|
|
63
|
+
const a = argv[i];
|
|
64
|
+
if (a === '--project-root' || a === '-r') {
|
|
65
|
+
const next = argv[++i];
|
|
66
|
+
if (!next)
|
|
67
|
+
usage(`${a} requires a value`);
|
|
68
|
+
projectRoot = next;
|
|
69
|
+
}
|
|
70
|
+
else if (a.startsWith('--project-root=')) {
|
|
71
|
+
projectRoot = a.slice('--project-root='.length);
|
|
72
|
+
}
|
|
73
|
+
else if (a === '--port' || a === '-p') {
|
|
74
|
+
const next = argv[++i];
|
|
75
|
+
if (!next)
|
|
76
|
+
usage(`${a} requires a value`);
|
|
77
|
+
port = parseInt(next, 10);
|
|
78
|
+
portExplicit = true;
|
|
79
|
+
}
|
|
80
|
+
else if (a.startsWith('--port=')) {
|
|
81
|
+
port = parseInt(a.slice('--port='.length), 10);
|
|
82
|
+
portExplicit = true;
|
|
83
|
+
}
|
|
84
|
+
else if (a === '--host' || a === '-H') {
|
|
85
|
+
const next = argv[++i];
|
|
86
|
+
if (!next)
|
|
87
|
+
usage(`${a} requires a value`);
|
|
88
|
+
hostOverride = next;
|
|
89
|
+
}
|
|
90
|
+
else if (a.startsWith('--host=')) {
|
|
91
|
+
hostOverride = a.slice('--host='.length);
|
|
92
|
+
}
|
|
93
|
+
else if (a === '--no-tailscale') {
|
|
94
|
+
noTailscale = true;
|
|
95
|
+
}
|
|
96
|
+
else if (a === '--help' || a === '-h') {
|
|
97
|
+
usage(null);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
usage(`unknown argument: ${a}`);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (!Number.isFinite(port) || port <= 0 || port > 65535) {
|
|
104
|
+
usage(`invalid port: ${port}`);
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
projectRoot: isAbsolute(projectRoot) ? projectRoot : resolve(process.cwd(), projectRoot),
|
|
108
|
+
port,
|
|
109
|
+
portExplicit,
|
|
110
|
+
hostOverride,
|
|
111
|
+
noTailscale,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function usage(error) {
|
|
115
|
+
const out = error ? process.stderr : process.stdout;
|
|
116
|
+
if (error)
|
|
117
|
+
out.write(`error: ${error}\n\n`);
|
|
118
|
+
out.write('Usage: deskwork-studio [--project-root <path>] [--port <n>] [--host <addr>] [--no-tailscale]\n');
|
|
119
|
+
out.write('\n');
|
|
120
|
+
out.write('Options:\n');
|
|
121
|
+
out.write(' -r, --project-root <path> project root containing .deskwork/config.json\n');
|
|
122
|
+
out.write(' (default: cwd)\n');
|
|
123
|
+
out.write(` -p, --port <n> listen on this port (default: ${DEFAULT_PORT})\n`);
|
|
124
|
+
out.write(' -H, --host <addr> bind address. When set, the studio binds ONLY to\n');
|
|
125
|
+
out.write(' this address — overrides Tailscale auto-detection.\n');
|
|
126
|
+
out.write(' Use 0.0.0.0 to expose on every interface (LAN +\n');
|
|
127
|
+
out.write(' Tailscale + Wi-Fi). Studio has no auth; only do this\n');
|
|
128
|
+
out.write(' on trusted networks.\n');
|
|
129
|
+
out.write(' --no-tailscale skip Tailscale auto-detection (loopback only)\n');
|
|
130
|
+
out.write(' -h, --help show this message\n');
|
|
131
|
+
out.write('\n');
|
|
132
|
+
out.write('Default networking policy: bind to 127.0.0.1 (loopback) AND, if Tailscale is\n');
|
|
133
|
+
out.write('running on this machine, the local Tailscale interface(s). Tailscale peers can\n');
|
|
134
|
+
out.write("then reach the studio at the magic-DNS hostname (e.g. '<machine>.<tailnet>.ts.net').\n");
|
|
135
|
+
process.exit(error ? 2 : 0);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Resolve a UUID `id` against the calendar for `site` and return a
|
|
139
|
+
* `ReviewLookup` carrying both the id and the entry's display slug.
|
|
140
|
+
* Returns null when the id doesn't match any calendar entry — the
|
|
141
|
+
* caller then renders a "no galley to review" error page.
|
|
142
|
+
*/
|
|
143
|
+
function resolveEntryById(ctx, site, id) {
|
|
144
|
+
if (!(site in ctx.config.sites))
|
|
145
|
+
return null;
|
|
146
|
+
try {
|
|
147
|
+
const calendarPath = resolveCalendarPath(ctx.projectRoot, ctx.config, site);
|
|
148
|
+
if (!existsSync(calendarPath))
|
|
149
|
+
return null;
|
|
150
|
+
const cal = readCalendar(calendarPath);
|
|
151
|
+
const entry = cal.entries.find((e) => e.id === id);
|
|
152
|
+
if (!entry || entry.id === undefined)
|
|
153
|
+
return null;
|
|
154
|
+
return { kind: 'id', entryId: entry.id, slug: entry.slug };
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Resolve a slug to either:
|
|
162
|
+
* - `{ kind: 'id', entryId, slug }` when the entry has a stable id
|
|
163
|
+
* stamped — caller 302-redirects to the canonical id URL.
|
|
164
|
+
* - `{ kind: 'slug', slug }` when the entry exists but has no id
|
|
165
|
+
* (pre-doctor migration state) — caller renders directly.
|
|
166
|
+
* - `null` when no entry matches the slug — caller renders 404.
|
|
167
|
+
* - `'unknown-site'` when the site param isn't configured.
|
|
168
|
+
*/
|
|
169
|
+
function resolveEntryBySlug(ctx, site, slug) {
|
|
170
|
+
if (!(site in ctx.config.sites))
|
|
171
|
+
return 'unknown-site';
|
|
172
|
+
try {
|
|
173
|
+
const calendarPath = resolveCalendarPath(ctx.projectRoot, ctx.config, site);
|
|
174
|
+
if (!existsSync(calendarPath))
|
|
175
|
+
return null;
|
|
176
|
+
const cal = readCalendar(calendarPath);
|
|
177
|
+
const entry = cal.entries.find((e) => e.slug === slug);
|
|
178
|
+
if (!entry)
|
|
179
|
+
return null;
|
|
180
|
+
if (entry.id)
|
|
181
|
+
return { kind: 'id', entryId: entry.id, slug: entry.slug };
|
|
182
|
+
return { kind: 'slug', slug: entry.slug };
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Build the canonical id-based redirect URL while preserving the
|
|
190
|
+
* original request's query string (site, version, kind, etc.). The
|
|
191
|
+
* input URL is the absolute request URL (Hono's `c.req.url`); we
|
|
192
|
+
* extract just the search portion and graft it onto the new path.
|
|
193
|
+
*/
|
|
194
|
+
function buildReviewRedirectUrl(entryId, requestUrl) {
|
|
195
|
+
let search = '';
|
|
196
|
+
try {
|
|
197
|
+
const u = new URL(requestUrl);
|
|
198
|
+
search = u.search;
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
search = '';
|
|
202
|
+
}
|
|
203
|
+
return `/dev/editorial-review/${entryId}${search}`;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Resolve the plugin tree root (`plugins/deskwork-studio/`) at runtime.
|
|
207
|
+
*
|
|
208
|
+
* Three runtime layouts (Phase 23 source-shipped re-architecture):
|
|
209
|
+
* - Workspace: `packages/studio/src/server.ts` (run via the workspace
|
|
210
|
+
* bin symlink) → plugin root is `<HERE>/../../../plugins/deskwork-studio`.
|
|
211
|
+
* - Marketplace (legacy node_modules layout): `<pluginRoot>/node_modules/
|
|
212
|
+
* @deskwork/studio/src/server.ts` → plugin root is `<HERE>/../../../..`.
|
|
213
|
+
* - Marketplace (materialized vendor layout, Phase 23c): npm symlinks
|
|
214
|
+
* `node_modules/@deskwork/studio` → `vendor/studio`, so `import.meta.url`
|
|
215
|
+
* resolves through the symlink to `<pluginRoot>/vendor/studio/src/server.ts`
|
|
216
|
+
* → plugin root is `<HERE>/../../..`. Surfaced by the Phase 23g
|
|
217
|
+
* `scripts/smoke-marketplace.sh` smoke test, which boots the studio
|
|
218
|
+
* against an extracted+materialized tree and asserts every route 200s.
|
|
219
|
+
*
|
|
220
|
+
* All candidates are tried; whichever has a `public/src/` directory
|
|
221
|
+
* adjacent wins. `public/src/` ships in the plugin tree only.
|
|
222
|
+
*/
|
|
223
|
+
function pluginRoot() {
|
|
224
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
225
|
+
const candidates = [
|
|
226
|
+
resolve(here, '..', '..', '..', 'plugins', 'deskwork-studio'),
|
|
227
|
+
resolve(here, '..', '..', '..', '..'),
|
|
228
|
+
resolve(here, '..', '..', '..'),
|
|
229
|
+
];
|
|
230
|
+
for (const candidate of candidates) {
|
|
231
|
+
// Use the plugin's marker file (public/src exists in both layouts)
|
|
232
|
+
// to avoid grabbing an unrelated parent dir.
|
|
233
|
+
if (existsSync(resolve(candidate, 'public', 'src')))
|
|
234
|
+
return candidate;
|
|
235
|
+
}
|
|
236
|
+
throw new Error(`deskwork-studio: could not find plugin root. Tried:\n ${candidates.join('\n ')}`);
|
|
237
|
+
}
|
|
238
|
+
function publicDir() {
|
|
239
|
+
// CSS, source modules, and any other static assets live under
|
|
240
|
+
// `<pluginRoot>/public/`. Compiled client JS does NOT live here in
|
|
241
|
+
// the runtime-built path (Phase 23e) — see clientAssetsDir().
|
|
242
|
+
const root = resolve(pluginRoot(), 'public');
|
|
243
|
+
if (!existsSync(root)) {
|
|
244
|
+
throw new Error(`deskwork-studio: could not find public/ assets at ${root}`);
|
|
245
|
+
}
|
|
246
|
+
return root;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Path to runtime-built client modules
|
|
250
|
+
* (`<pluginRoot>/.runtime-cache/dist/`). Phase 23e builds into this dir
|
|
251
|
+
* during boot; the `/static/dist/*` mount serves from it.
|
|
252
|
+
*/
|
|
253
|
+
function clientAssetsDir() {
|
|
254
|
+
return resolve(pluginRoot(), '.runtime-cache', 'dist');
|
|
255
|
+
}
|
|
256
|
+
export function createApp(ctx) {
|
|
257
|
+
const app = new Hono();
|
|
258
|
+
// Per-request content-index memoization. Mounted before page routes
|
|
259
|
+
// so every renderer in a single request shares one index per site.
|
|
260
|
+
// The middleware just attaches an empty cache; renderers populate it
|
|
261
|
+
// lazily via `getRequestContentIndex(c, ctx, site)`.
|
|
262
|
+
app.use('*', contentIndexMiddleware());
|
|
263
|
+
// API routes
|
|
264
|
+
app.route('/api/dev/editorial-review', createApiRouter(ctx));
|
|
265
|
+
// Page routes
|
|
266
|
+
app.get('/dev', (c) => c.html(renderStudioIndex(ctx)));
|
|
267
|
+
app.get('/dev/', (c) => c.html(renderStudioIndex(ctx)));
|
|
268
|
+
app.get('/dev/editorial-studio', async (c) => {
|
|
269
|
+
const getIndex = (site) => getRequestContentIndex(c, ctx, site);
|
|
270
|
+
// Phase 23f: per-project override check. The override module's
|
|
271
|
+
// `default` is called with the same args the built-in renderer
|
|
272
|
+
// expects: (ctx, getIndex). When no override exists, we fall
|
|
273
|
+
// through to the built-in dashboard.
|
|
274
|
+
const overridden = await runTemplateOverride(ctx, 'dashboard', [
|
|
275
|
+
ctx,
|
|
276
|
+
getIndex,
|
|
277
|
+
]);
|
|
278
|
+
if (overridden !== null)
|
|
279
|
+
return c.html(overridden);
|
|
280
|
+
return c.html(renderDashboard(ctx, getIndex));
|
|
281
|
+
});
|
|
282
|
+
app.get('/dev/editorial-help', async (c) => {
|
|
283
|
+
const overridden = await runTemplateOverride(ctx, 'help', [ctx]);
|
|
284
|
+
if (overridden !== null)
|
|
285
|
+
return c.html(overridden);
|
|
286
|
+
return c.html(renderHelpPage(ctx));
|
|
287
|
+
});
|
|
288
|
+
app.get('/dev/editorial-review-shortform', (c) => c.html(renderShortformPage(ctx)));
|
|
289
|
+
// Phase 19d: id-based canonical review URL. Strict UUID-shape regex
|
|
290
|
+
// matched FIRST so it wins over the legacy `:slug{.+}` route below.
|
|
291
|
+
// Hono evaluates routes in registration order; first match wins.
|
|
292
|
+
//
|
|
293
|
+
// Phase 21c added a workflow-id branch: the dashboard's shortform
|
|
294
|
+
// matrix (and any other surface that knows a workflow id) deep-links
|
|
295
|
+
// straight to a workflow record. We try workflow-id resolution first
|
|
296
|
+
// because workflow journals are smaller than the calendar; entry-id
|
|
297
|
+
// is the existing canonical longform/outline path and stays the
|
|
298
|
+
// fallback when the id doesn't match a workflow.
|
|
299
|
+
app.get('/dev/editorial-review/:id{[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}', async (c) => {
|
|
300
|
+
const id = c.req.param('id');
|
|
301
|
+
const siteParam = c.req.query('site') ?? ctx.config.defaultSite;
|
|
302
|
+
const getIndex = (s) => getRequestContentIndex(c, ctx, s);
|
|
303
|
+
const reviewQuery = {
|
|
304
|
+
site: c.req.query('site') ?? null,
|
|
305
|
+
version: c.req.query('v') ?? null,
|
|
306
|
+
kind: c.req.query('kind') ?? null,
|
|
307
|
+
};
|
|
308
|
+
// 1. Workflow-id branch — phase 21c.
|
|
309
|
+
const wf = readWorkflow(ctx.projectRoot, ctx.config, id);
|
|
310
|
+
if (wf !== null) {
|
|
311
|
+
const lookup = { kind: 'workflow', workflowId: id };
|
|
312
|
+
const overridden = await runTemplateOverride(ctx, 'review', [
|
|
313
|
+
ctx,
|
|
314
|
+
lookup,
|
|
315
|
+
reviewQuery,
|
|
316
|
+
getIndex,
|
|
317
|
+
]);
|
|
318
|
+
if (overridden !== null)
|
|
319
|
+
return c.html(overridden);
|
|
320
|
+
return c.html(await renderReviewPage(ctx, lookup, reviewQuery, getIndex));
|
|
321
|
+
}
|
|
322
|
+
// 2. Entry-id branch — the legacy canonical longform/outline URL.
|
|
323
|
+
const lookup = resolveEntryById(ctx, siteParam, id);
|
|
324
|
+
const effectiveLookup = lookup ?? { kind: 'id', entryId: id, slug: id };
|
|
325
|
+
const overridden = await runTemplateOverride(ctx, 'review', [
|
|
326
|
+
ctx,
|
|
327
|
+
effectiveLookup,
|
|
328
|
+
reviewQuery,
|
|
329
|
+
getIndex,
|
|
330
|
+
]);
|
|
331
|
+
if (overridden !== null)
|
|
332
|
+
return c.html(overridden);
|
|
333
|
+
return c.html(await renderReviewPage(ctx, effectiveLookup, reviewQuery, getIndex));
|
|
334
|
+
});
|
|
335
|
+
// Legacy slug route. `:slug{.+}` captures hierarchical slugs
|
|
336
|
+
// (`/`-separated kebab-case segments). Resolution order:
|
|
337
|
+
// 1. Calendar entry exists with id → 302-redirect to canonical id URL.
|
|
338
|
+
// 2. Calendar entry exists without id (pre-doctor) → render via
|
|
339
|
+
// legacy slug-keyed workflow join (no redirect).
|
|
340
|
+
// 3. No calendar entry → fall through to slug-keyed render anyway:
|
|
341
|
+
// a workflow may exist independently (test fixtures, ad-hoc
|
|
342
|
+
// drafts not on the calendar). The renderer's renderError path
|
|
343
|
+
// handles "no workflow either" with a 200 explainer page.
|
|
344
|
+
// Only reachable when the path doesn't match the UUID route above.
|
|
345
|
+
app.get('/dev/editorial-review/:slug{.+}', async (c) => {
|
|
346
|
+
const slug = decodeURIComponent(c.req.param('slug'));
|
|
347
|
+
const siteParam = c.req.query('site') ?? ctx.config.defaultSite;
|
|
348
|
+
const found = resolveEntryBySlug(ctx, siteParam, slug);
|
|
349
|
+
if (found === 'unknown-site') {
|
|
350
|
+
return c.notFound();
|
|
351
|
+
}
|
|
352
|
+
if (found !== null && found.kind === 'id') {
|
|
353
|
+
const url = buildReviewRedirectUrl(found.entryId, c.req.url);
|
|
354
|
+
return c.redirect(url, 302);
|
|
355
|
+
}
|
|
356
|
+
// `found === null` (no calendar entry) OR `kind: 'slug'` (entry
|
|
357
|
+
// present, no id). Both render through the slug-keyed legacy path.
|
|
358
|
+
const lookup = found !== null ? found : { kind: 'slug', slug };
|
|
359
|
+
const getIndex = (s) => getRequestContentIndex(c, ctx, s);
|
|
360
|
+
const reviewQuery = {
|
|
361
|
+
site: c.req.query('site') ?? null,
|
|
362
|
+
version: c.req.query('v') ?? null,
|
|
363
|
+
kind: c.req.query('kind') ?? null,
|
|
364
|
+
};
|
|
365
|
+
const overridden = await runTemplateOverride(ctx, 'review', [
|
|
366
|
+
ctx,
|
|
367
|
+
lookup,
|
|
368
|
+
reviewQuery,
|
|
369
|
+
getIndex,
|
|
370
|
+
]);
|
|
371
|
+
if (overridden !== null)
|
|
372
|
+
return c.html(overridden);
|
|
373
|
+
return c.html(await renderReviewPage(ctx, lookup, reviewQuery, getIndex));
|
|
374
|
+
});
|
|
375
|
+
// Wildcard path — `:site` is a single segment, the trailing path
|
|
376
|
+
// captures arbitrarily-deep hierarchical addresses (e.g.
|
|
377
|
+
// `the-outbound/characters/strivers`). Hono's `:path{.+}` regex
|
|
378
|
+
// matcher swallows everything after the site segment.
|
|
379
|
+
app.get('/dev/scrapbook/:site/:path{.+}', async (c) => {
|
|
380
|
+
const site = c.req.param('site');
|
|
381
|
+
const path = decodeURIComponent(c.req.param('path'));
|
|
382
|
+
const overridden = await runTemplateOverride(ctx, 'scrapbook', [
|
|
383
|
+
ctx,
|
|
384
|
+
site,
|
|
385
|
+
path,
|
|
386
|
+
]);
|
|
387
|
+
if (overridden !== null)
|
|
388
|
+
return c.html(overridden);
|
|
389
|
+
return c.html(renderScrapbookPage(ctx, site, path));
|
|
390
|
+
});
|
|
391
|
+
// Read-only binary endpoint for scrapbook files. Used by the
|
|
392
|
+
// shared scrapbook-item renderer (`components/scrapbook-item.ts`)
|
|
393
|
+
// to source image thumbnails, PDF iframes, and download fallbacks.
|
|
394
|
+
// The standalone scrapbook viewer also uses this for previews; its
|
|
395
|
+
// mutation endpoints (save/rename/delete/create/upload) hang off
|
|
396
|
+
// `/api/dev/scrapbook/*` below.
|
|
397
|
+
app.get('/api/dev/scrapbook-file', (c) => serveScrapbookFile(c, ctx));
|
|
398
|
+
// Mutation endpoints for the standalone scrapbook viewer. The
|
|
399
|
+
// client (`plugins/deskwork-studio/public/src/scrapbook-client.ts`)
|
|
400
|
+
// POSTs to /save, /rename, /delete, /create, /upload. All path
|
|
401
|
+
// resolution + traversal protection is delegated to
|
|
402
|
+
// `@deskwork/core/scrapbook` helpers — see issue #21 for the
|
|
403
|
+
// full contract.
|
|
404
|
+
app.route('/api/dev/scrapbook', createScrapbookMutationsRouter(ctx));
|
|
405
|
+
// Bird's-eye content view (Phase 16d). Three routes:
|
|
406
|
+
// GET /dev/content — top-level (sites + projects)
|
|
407
|
+
// GET /dev/content/:site — same shape filtered to one site
|
|
408
|
+
// GET /dev/content/:site/:project{.+} — drilldown for one project
|
|
409
|
+
// The `?node=<slug>` query param toggles the detail panel.
|
|
410
|
+
app.get('/dev/content', async (c) => {
|
|
411
|
+
const getIndex = (site) => getRequestContentIndex(c, ctx, site);
|
|
412
|
+
const overridden = await runTemplateOverride(ctx, 'content', [
|
|
413
|
+
ctx,
|
|
414
|
+
getIndex,
|
|
415
|
+
]);
|
|
416
|
+
if (overridden !== null)
|
|
417
|
+
return c.html(overridden);
|
|
418
|
+
return c.html(renderContentTopLevel(ctx, getIndex));
|
|
419
|
+
});
|
|
420
|
+
app.get('/dev/content/:site', async (c) => {
|
|
421
|
+
const getIndex = (site) => getRequestContentIndex(c, ctx, site);
|
|
422
|
+
const overridden = await runTemplateOverride(ctx, 'content', [
|
|
423
|
+
ctx,
|
|
424
|
+
getIndex,
|
|
425
|
+
]);
|
|
426
|
+
if (overridden !== null)
|
|
427
|
+
return c.html(overridden);
|
|
428
|
+
return c.html(renderContentTopLevel(ctx, getIndex));
|
|
429
|
+
});
|
|
430
|
+
app.get('/dev/content/:site/:project{.+}', async (c) => {
|
|
431
|
+
const site = c.req.param('site');
|
|
432
|
+
const project = decodeURIComponent(c.req.param('project'));
|
|
433
|
+
const node = c.req.query('node') ?? null;
|
|
434
|
+
const getIndex = (s) => getRequestContentIndex(c, ctx, s);
|
|
435
|
+
const overridden = await runTemplateOverride(ctx, 'content-project', [
|
|
436
|
+
ctx,
|
|
437
|
+
site,
|
|
438
|
+
project,
|
|
439
|
+
node,
|
|
440
|
+
getIndex,
|
|
441
|
+
]);
|
|
442
|
+
if (overridden !== null)
|
|
443
|
+
return c.html(overridden);
|
|
444
|
+
const r = await renderContentProject(ctx, site, project, node, getIndex);
|
|
445
|
+
return c.html(r.html, r.status);
|
|
446
|
+
});
|
|
447
|
+
// Static assets — UI client JS, CSS, etc.
|
|
448
|
+
//
|
|
449
|
+
// Phase 23e: client modules are esbuild-built at server boot into
|
|
450
|
+
// <pluginRoot>/.runtime-cache/dist/. The more-specific `/static/dist/*`
|
|
451
|
+
// mount is registered FIRST so it wins over the catchall below for JS
|
|
452
|
+
// requests; CSS and other files stay served from `public/`. URL surface
|
|
453
|
+
// is unchanged — page renderers still emit /static/dist/<name>.js and
|
|
454
|
+
// /static/css/<file>.css.
|
|
455
|
+
app.use('/static/dist/*', serveStatic({
|
|
456
|
+
root: clientAssetsDir(),
|
|
457
|
+
rewriteRequestPath: (path) => path.replace(/^\/static\/dist/, ''),
|
|
458
|
+
}));
|
|
459
|
+
app.use('/static/*', serveStatic({
|
|
460
|
+
root: publicDir(),
|
|
461
|
+
rewriteRequestPath: (path) => path.replace(/^\/static/, ''),
|
|
462
|
+
}));
|
|
463
|
+
// Convenience root redirect to the studio index.
|
|
464
|
+
app.get('/', (c) => c.redirect('/dev/'));
|
|
465
|
+
return app;
|
|
466
|
+
}
|
|
467
|
+
async function main() {
|
|
468
|
+
const { projectRoot, port, portExplicit, hostOverride, noTailscale } = parseCliArgs(process.argv.slice(2));
|
|
469
|
+
let config;
|
|
470
|
+
try {
|
|
471
|
+
config = readConfig(projectRoot);
|
|
472
|
+
}
|
|
473
|
+
catch (err) {
|
|
474
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
475
|
+
process.stderr.write(`Could not load config: ${reason}\n`);
|
|
476
|
+
process.exit(1);
|
|
477
|
+
}
|
|
478
|
+
// Phase 23e: build client modules from source into the runtime cache
|
|
479
|
+
// BEFORE wiring routes (the `/static/dist/*` mount records its root
|
|
480
|
+
// at registration time and warns when the path doesn't exist yet).
|
|
481
|
+
// Failures abort startup — serving stale or missing JS would silently
|
|
482
|
+
// break the UI.
|
|
483
|
+
try {
|
|
484
|
+
const summary = await buildClientAssets({ pluginRoot: pluginRoot() });
|
|
485
|
+
process.stdout.write(`deskwork-studio: built ${summary.entriesBuilt} client assets ` +
|
|
486
|
+
`(${summary.entriesCached} cached) -> ${summary.outDir}\n`);
|
|
487
|
+
}
|
|
488
|
+
catch (err) {
|
|
489
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
490
|
+
process.stderr.write(`deskwork-studio: client asset build failed: ${reason}\n`);
|
|
491
|
+
process.exit(1);
|
|
492
|
+
}
|
|
493
|
+
// Phase 23f: build the override resolver once at boot so every page
|
|
494
|
+
// request reuses the same instance. The resolver itself is cheap, but
|
|
495
|
+
// threading it through `ctx` makes the dependency explicit.
|
|
496
|
+
const resolver = createOverrideResolver(projectRoot);
|
|
497
|
+
const ctx = { projectRoot, config, resolver };
|
|
498
|
+
const app = createApp(ctx);
|
|
499
|
+
// Networking policy:
|
|
500
|
+
// --host <addr> → bind ONLY to that address (operator override)
|
|
501
|
+
// --no-tailscale → loopback only
|
|
502
|
+
// default → loopback + auto-detected Tailscale (if running)
|
|
503
|
+
//
|
|
504
|
+
// The studio is dev-only with no auth. Loopback is always safe.
|
|
505
|
+
// Tailscale's tailnet is treated as a trusted network — peers on the
|
|
506
|
+
// same tailnet are usually devices the operator owns. LAN/Wi-Fi
|
|
507
|
+
// exposure stays opt-in via `--host 0.0.0.0`.
|
|
508
|
+
let tailscale = null;
|
|
509
|
+
let bindAddresses;
|
|
510
|
+
if (hostOverride !== null) {
|
|
511
|
+
bindAddresses = [hostOverride];
|
|
512
|
+
}
|
|
513
|
+
else if (noTailscale) {
|
|
514
|
+
bindAddresses = [LOOPBACK];
|
|
515
|
+
}
|
|
516
|
+
else {
|
|
517
|
+
tailscale = detectTailscale();
|
|
518
|
+
bindAddresses = tailscale === null ? [LOOPBACK] : [LOOPBACK, ...tailscale.ipv4];
|
|
519
|
+
}
|
|
520
|
+
// Issue #43: bind every address with EADDRINUSE handling.
|
|
521
|
+
// - default port: walk forward through a small range on conflict.
|
|
522
|
+
// - --port explicit: fail fast with a clear error.
|
|
523
|
+
let result;
|
|
524
|
+
try {
|
|
525
|
+
result = await listenWithAutoIncrement({
|
|
526
|
+
fetch: app.fetch,
|
|
527
|
+
port,
|
|
528
|
+
addresses: bindAddresses,
|
|
529
|
+
explicitPort: portExplicit,
|
|
530
|
+
}, serve);
|
|
531
|
+
}
|
|
532
|
+
catch (err) {
|
|
533
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
534
|
+
process.stderr.write(`deskwork-studio: ${reason}\n`);
|
|
535
|
+
process.exit(1);
|
|
536
|
+
}
|
|
537
|
+
const reachableUrls = [];
|
|
538
|
+
for (const addr of bindAddresses) {
|
|
539
|
+
reachableUrls.push(`http://${addr === LOOPBACK ? 'localhost' : addr}:${result.port}/`);
|
|
540
|
+
}
|
|
541
|
+
printBanner({
|
|
542
|
+
urls: reachableUrls,
|
|
543
|
+
projectRoot,
|
|
544
|
+
siteSlugs: Object.keys(config.sites),
|
|
545
|
+
tailscale,
|
|
546
|
+
port: result.port,
|
|
547
|
+
override: hostOverride,
|
|
548
|
+
autoIncrementedFrom: result.autoIncremented ? port : null,
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
function printBanner(b) {
|
|
552
|
+
process.stdout.write('deskwork-studio listening on:\n');
|
|
553
|
+
for (const url of b.urls) {
|
|
554
|
+
process.stdout.write(` ${url}\n`);
|
|
555
|
+
}
|
|
556
|
+
if (b.tailscale && b.tailscale.magicDnsName) {
|
|
557
|
+
process.stdout.write(` http://${b.tailscale.magicDnsName}:${b.port}/ (Tailscale magic-DNS)\n`);
|
|
558
|
+
}
|
|
559
|
+
process.stdout.write(` project: ${b.projectRoot}\n`);
|
|
560
|
+
process.stdout.write(` sites: ${b.siteSlugs.join(', ')}\n`);
|
|
561
|
+
if (b.autoIncrementedFrom !== null) {
|
|
562
|
+
// Issue #43: surface the auto-increment so the operator isn't
|
|
563
|
+
// confused when the URL doesn't match the documented default.
|
|
564
|
+
process.stdout.write(` note: port ${b.autoIncrementedFrom} was in use; using ${b.port} instead\n`);
|
|
565
|
+
}
|
|
566
|
+
// Loud warning when bound beyond loopback + Tailscale tailnet.
|
|
567
|
+
// Tailscale interfaces (100.64.0.0/10) are considered trusted; an
|
|
568
|
+
// explicit --host other than loopback is not.
|
|
569
|
+
const exposed = b.override !== null && b.override !== LOOPBACK;
|
|
570
|
+
if (exposed) {
|
|
571
|
+
process.stdout.write(` warning: bound to ${b.override}. Studio has no authentication —\n` +
|
|
572
|
+
' only run this on a trusted network (Tailscale, VPN, etc.).\n');
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
// Only run when invoked directly, not when imported from tests. Resolve
|
|
576
|
+
// argv[1] to an absolute path before comparing to import.meta.url, since the
|
|
577
|
+
// shell may invoke us through a symlink (npm's node_modules/.bin/...).
|
|
578
|
+
if (process.argv[1] && realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
579
|
+
await main();
|
|
580
|
+
}
|
|
581
|
+
//# sourceMappingURL=server.js.map
|