@tensorix/metahub 0.1.3 → 0.1.4

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/index.js CHANGED
@@ -531,9 +531,14 @@ var init_sites = __esm(() => {
531
531
  // src/core/sync/webui.ts
532
532
  var exports_webui = {};
533
533
  __export(exports_webui, {
534
+ warmWebui: () => warmWebui,
535
+ setWebuiBundle: () => setWebuiBundle,
534
536
  serveWebui: () => serveWebui
535
537
  });
536
538
  import { fileURLToPath } from "url";
539
+ function setWebuiBundle(js) {
540
+ cachedJs = js;
541
+ }
537
542
  async function getJs() {
538
543
  if (cachedJs != null)
539
544
  return cachedJs;
@@ -549,6 +554,11 @@ async function getJs() {
549
554
  cachedJs = await res.outputs[0].text();
550
555
  return cachedJs;
551
556
  }
557
+ async function warmWebui() {
558
+ try {
559
+ await getJs();
560
+ } catch {}
561
+ }
552
562
  async function serveWebui(req) {
553
563
  if (req.method !== "GET")
554
564
  return null;
@@ -575,7 +585,13 @@ var HTML = `<!doctype html>
575
585
  <title>Metahub</title>
576
586
  <link rel="preconnect" href="https://fonts.googleapis.com">
577
587
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
578
- <link href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
588
+ <!-- Load web fonts without blocking first paint: media="print" keeps the
589
+ stylesheet non-render-blocking, then onload flips it to "all". The page
590
+ paints instantly with the system-font fallbacks baked into --ui/--mono and
591
+ swaps to the web fonts when they arrive (or stays on system fonts offline).
592
+ This is what kept the desktop cold-start white for seconds on slow networks. -->
593
+ <link rel="stylesheet" media="print" onload="this.media='all'" href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap">
594
+ <noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Hanken+Grotesk:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"></noscript>
579
595
  <script>try{document.documentElement.dataset.theme=localStorage.getItem('mh-theme')||'system'}catch(e){}</script>
580
596
  <style>
581
597
  :root {
@@ -685,6 +701,9 @@ var HTML = `<!doctype html>
685
701
  .set-section { margin-top:34px; }
686
702
  .set-section-head { font-size:12px; font-weight:600; text-transform:uppercase; letter-spacing:.07em; color:var(--muted); margin-bottom:4px; }
687
703
  .set-section-desc { color:var(--fg-soft); margin-bottom:16px; }
704
+ .set-footer { margin-top:40px; padding-top:20px; border-top:1px solid var(--line); display:flex;
705
+ justify-content:center; gap:8px; color:var(--muted); font-size:12px; }
706
+ .set-footer-sep { opacity:.5; }
688
707
  .theme-grid { display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
689
708
  .theme-card { position:relative; display:flex; flex-direction:column; align-items:flex-start; gap:10px;
690
709
  text-align:left; padding:16px; border:1px solid var(--line-strong); border-radius:var(--radius);
@@ -722,6 +741,7 @@ var HTML = `<!doctype html>
722
741
  /* main */
723
742
  .main { flex:1; display:flex; flex-direction:column; overflow:hidden; min-width:0; }
724
743
  .topbar { display:flex; align-items:center; gap:6px; padding:10px 18px; border-bottom:1px solid var(--line); min-height:49px; }
744
+ .topbar.bare { border-bottom:0; }
725
745
  .topbar .hamburger { display:none; }
726
746
  .topbar .hamburger.show-collapsed { display:grid; }
727
747
  .sidebar.collapsed { overflow:hidden; }
@@ -1046,7 +1066,71 @@ var HTML = `<!doctype html>
1046
1066
  @keyframes slidein { from { opacity:0; transform:translateX(-12px); } }
1047
1067
 
1048
1068
  /* misc */
1049
- .empty { display:grid; place-items:center; height:100%; color:var(--muted); text-align:center; padding:40px; }
1069
+ .empty { display:flex; flex-direction:column; align-items:center; justify-content:center; height:100%;
1070
+ color:var(--muted); text-align:center; padding:40px; }
1071
+
1072
+ /* ---- empty state: \u77E5\u8BC6\u751F\u957F\u63D2\u753B ---- */
1073
+ .estate-art { width:240px; height:208px; overflow:visible; animation:idleFloat 5s ease-in-out 1.6s infinite; }
1074
+ .estate-art .stroke-a { fill:none; stroke:var(--accent); stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round; }
1075
+ .estate-art .stroke { fill:none; stroke:var(--line-strong); stroke-width:2.4; stroke-linecap:round; stroke-linejoin:round; }
1076
+ .estate-art .fill-a { fill:var(--accent); }
1077
+ .estate-art .fill-soft { fill:var(--accent-soft); }
1078
+ .estate-art .fill-surface { fill:var(--bg); }
1079
+ .estate-art .ground { fill:var(--accent); }
1080
+ .estate-title { margin:28px 0 0; font-size:18px; font-weight:600; letter-spacing:.2px; color:var(--fg);
1081
+ opacity:0; animation:fadeUp .5s ease forwards 1.0s; }
1082
+ .estate-hint { margin:9px 0 0; font-size:13.5px; line-height:1.6; color:var(--muted); max-width:300px;
1083
+ opacity:0; animation:fadeUp .5s ease forwards 1.15s; }
1084
+ .estate-link { margin:18px 0 0; font-size:14px; font-weight:600; color:var(--accent);
1085
+ display:inline-flex; align-items:center; gap:6px; padding:9px 8px; border-radius:var(--radius-sm);
1086
+ opacity:0; animation:fadeUp .5s ease forwards 1.3s; transition:opacity .15s; }
1087
+ .estate-link:hover { opacity:.7; }
1088
+ /* intro */
1089
+ .draw { stroke-dasharray:100; stroke-dashoffset:100; }
1090
+ @keyframes draw { to { stroke-dashoffset:0; } }
1091
+ @keyframes leafGrow { from { opacity:0; transform:scale(.2) rotate(-10deg); } to { opacity:1; transform:scale(1) rotate(0); } }
1092
+ @keyframes cardUp { from { opacity:0; transform:translateY(16px) scale(.96); } to { opacity:1; transform:translateY(0) scale(1); } }
1093
+ @keyframes groundIn { to { opacity:.1; } }
1094
+ @keyframes glowIn { to { opacity:.6; } }
1095
+ @keyframes fadeUp { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:translateY(0); } }
1096
+ /* idle loops \u2014 each 0% equals the settled rest state to avoid a jump */
1097
+ @keyframes idleFloat { 0%,100% { transform:translateY(0); } 50% { transform:translateY(-5px); } }
1098
+ @keyframes plantSway { 0%,100% { transform:rotate(0deg); } 25% { transform:rotate(-1.3deg); } 75% { transform:rotate(1.3deg); } }
1099
+ @keyframes leafSwayA { 0%,100% { transform:rotate(0deg); } 25% { transform:rotate(-2.6deg); } 75% { transform:rotate(2.6deg); } }
1100
+ @keyframes leafSwayB { 0%,100% { transform:rotate(0deg); } 25% { transform:rotate(2.6deg); } 75% { transform:rotate(-2.6deg); } }
1101
+ @keyframes groundBreathe { 0%,100% { transform:scale(1); opacity:.10; } 50% { transform:scale(1.07); opacity:.15; } }
1102
+ @keyframes glowPulse { 0%,100% { transform:scale(1); opacity:.6; } 50% { transform:scale(1.1); opacity:.85; } }
1103
+ @keyframes particle { 0% { opacity:0; transform:translate(0,0) scale(.4); } 35% { opacity:.85; transform:translate(2px,-4px) scale(1); } 70% { opacity:0; transform:translate(4px,-9px) scale(.5); } 100% { opacity:0; transform:translate(0,0) scale(.4); } }
1104
+ /* wiring */
1105
+ .kg-ground { transform-box:fill-box; transform-origin:center; opacity:0;
1106
+ animation:groundIn .5s ease forwards .1s, groundBreathe 6s ease-in-out 1.6s infinite; }
1107
+ .kg-glow { filter:blur(9px); transform-box:fill-box; transform-origin:center; opacity:0;
1108
+ animation:glowIn .6s ease forwards .1s, glowPulse 4.6s ease-in-out 1.6s infinite; }
1109
+ .kg-cardB { transform-box:fill-box; transform-origin:center; opacity:0; animation:cardUp .55s cubic-bezier(.2,.8,.2,1) forwards .2s; }
1110
+ .kg-cardA { transform-box:fill-box; transform-origin:center; opacity:0; animation:cardUp .55s cubic-bezier(.2,.8,.2,1) forwards .32s; }
1111
+ .kg-plant { transform-box:fill-box; transform-origin:50% 100%; animation:plantSway 6s ease-in-out 1.7s infinite; }
1112
+ .kg-stem { animation:draw .9s ease-out forwards .4s; }
1113
+ .kg-leaf { transform-box:fill-box; }
1114
+ .kg-grow { transform-box:fill-box; opacity:0; }
1115
+ .kg-leaf.l1 { transform-origin:90% 100%; animation:leafSwayA 4.6s ease-in-out 1.7s infinite; }
1116
+ .kg-leaf.l2 { transform-origin:0% 80%; animation:leafSwayB 5.2s ease-in-out 1.8s infinite; }
1117
+ .kg-leaf.l3 { transform-origin:0% 100%; animation:leafSwayA 5.0s ease-in-out 1.9s infinite; }
1118
+ .kg-leaf.l1 .kg-grow { transform-origin:90% 100%; animation:leafGrow .52s cubic-bezier(.18,.9,.24,1.22) forwards .85s; }
1119
+ .kg-leaf.l2 .kg-grow { transform-origin:0% 80%; animation:leafGrow .52s cubic-bezier(.18,.9,.24,1.22) forwards 1.0s; }
1120
+ .kg-leaf.l3 .kg-grow { transform-origin:0% 100%; animation:leafGrow .52s cubic-bezier(.18,.9,.24,1.22) forwards 1.15s; }
1121
+ .kg-particle { transform-box:fill-box; transform-origin:center; opacity:0; }
1122
+ .kg-particle.p1 { animation:particle 4.5s ease-in-out 1.6s infinite; }
1123
+ .kg-particle.p2 { animation:particle 5.2s ease-in-out 2.0s infinite; }
1124
+ .kg-particle.p3 { animation:particle 4.8s ease-in-out 2.6s infinite; }
1125
+ .kg-particle.p4 { animation:particle 5.6s ease-in-out 3.1s infinite; }
1126
+ .kg-particle.p5 { animation:particle 4.2s ease-in-out 2.3s infinite; }
1127
+ @media (prefers-reduced-motion: reduce) {
1128
+ .estate-art, .estate-art *, .estate-title, .estate-hint, .estate-link { animation:none !important; opacity:1 !important; transform:none !important; }
1129
+ .draw { stroke-dashoffset:0 !important; }
1130
+ .kg-ground { opacity:.1 !important; }
1131
+ .kg-glow { opacity:.6 !important; }
1132
+ .kg-particle { opacity:0 !important; }
1133
+ }
1050
1134
  .error-bar { margin:12px 24px; padding:10px 14px; background:var(--danger-soft); color:var(--danger); border-radius:var(--radius-sm); font-size:13px; cursor:pointer; }
1051
1135
  .view-placeholder { padding:40px; text-align:center; border:1px dashed var(--line-strong); border-radius:var(--radius); color:var(--muted); margin-top:8px; }
1052
1136
  .ico.flip { transform:scaleX(-1); }
@@ -1426,9 +1510,20 @@ function deleteDatabase(db, id) {
1426
1510
  if (!getDatabase(db, id))
1427
1511
  return false;
1428
1512
  emit(db, "databases", id, "__deleted", 1);
1513
+ const tombstone = (table) => {
1514
+ for (const r of liveChildren(db, table, "database_id", id))
1515
+ emit(db, table, r, "__deleted", 1);
1516
+ };
1517
+ tombstone("properties");
1518
+ tombstone("records");
1519
+ for (const d of liveChildren(db, "documents", "database_id", id))
1520
+ emit(db, "documents", d, "database_id", null);
1429
1521
  db.query("DELETE FROM meta WHERE key = 'current_db' AND value = ?").run(id);
1430
1522
  return true;
1431
1523
  }
1524
+ function liveChildren(db, table, col, parentId) {
1525
+ return db.query(`SELECT id FROM ${table} WHERE ${col} = ? AND __deleted = 0`).all(parentId).map((r) => r.id);
1526
+ }
1432
1527
 
1433
1528
  // src/core/properties.ts
1434
1529
  init_ids();
@@ -1557,9 +1652,13 @@ function setPropertyWidth(db, id, width) {
1557
1652
  return updateProperty(db, id, { config: { ...cur.config ?? {}, width: w } });
1558
1653
  }
1559
1654
  function removeProperty(db, id) {
1560
- if (!getProperty(db, id))
1655
+ const prop = getProperty(db, id);
1656
+ if (!prop)
1561
1657
  return false;
1562
1658
  emit(db, "properties", id, "__deleted", 1);
1659
+ const rows = db.query("SELECT id FROM records WHERE database_id = ? AND __deleted = 0 AND data ->> ? IS NOT NULL").all(prop.database_id, id);
1660
+ for (const r of rows)
1661
+ emit(db, "records", r.id, id, undefined);
1563
1662
  return true;
1564
1663
  }
1565
1664
 
@@ -2225,8 +2324,15 @@ function deleteDocument(db, id) {
2225
2324
  if (!getDocument(db, id))
2226
2325
  return false;
2227
2326
  emit(db, "documents", id, "__deleted", 1);
2327
+ for (const b of liveChildIds(db, "doc_blocks", "doc_id", id))
2328
+ emit(db, "doc_blocks", b, "__deleted", 1);
2329
+ for (const c of liveChildIds(db, "documents", "parent_id", id))
2330
+ emit(db, "documents", c, "parent_id", null);
2228
2331
  return true;
2229
2332
  }
2333
+ function liveChildIds(db, table, col, parentId) {
2334
+ return db.query(`SELECT id FROM ${table} WHERE ${col} = ? AND __deleted = 0`).all(parentId).map((r) => r.id);
2335
+ }
2230
2336
  function countOccurrences(haystack, needle) {
2231
2337
  if (needle === "")
2232
2338
  return 0;
@@ -2239,26 +2345,112 @@ function countOccurrences(haystack, needle) {
2239
2345
  return n;
2240
2346
  }
2241
2347
  // src/core/search.ts
2348
+ init_crdt();
2242
2349
  var TEXT_TYPES = "('text','url','select','multi_select','date')";
2243
- function ensureIndex(db) {
2244
- if (!ftsAvailable(db))
2245
- return false;
2246
- const max = db.query("SELECT MAX(hlc) AS h FROM crdt_changes").get().h ?? "";
2247
- const indexed = db.query("SELECT value FROM meta WHERE key = 'search_hlc'").get()?.value ?? "";
2248
- if (max === indexed)
2249
- return true;
2250
- db.query("DELETE FROM search_fts").run();
2251
- for (const d of db.query("SELECT id, title, body, database_id FROM documents WHERE __deleted = 0").all()) {
2350
+ var SEARCH_INDEX_VERSION = "1";
2351
+ function readMeta(db, key) {
2352
+ return db.query("SELECT value FROM meta WHERE key = ?").get(key)?.value ?? null;
2353
+ }
2354
+ function writeMeta(db, key, value) {
2355
+ db.query("INSERT INTO meta (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(key, value);
2356
+ }
2357
+ function reindexDocument(db, id) {
2358
+ db.query("DELETE FROM search_fts WHERE kind = 'document' AND id = ?").run(id);
2359
+ const d = db.query("SELECT id, title, body, database_id FROM documents WHERE id = ? AND __deleted = 0").get(id);
2360
+ if (d)
2252
2361
  db.query("INSERT INTO search_fts (kind, id, database_id, title, body) VALUES ('document', ?, ?, ?, ?)").run(d.id, d.database_id, d.title ?? "", d.body ?? "");
2253
- }
2254
- for (const r of db.query(`SELECT r.id AS id, r.database_id AS database_id, group_concat(je.value, ' ') AS body
2362
+ }
2363
+ function recordBodyRows(db, where, ...args) {
2364
+ return db.query(`SELECT r.id AS id, r.database_id AS database_id, group_concat(je.value, ' ') AS body
2255
2365
  FROM records r, json_each(r.data) je
2256
2366
  JOIN properties p ON p.id = je.key AND p.__deleted = 0
2257
- WHERE r.__deleted = 0 AND p.type IN ${TEXT_TYPES}
2258
- GROUP BY r.id`).all()) {
2259
- db.query("INSERT INTO search_fts (kind, id, database_id, title, body) VALUES ('record', ?, ?, ?, ?)").run(r.id, r.database_id, r.id, r.body ?? "");
2367
+ WHERE ${where} AND r.__deleted = 0 AND p.type IN ${TEXT_TYPES}
2368
+ GROUP BY r.id`).all(...args);
2369
+ }
2370
+ function insertRecordRow(db, r) {
2371
+ db.query("INSERT INTO search_fts (kind, id, database_id, title, body) VALUES ('record', ?, ?, ?, ?)").run(r.id, r.database_id, r.id, r.body ?? "");
2372
+ }
2373
+ function reindexRecord(db, id) {
2374
+ db.query("DELETE FROM search_fts WHERE kind = 'record' AND id = ?").run(id);
2375
+ const r = recordBodyRows(db, "r.id = ?", id)[0];
2376
+ if (r)
2377
+ insertRecordRow(db, r);
2378
+ }
2379
+ function reindexDatabaseRecords(db, databaseId) {
2380
+ db.query("DELETE FROM search_fts WHERE kind = 'record' AND database_id = ?").run(databaseId);
2381
+ for (const r of recordBodyRows(db, "r.database_id = ?", databaseId))
2382
+ insertRecordRow(db, r);
2383
+ }
2384
+ function fullRebuild(db) {
2385
+ db.query("DELETE FROM search_fts").run();
2386
+ for (const d of db.query("SELECT id, title, body, database_id FROM documents WHERE __deleted = 0").all())
2387
+ db.query("INSERT INTO search_fts (kind, id, database_id, title, body) VALUES ('document', ?, ?, ?, ?)").run(d.id, d.database_id, d.title ?? "", d.body ?? "");
2388
+ for (const r of recordBodyRows(db, "1 = 1"))
2389
+ insertRecordRow(db, r);
2390
+ const max = db.query("SELECT MAX(rowid) AS m FROM crdt_changes").get().m ?? 0;
2391
+ writeMeta(db, "search_seq", String(max));
2392
+ writeMeta(db, "search_index_version", SEARCH_INDEX_VERSION);
2393
+ }
2394
+ function incrementalUpdate(db) {
2395
+ const cursor = Number(readMeta(db, "search_seq") ?? "0");
2396
+ const { changes, cursor: next } = changesAfterSeq(db, cursor);
2397
+ if (changes.length === 0)
2398
+ return;
2399
+ const docIds = new Set;
2400
+ const recordIds = new Set;
2401
+ const dbIds = new Set;
2402
+ for (const c of changes) {
2403
+ switch (c.dataset) {
2404
+ case "documents":
2405
+ docIds.add(c.row_id);
2406
+ break;
2407
+ case "doc_blocks": {
2408
+ const blk = db.query("SELECT doc_id FROM doc_blocks WHERE id = ?").get(c.row_id);
2409
+ if (blk?.doc_id)
2410
+ docIds.add(blk.doc_id);
2411
+ break;
2412
+ }
2413
+ case "records":
2414
+ recordIds.add(c.row_id);
2415
+ break;
2416
+ case "properties":
2417
+ if (c.col === "type" || c.col === "__deleted" || c.col === "database_id") {
2418
+ const p = db.query("SELECT database_id FROM properties WHERE id = ?").get(c.row_id);
2419
+ if (p?.database_id)
2420
+ dbIds.add(p.database_id);
2421
+ }
2422
+ break;
2423
+ }
2424
+ }
2425
+ for (const id of docIds)
2426
+ reindexDocument(db, id);
2427
+ for (const dbId of dbIds)
2428
+ reindexDatabaseRecords(db, dbId);
2429
+ for (const id of recordIds) {
2430
+ const r = db.query("SELECT database_id FROM records WHERE id = ?").get(id);
2431
+ if (r?.database_id && dbIds.has(r.database_id))
2432
+ continue;
2433
+ reindexRecord(db, id);
2260
2434
  }
2261
- db.query("INSERT INTO meta (key, value) VALUES ('search_hlc', ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value").run(max);
2435
+ writeMeta(db, "search_seq", String(next));
2436
+ }
2437
+ function ensureIndex(db) {
2438
+ if (!ftsAvailable(db))
2439
+ return false;
2440
+ const version = readMeta(db, "search_index_version");
2441
+ const seq = readMeta(db, "search_seq");
2442
+ db.transaction(() => {
2443
+ if (version !== SEARCH_INDEX_VERSION || seq === null)
2444
+ fullRebuild(db);
2445
+ else
2446
+ incrementalUpdate(db);
2447
+ })();
2448
+ return true;
2449
+ }
2450
+ function rebuildSearchIndex(db) {
2451
+ if (!ftsAvailable(db))
2452
+ return false;
2453
+ db.transaction(() => fullRebuild(db))();
2262
2454
  return true;
2263
2455
  }
2264
2456
  function ftsSearch(db, query, limit) {
@@ -16772,7 +16964,7 @@ function getServerConfig(db) {
16772
16964
  // package.json
16773
16965
  var package_default = {
16774
16966
  name: "@tensorix/metahub",
16775
- version: "0.1.3",
16967
+ version: "0.1.4",
16776
16968
  description: "Metahub core library and CLI",
16777
16969
  type: "module",
16778
16970
  main: "./dist/index.js",
@@ -16798,7 +16990,8 @@ var package_default = {
16798
16990
  build: "bun run scripts/build.ts",
16799
16991
  "build:binaries": "bun run scripts/compile-binaries.ts",
16800
16992
  prepublishOnly: "bun run build",
16801
- test: "bun test"
16993
+ test: "bun test",
16994
+ release: "bun run scripts/tag-release.ts"
16802
16995
  },
16803
16996
  dependencies: {
16804
16997
  "@clack/prompts": "^1.5.0",
@@ -16907,7 +17100,15 @@ function handle(fn) {
16907
17100
  }
16908
17101
  };
16909
17102
  }
17103
+ var VersionSchema = exports_external.object({ version: exports_external.string() });
16910
17104
  var webuiRoutes = [
17105
+ {
17106
+ method: "GET",
17107
+ path: "/api/version",
17108
+ summary: "Version of the running core (sidecar). Used by the desktop app's settings footer.",
17109
+ response: VersionSchema,
17110
+ handler: () => Response.json({ version: package_default.version })
17111
+ },
16911
17112
  {
16912
17113
  method: "GET",
16913
17114
  path: "/api/databases",
@@ -17635,6 +17836,16 @@ function unauthorized() {
17635
17836
  }
17636
17837
 
17637
17838
  // src/core/sync/server.ts
17839
+ class PortInUseError extends Error {
17840
+ port;
17841
+ host;
17842
+ constructor(port, host) {
17843
+ super(`port ${port} is already in use \u2014 another mh server may be running. ` + `Stop it, or start on a free port with --port <n>.`);
17844
+ this.port = port;
17845
+ this.host = host;
17846
+ this.name = "PortInUseError";
17847
+ }
17848
+ }
17638
17849
  function scalarHtml(specUrl) {
17639
17850
  return `<!doctype html><html><head>
17640
17851
  <meta charset="utf-8"><title>Metahub API</title>
@@ -17659,48 +17870,60 @@ function startServer(opts = {}) {
17659
17870
  ttlMs: DEFAULT_TTL_MS,
17660
17871
  graceMs: DEFAULT_GRACE_MS
17661
17872
  };
17662
- const server = Bun.serve({
17663
- port,
17664
- hostname: host,
17665
- async fetch(req) {
17666
- const url2 = new URL(req.url);
17667
- if (url2.pathname === SYNC_PATH) {
17668
- if (!acceptsSyncToken(req, url2, auth, db))
17669
- return unauthorized();
17670
- } else {
17671
- const exempt = url2.pathname === HEALTH_PATH || url2.pathname === RENEW_PATH || url2.pathname === PAIR_PATH;
17672
- if (!exempt && !hasValidToken(req, url2, auth)) {
17673
- return wantsHtml(req) ? new Response(unlockPage(), { headers: HTML_HEADERS }) : unauthorized();
17873
+ let server;
17874
+ try {
17875
+ server = Bun.serve({
17876
+ port,
17877
+ hostname: host,
17878
+ async fetch(req) {
17879
+ const url2 = new URL(req.url);
17880
+ if (url2.pathname === SYNC_PATH) {
17881
+ if (!acceptsSyncToken(req, url2, auth, db))
17882
+ return unauthorized();
17883
+ } else {
17884
+ const exempt = url2.pathname === HEALTH_PATH || url2.pathname === RENEW_PATH || url2.pathname === PAIR_PATH;
17885
+ if (!exempt && !hasValidToken(req, url2, auth)) {
17886
+ return wantsHtml(req) ? new Response(unlockPage(), { headers: HTML_HEADERS }) : unauthorized();
17887
+ }
17674
17888
  }
17889
+ if (url2.pathname === RENEW_PATH) {
17890
+ const r = renewToken(req, url2, auth);
17891
+ return r ? Response.json(r) : unauthorized();
17892
+ }
17893
+ if (req.method === "GET" && url2.pathname === "/docs.json") {
17894
+ return Response.json(buildOpenApi(package_default.version));
17895
+ }
17896
+ if (req.method === "GET" && url2.pathname === "/docs") {
17897
+ return withShim(new Response(scalarHtml("/docs.json"), { headers: HTML_HEADERS }), auth);
17898
+ }
17899
+ if (req.method === "GET" && (url2.pathname === "/" || url2.pathname === "/webui.js")) {
17900
+ const { serveWebui: serveWebui2 } = await Promise.resolve().then(() => (init_webui(), exports_webui));
17901
+ const res = await serveWebui2(req);
17902
+ if (res)
17903
+ return withShim(res, auth);
17904
+ }
17905
+ if (req.method === "GET" && url2.pathname.startsWith("/sites/")) {
17906
+ const { serveSite: serveSite2 } = await Promise.resolve().then(() => (init_sites_serve(), exports_sites_serve));
17907
+ const res = await serveSite2(req, ctx);
17908
+ if (res)
17909
+ return withShim(res, auth);
17910
+ }
17911
+ const route = routes.find((r) => r.method === req.method && r.path === url2.pathname);
17912
+ if (route)
17913
+ return route.handler(req, ctx);
17914
+ return new Response("not found", { status: 404 });
17675
17915
  }
17676
- if (url2.pathname === RENEW_PATH) {
17677
- const r = renewToken(req, url2, auth);
17678
- return r ? Response.json(r) : unauthorized();
17679
- }
17680
- if (req.method === "GET" && url2.pathname === "/docs.json") {
17681
- return Response.json(buildOpenApi(package_default.version));
17682
- }
17683
- if (req.method === "GET" && url2.pathname === "/docs") {
17684
- return withShim(new Response(scalarHtml("/docs.json"), { headers: HTML_HEADERS }), auth);
17685
- }
17686
- if (req.method === "GET" && (url2.pathname === "/" || url2.pathname === "/webui.js")) {
17687
- const { serveWebui: serveWebui2 } = await Promise.resolve().then(() => (init_webui(), exports_webui));
17688
- const res = await serveWebui2(req);
17689
- if (res)
17690
- return withShim(res, auth);
17691
- }
17692
- if (req.method === "GET" && url2.pathname.startsWith("/sites/")) {
17693
- const { serveSite: serveSite2 } = await Promise.resolve().then(() => (init_sites_serve(), exports_sites_serve));
17694
- const res = await serveSite2(req, ctx);
17695
- if (res)
17696
- return withShim(res, auth);
17697
- }
17698
- const route = routes.find((r) => r.method === req.method && r.path === url2.pathname);
17699
- if (route)
17700
- return route.handler(req, ctx);
17701
- return new Response("not found", { status: 404 });
17916
+ });
17917
+ } catch (e) {
17918
+ const code = e?.code;
17919
+ if (code === "EADDRINUSE") {
17920
+ throw new PortInUseError(port, host);
17702
17921
  }
17703
- });
17922
+ if (code === "EACCES") {
17923
+ throw new Error(`permission denied binding ${host}:${port} \u2014 ports below 1024 need elevated privileges; pick a higher port with --port`);
17924
+ }
17925
+ throw e;
17926
+ }
17704
17927
  let timer = null;
17705
17928
  if (autoSync && syncIntervalMs > 0) {
17706
17929
  timer = setInterval(() => {
@@ -17709,12 +17932,17 @@ function startServer(opts = {}) {
17709
17932
  timer.unref?.();
17710
17933
  }
17711
17934
  const active = activeToken(auth);
17935
+ const authMode = opts.debug ? "disabled" : opts.token ? "static" : "managed";
17712
17936
  return {
17713
17937
  server,
17714
17938
  node,
17715
17939
  port: server.port ?? port,
17940
+ host,
17716
17941
  token: active?.token ?? null,
17717
17942
  exp: active?.exp ?? null,
17943
+ authMode,
17944
+ autoSync: Boolean(autoSync && syncIntervalMs > 0),
17945
+ syncIntervalMs,
17718
17946
  stop() {
17719
17947
  if (timer)
17720
17948
  clearInterval(timer);
@@ -17741,6 +17969,7 @@ export {
17741
17969
  resolveCandidates,
17742
17970
  removeProperty,
17743
17971
  reconcile,
17972
+ rebuildSearchIndex,
17744
17973
  randomSuffix,
17745
17974
  putFile,
17746
17975
  putBlob,
@@ -17810,6 +18039,7 @@ export {
17810
18039
  SyncRequestSchema,
17811
18040
  SYNC_PATH,
17812
18041
  RENEW_PATH,
18042
+ PortInUseError,
17813
18043
  PairResponseSchema,
17814
18044
  PairRequestSchema,
17815
18045
  PROP_TYPES,
@@ -17819,4 +18049,4 @@ export {
17819
18049
  ChangeSchema
17820
18050
  };
17821
18051
 
17822
- //# debugId=52E20C0E56A04E8A64756E2164756E21
18052
+ //# debugId=539C6C8168968A4864756E2164756E21