@kky42/pievo-server 1.0.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/.output/nitro.json +17 -0
- package/.output/public/assets/CodeField-dOzyFQNH.js +34 -0
- package/.output/public/assets/LoopView-B4H9QibC.js +55 -0
- package/.output/public/assets/Modal-D33gNSgx.js +1 -0
- package/.output/public/assets/SignIn-SHuRRyOv.js +1 -0
- package/.output/public/assets/actionUi-ChGGALzg.js +1 -0
- package/.output/public/assets/app-DElSo_jy.css +2 -0
- package/.output/public/assets/artifactView-DFuubXLJ.js +66 -0
- package/.output/public/assets/index-DfpTWRSz.js +12 -0
- package/.output/public/assets/invite._token-DJtd-XE2.js +1 -0
- package/.output/public/assets/invite._token-T8oo4Qtw.js +1 -0
- package/.output/public/assets/jsx-runtime-BseJUIpC.js +1 -0
- package/.output/public/assets/lifecycleUi-DKkChdnU.js +1 -0
- package/.output/public/assets/loopApi-BM2nj71x.js +3 -0
- package/.output/public/assets/loops._loopId-B19Jw7jC.js +5 -0
- package/.output/public/assets/loops._loopId_.runs._runId-_CflHV38.js +3 -0
- package/.output/public/assets/notifyFns-DCubjpRy.js +1 -0
- package/.output/public/assets/preload-helper-CKUiEq3b.js +3 -0
- package/.output/public/assets/routes-B9tgli5f.js +1 -0
- package/.output/public/assets/routes-CTtlM_qt.js +1 -0
- package/.output/public/assets/t._teamId-Bm21mngW.js +1 -0
- package/.output/public/assets/t._teamId-gR7BVKkR.js +1 -0
- package/.output/public/assets/ui-Dp88qUWh.js +1 -0
- package/.output/public/assets/useRouter-DsjH8G0p.js +1 -0
- package/.output/public/favicon.svg +12 -0
- package/.output/public/fonts/GeistPixel-Square.woff2 +0 -0
- package/.output/server/_chunks/ssr-renderer.mjs +26 -0
- package/.output/server/_libs/@aws-crypto/crc32+[...].mjs +419 -0
- package/.output/server/_libs/@aws-sdk/checksums+[...].mjs +10732 -0
- package/.output/server/_libs/@aws-sdk/client-s3+[...].mjs +9475 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-http+[...].mjs +137 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-ini+[...].mjs +440 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-process+[...].mjs +62 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-sso+[...].mjs +818 -0
- package/.output/server/_libs/@aws-sdk/credential-provider-web-identity+[...].mjs +59 -0
- package/.output/server/_libs/@base-ui/react+[...].mjs +11125 -0
- package/.output/server/_libs/@codemirror/autocomplete+[...].mjs +19713 -0
- package/.output/server/_libs/@codemirror/lang-css+[...].mjs +2636 -0
- package/.output/server/_libs/@codemirror/lang-html+[...].mjs +2247 -0
- package/.output/server/_libs/@codemirror/lang-json+[...].mjs +79 -0
- package/.output/server/_libs/@reduxjs/toolkit+[...].mjs +1736 -0
- package/.output/server/_libs/@smithy/credential-provider-imds+[...].mjs +342 -0
- package/.output/server/_libs/@tanstack/react-router+[...].mjs +14300 -0
- package/.output/server/_libs/@uiw/codemirror-extensions-basic-setup+[...].mjs +76 -0
- package/.output/server/_libs/atomic-sleep.mjs +27 -0
- package/.output/server/_libs/aws-crypto__crc32c.mjs +314 -0
- package/.output/server/_libs/aws-sdk__nested-clients.mjs +2671 -0
- package/.output/server/_libs/babel__runtime.mjs +30 -0
- package/.output/server/_libs/clsx.mjs +16 -0
- package/.output/server/_libs/codemirror__commands.mjs +1725 -0
- package/.output/server/_libs/codemirror__lint.mjs +565 -0
- package/.output/server/_libs/codemirror__search.mjs +1138 -0
- package/.output/server/_libs/codemirror__theme-one-dark.mjs +161 -0
- package/.output/server/_libs/colorette.mjs +129 -0
- package/.output/server/_libs/croner.mjs +735 -0
- package/.output/server/_libs/d3-array.mjs +231 -0
- package/.output/server/_libs/d3-color.mjs +330 -0
- package/.output/server/_libs/d3-format.mjs +252 -0
- package/.output/server/_libs/d3-interpolate.mjs +163 -0
- package/.output/server/_libs/d3-path.mjs +77 -0
- package/.output/server/_libs/d3-scale+[...].mjs +1907 -0
- package/.output/server/_libs/d3-shape.mjs +689 -0
- package/.output/server/_libs/dateformat.mjs +341 -0
- package/.output/server/_libs/decimal.js-light.mjs +884 -0
- package/.output/server/_libs/diff.mjs +732 -0
- package/.output/server/_libs/dom-serializer+[...].mjs +708 -0
- package/.output/server/_libs/domhandler.mjs +461 -0
- package/.output/server/_libs/dompurify.mjs +2111 -0
- package/.output/server/_libs/domutils.mjs +868 -0
- package/.output/server/_libs/drizzle-orm+postgres.mjs +7689 -0
- package/.output/server/_libs/electric-sql__pglite.mjs +14674 -0
- package/.output/server/_libs/end-of-stream+once+wrappy.mjs +145 -0
- package/.output/server/_libs/es-toolkit.mjs +1737 -0
- package/.output/server/_libs/eventemitter3.mjs +236 -0
- package/.output/server/_libs/fast-copy.mjs +285 -0
- package/.output/server/_libs/fast-safe-stringify.mjs +172 -0
- package/.output/server/_libs/h3+rou3+srvx.mjs +1201 -0
- package/.output/server/_libs/html-dom-parser+htmlparser2.mjs +1560 -0
- package/.output/server/_libs/html-react-parser+[...].mjs +1360 -0
- package/.output/server/_libs/initdb.wasm +0 -0
- package/.output/server/_libs/marked.mjs +1548 -0
- package/.output/server/_libs/on-exit-leak-free.mjs +80 -0
- package/.output/server/_libs/pglite.data +37667 -8
- package/.output/server/_libs/pglite.wasm +0 -0
- package/.output/server/_libs/pino+[...].mjs +3196 -0
- package/.output/server/_libs/pino-abstract-transport+split2.mjs +194 -0
- package/.output/server/_libs/pino-pretty+[...].mjs +1623 -0
- package/.output/server/_libs/pinojs__redact.mjs +280 -0
- package/.output/server/_libs/react-redux+[...].mjs +205 -0
- package/.output/server/_libs/recharts+victory-vendor.mjs +15875 -0
- package/.output/server/_libs/tanstack__history.mjs +342 -0
- package/.output/server/_libs/ufo.mjs +64 -0
- package/.output/server/_libs/uiw__codemirror-themes.mjs +32 -0
- package/.output/server/_libs/uiw__react-codemirror.mjs +354 -0
- package/.output/server/_runtime.mjs +37 -0
- package/.output/server/_ssr/CodeField-tm4rr6G3.mjs +143 -0
- package/.output/server/_ssr/DashboardView-CC7htv28.mjs +2795 -0
- package/.output/server/_ssr/LoopPlaybook-BXH8mhiX.mjs +2105 -0
- package/.output/server/_ssr/LoopView-DCugEbHx.mjs +1106 -0
- package/.output/server/_ssr/Modal-DpKZHLZK.mjs +49 -0
- package/.output/server/_ssr/SignIn-dTndU6Hw.mjs +67 -0
- package/.output/server/_ssr/actionUi-CZbEixbf.mjs +119 -0
- package/.output/server/_ssr/adapters-BS8XosjF.mjs +130 -0
- package/.output/server/_ssr/artifactFiles-Cagtj7J0.mjs +61 -0
- package/.output/server/_ssr/artifactKind-BW0isV8L.mjs +37 -0
- package/.output/server/_ssr/artifactView-DS4O22wl.mjs +304 -0
- package/.output/server/_ssr/artifacts-DngKyW2u.mjs +2 -0
- package/.output/server/_ssr/auth-DY1DuYZd.mjs +38429 -0
- package/.output/server/_ssr/boot-BbtG0ImW.mjs +9010 -0
- package/.output/server/_ssr/boot-CMHTxQpJ.mjs +2 -0
- package/.output/server/_ssr/bun-sqlite-dialect-BW9W1_Ps-CU1Spd6z.mjs +162 -0
- package/.output/server/_ssr/core-RrmWoKne.mjs +5 -0
- package/.output/server/_ssr/createServerRpc-BD8Xn_0_.mjs +12 -0
- package/.output/server/_ssr/d1-sqlite-dialect-BLC8LXE6-DfG7tB8s.mjs +112 -0
- package/.output/server/_ssr/db-DWAuZq1o.mjs +2 -0
- package/.output/server/_ssr/dist-BIxFFVZg.mjs +342 -0
- package/.output/server/_ssr/empty-plugin-adapters-DKUlnwwl.mjs +5 -0
- package/.output/server/_ssr/factory-Blq0DYfT.mjs +6903 -0
- package/.output/server/_ssr/invite._token-BRCo9LGB.mjs +36 -0
- package/.output/server/_ssr/invite._token-DJxGLILJ.mjs +28 -0
- package/.output/server/_ssr/invite._token-NewFt27g.mjs +92 -0
- package/.output/server/_ssr/kysely-adapter-D3XTe64J.mjs +2 -0
- package/.output/server/_ssr/kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs +19 -0
- package/.output/server/_ssr/lifecycleUi-C9lg1r3r.mjs +38 -0
- package/.output/server/_ssr/logger-Dw82jNjH.mjs +2 -0
- package/.output/server/_ssr/loopApi-BtfkZQYK.mjs +532 -0
- package/.output/server/_ssr/loopApi-Cxe8WyOB.mjs +105 -0
- package/.output/server/_ssr/loops._loopId-7NQJPB9W.mjs +30 -0
- package/.output/server/_ssr/loops._loopId-DhnArGdL.mjs +1635 -0
- package/.output/server/_ssr/loops._loopId_.runs._runId-Bvuo2nki.mjs +29 -0
- package/.output/server/_ssr/loops._loopId_.runs._runId-Dip5Xk-q.mjs +674 -0
- package/.output/server/_ssr/machineFns-Dvr5ICUy.mjs +266 -0
- package/.output/server/_ssr/node-sqlite-dialect-DhyOpJTX.mjs +162 -0
- package/.output/server/_ssr/notifyFns-BcMRY5kP.mjs +118 -0
- package/.output/server/_ssr/notifyFns-Q458pZmE.mjs +580 -0
- package/.output/server/_ssr/router-J8KZ30xw.mjs +678 -0
- package/.output/server/_ssr/routes-Bcs4T1ox.mjs +28 -0
- package/.output/server/_ssr/routes-BoGrcf-b.mjs +43 -0
- package/.output/server/_ssr/routes-D4am3Zff.mjs +28 -0
- package/.output/server/_ssr/runDiff-CpEFqo7G.mjs +113 -0
- package/.output/server/_ssr/ssr.mjs +5837 -0
- package/.output/server/_ssr/start-4ifArtKx.mjs +4 -0
- package/.output/server/_ssr/store-b3JcQ08F.mjs +2 -0
- package/.output/server/_ssr/t._teamId-CeUhzgzT.mjs +32 -0
- package/.output/server/_ssr/t._teamId-DR-hQK7o.mjs +47 -0
- package/.output/server/_ssr/t._teamId-Dy_McbRt.mjs +31 -0
- package/.output/server/_ssr/teamCookie-B7hLOIie.mjs +10 -0
- package/.output/server/_ssr/teamFns-BIDnsg2A.mjs +473 -0
- package/.output/server/_ssr/teamFns-DA4ovI5g.mjs +33 -0
- package/.output/server/_ssr/tokens-ytd60FUt.mjs +2 -0
- package/.output/server/_ssr/ui-Dej2qjuS.mjs +267 -0
- package/.output/server/_tanstack-start-manifest_v-CVS6c7re.mjs +95 -0
- package/.output/server/drizzle/0000_round_marauders.sql +193 -0
- package/.output/server/drizzle/0001_naive_silver_fox.sql +25 -0
- package/.output/server/drizzle/0002_funny_sage.sql +12 -0
- package/.output/server/drizzle/0003_optimal_slapstick.sql +102 -0
- package/.output/server/drizzle/0004_remove_grok_agent.sql +5 -0
- package/.output/server/drizzle/0005_heavy_gauntlet.sql +8 -0
- package/.output/server/drizzle/0006_tranquil_sharon_carter.sql +1 -0
- package/.output/server/drizzle/0007_faulty_starbolt.sql +30 -0
- package/.output/server/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
- package/.output/server/drizzle/meta/0000_snapshot.json +1333 -0
- package/.output/server/drizzle/meta/0001_snapshot.json +1498 -0
- package/.output/server/drizzle/meta/0002_snapshot.json +1576 -0
- package/.output/server/drizzle/meta/0003_snapshot.json +1666 -0
- package/.output/server/drizzle/meta/0005_snapshot.json +1666 -0
- package/.output/server/drizzle/meta/0006_snapshot.json +1672 -0
- package/.output/server/drizzle/meta/0007_snapshot.json +1787 -0
- package/.output/server/drizzle/meta/_journal.json +69 -0
- package/.output/server/index.mjs +464 -0
- package/.output/server/node_modules/tslib/modules/index.js +70 -0
- package/.output/server/node_modules/tslib/modules/package.json +3 -0
- package/.output/server/node_modules/tslib/package.json +47 -0
- package/.output/server/node_modules/tslib/tslib.js +484 -0
- package/.output/server/package.json +9 -0
- package/LICENSE +21 -0
- package/drizzle/0000_round_marauders.sql +193 -0
- package/drizzle/0001_naive_silver_fox.sql +25 -0
- package/drizzle/0002_funny_sage.sql +12 -0
- package/drizzle/0003_optimal_slapstick.sql +102 -0
- package/drizzle/0004_remove_grok_agent.sql +5 -0
- package/drizzle/0005_heavy_gauntlet.sql +8 -0
- package/drizzle/0006_tranquil_sharon_carter.sql +1 -0
- package/drizzle/0007_faulty_starbolt.sql +30 -0
- package/drizzle/0008_durable_lifecycle_evidence.sql +15 -0
- package/drizzle/meta/0000_snapshot.json +1333 -0
- package/drizzle/meta/0001_snapshot.json +1498 -0
- package/drizzle/meta/0002_snapshot.json +1576 -0
- package/drizzle/meta/0003_snapshot.json +1666 -0
- package/drizzle/meta/0005_snapshot.json +1666 -0
- package/drizzle/meta/0006_snapshot.json +1672 -0
- package/drizzle/meta/0007_snapshot.json +1787 -0
- package/drizzle/meta/_journal.json +69 -0
- package/package.json +84 -0
- package/scripts/pievo-server.mjs +390 -0
- package/scripts/prestart.mjs +66 -0
- package/scripts/server-cli-lib.mjs +451 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { $t as updateMachine, At as machineIdFromToken, D as createMachine$1, F as ensureServer, Kt as sha256, Mt as mintDeviceToken, N as deleteMachine$1, Rt as rememberConnectKey, Z as getMachine, bt as listMachines$1, kt as loopsForMachine, xt as listMachinesForTeam } from "./boot-BbtG0ImW.mjs";
|
|
2
|
+
import { n as createServerFn } from "./ssr.mjs";
|
|
3
|
+
import { requestScope } from "./auth-DY1DuYZd.mjs";
|
|
4
|
+
import { t as createServerRpc } from "./createServerRpc-BD8Xn_0_.mjs";
|
|
5
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/machineScope-2h-fcKmG.js
|
|
6
|
+
/**
|
|
7
|
+
* Whether a machine is visible/actionable in the request scope. Mirrors
|
|
8
|
+
* listMachines: open mode sees everything; otherwise the requester must own the
|
|
9
|
+
* machine or share the active team with its owner. `teamMachineIds` is a THUNK
|
|
10
|
+
* (the team set needs a DB join) invoked only after the owner check misses — the
|
|
11
|
+
* hot path (machineStatus polls every ~2.5s while the connect dialog is open,
|
|
12
|
+
* usually by the owner) pays no query.
|
|
13
|
+
*/
|
|
14
|
+
function machineInScope(m, scope, teamMachineIds) {
|
|
15
|
+
if (!scope.enforce) return true;
|
|
16
|
+
if (!scope.userId) return false;
|
|
17
|
+
if (m.userId === scope.userId) return true;
|
|
18
|
+
return teamMachineIds().has(m.id);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Whether the machine's PLAINTEXT device token may be serialized to this
|
|
22
|
+
* requester. Owner-only under the gate — the token fully impersonates the
|
|
23
|
+
* machine, so even a teammate/admin who may see (or delete) the row gets
|
|
24
|
+
* `token: null`. Open mode keeps the v1 behavior (token shown, e.g. for the
|
|
25
|
+
* reconnect command).
|
|
26
|
+
*/
|
|
27
|
+
function tokenVisibleTo(m, scope) {
|
|
28
|
+
return !scope.enforce || m.userId === scope.userId;
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/machineFns-Dvr5ICUy.js
|
|
32
|
+
/**
|
|
33
|
+
* Latest published @kky42/pievo version — a cached, fail-silent lookup of the
|
|
34
|
+
* npm dist-tag `latest`, so the web can tell a user their daemon is outdated and
|
|
35
|
+
* show the exact update command.
|
|
36
|
+
*
|
|
37
|
+
* Zero-exec invariant: this is a plain HTTP GET against the public npm registry —
|
|
38
|
+
* the server runs no LLM and executes no user code. It NEVER surfaces an error:
|
|
39
|
+
* if npm is unreachable/slow/garbage, the cache simply stays as-is (undefined at
|
|
40
|
+
* first) and the web shows no update hint. Bounded timeout + ~1h in-memory cache
|
|
41
|
+
* so the machine-list hot path never blocks on the network.
|
|
42
|
+
*
|
|
43
|
+
* The fetch is injectable (mirroring the gateway's injectable notifier/blobStore)
|
|
44
|
+
* so tests need no network: construct a `LatestDaemonVersion` with a fake fetch
|
|
45
|
+
* and `now`, or call the pure `fetchNpmLatest` directly.
|
|
46
|
+
*/
|
|
47
|
+
var NPM_URL = "https://registry.npmjs.org/@kky42/pievo";
|
|
48
|
+
var DEFAULT_TTL_MS = 3600 * 1e3;
|
|
49
|
+
var FETCH_TIMEOUT_MS = 4e3;
|
|
50
|
+
/**
|
|
51
|
+
* One npm `latest` read — bounded + fail-silent. Returns the version string or
|
|
52
|
+
* null (unreachable/timeout/malformed). Pure w.r.t. the injected fetch, so it's
|
|
53
|
+
* directly unit-testable with no network.
|
|
54
|
+
*/
|
|
55
|
+
async function fetchNpmLatest(fetchImpl, timeoutMs = FETCH_TIMEOUT_MS) {
|
|
56
|
+
const ctrl = new AbortController();
|
|
57
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
58
|
+
try {
|
|
59
|
+
const res = await fetchImpl(NPM_URL, {
|
|
60
|
+
headers: { accept: "application/vnd.npm.install-v1+json" },
|
|
61
|
+
signal: ctrl.signal
|
|
62
|
+
});
|
|
63
|
+
if (!res.ok) return null;
|
|
64
|
+
const latest = (await res.json())?.["dist-tags"]?.latest;
|
|
65
|
+
return typeof latest === "string" && latest.trim() ? latest.trim() : null;
|
|
66
|
+
} catch {
|
|
67
|
+
return null;
|
|
68
|
+
} finally {
|
|
69
|
+
clearTimeout(timer);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* In-memory cached accessor. `get()` returns the currently cached value (null
|
|
74
|
+
* until the first successful fetch) and, when the cache is stale, kicks off a
|
|
75
|
+
* background refresh — it never blocks the caller and never throws. A single
|
|
76
|
+
* refresh is in-flight at a time (concurrent `get()`s share it).
|
|
77
|
+
*/
|
|
78
|
+
var LatestDaemonVersion = class {
|
|
79
|
+
fetchImpl;
|
|
80
|
+
ttlMs;
|
|
81
|
+
now;
|
|
82
|
+
cached = null;
|
|
83
|
+
fetchedAt = 0;
|
|
84
|
+
inflight = null;
|
|
85
|
+
constructor(fetchImpl = fetch, ttlMs = DEFAULT_TTL_MS, now = Date.now) {
|
|
86
|
+
this.fetchImpl = fetchImpl;
|
|
87
|
+
this.ttlMs = ttlMs;
|
|
88
|
+
this.now = now;
|
|
89
|
+
}
|
|
90
|
+
/** Cached latest version, refreshing in the background when stale. Non-blocking. */
|
|
91
|
+
get() {
|
|
92
|
+
if (this.now() - this.fetchedAt >= this.ttlMs) this.refresh();
|
|
93
|
+
return this.cached;
|
|
94
|
+
}
|
|
95
|
+
/** Force a refresh and resolve with the (possibly unchanged) cached value.
|
|
96
|
+
* Await-able for tests; production callers use `get()`. Never throws. */
|
|
97
|
+
async refresh() {
|
|
98
|
+
if (this.inflight) return this.inflight;
|
|
99
|
+
this.inflight = (async () => {
|
|
100
|
+
const v = await fetchNpmLatest(this.fetchImpl);
|
|
101
|
+
this.fetchedAt = this.now();
|
|
102
|
+
if (v) this.cached = v;
|
|
103
|
+
return this.cached;
|
|
104
|
+
})();
|
|
105
|
+
try {
|
|
106
|
+
return await this.inflight;
|
|
107
|
+
} finally {
|
|
108
|
+
this.inflight = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
/** Process-wide singleton the machine server fns read (fail-silent, cached). */
|
|
113
|
+
var latestDaemonVersion = new LatestDaemonVersion();
|
|
114
|
+
/**
|
|
115
|
+
* Machine management server functions. Connect flow (two acts):
|
|
116
|
+
* 1. createMachine() → mint a token, create a PENDING (unnamed) row, return
|
|
117
|
+
* {id, token}. The UI shows the connect command + "waiting…".
|
|
118
|
+
* 2. the daemon connects → poll records online + hostname/platform/arch. The
|
|
119
|
+
* UI polls machineStatus(id); once connected it shows the name field
|
|
120
|
+
* (prefilled with the hostname). finalizeMachine({id,name}) names it →
|
|
121
|
+
* it appears in the list. cancelMachine(id) drops a pending row.
|
|
122
|
+
*
|
|
123
|
+
* Scoping: when the auth gate is on, every fn requires a signed-in user, and a
|
|
124
|
+
* machine is visible/actionable only when the requester owns it, its owner is a
|
|
125
|
+
* member of the active team, or the scope is the admin "All teams" view (the
|
|
126
|
+
* same rule listMachines filters by). The PLAINTEXT device token is serialized
|
|
127
|
+
* ONLY to the machine's owner — it fully impersonates the machine (poll /
|
|
128
|
+
* create-loop / log), so a teammate who can see the row must never exfiltrate
|
|
129
|
+
* it. Open mode (gate off) keeps the shared workspace: everyone sees/manages
|
|
130
|
+
* all machines, tokens included. No workdir jail (fully open) for now.
|
|
131
|
+
*/
|
|
132
|
+
/** Ids of the machines membership-visible in the scope's active team (the same
|
|
133
|
+
* set listMachines serves). Empty when the scope needs no team check (open
|
|
134
|
+
* mode or signed-out — machineInScope settles those before ever invoking its
|
|
135
|
+
* team-set thunk). */
|
|
136
|
+
async function teamMachineIds(scope) {
|
|
137
|
+
if (!scope.enforce || !scope.userId) return /* @__PURE__ */ new Set();
|
|
138
|
+
return new Set((await listMachinesForTeam(scope.teamId)).map((m) => m.id));
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Resolve a machine and authorize it against the request scope (the machine-fn
|
|
142
|
+
* twin of loopApi's `ownedLoop`). `machine` is undefined when it's missing OR
|
|
143
|
+
* out of scope — callers treat both as "not found" so existence never leaks.
|
|
144
|
+
* The scope rides along so callers don't re-run requestScope (a second session
|
|
145
|
+
* decrypt); the team-set thunk keeps the owner fast path query-free.
|
|
146
|
+
*/
|
|
147
|
+
async function scopedMachine(id) {
|
|
148
|
+
const scope = await requestScope();
|
|
149
|
+
const m = await getMachine(id);
|
|
150
|
+
const teamIds = await teamMachineIds(scope);
|
|
151
|
+
return {
|
|
152
|
+
scope,
|
|
153
|
+
machine: m && machineInScope(m, scope, () => teamIds) ? m : void 0
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
async function toSummary(m, scope) {
|
|
157
|
+
return {
|
|
158
|
+
id: m.id,
|
|
159
|
+
name: m.name,
|
|
160
|
+
online: !!m.online,
|
|
161
|
+
lastSeen: m.lastSeen ?? null,
|
|
162
|
+
hostname: m.hostname ?? null,
|
|
163
|
+
platform: m.platform ?? null,
|
|
164
|
+
arch: m.arch ?? null,
|
|
165
|
+
daemonVersion: m.daemonVersion ?? null,
|
|
166
|
+
daemonProtocol: m.daemonProtocol ?? null,
|
|
167
|
+
latestDaemonVersion: latestDaemonVersion.get(),
|
|
168
|
+
token: tokenVisibleTo(m, scope) ? m.token ?? null : null,
|
|
169
|
+
loopCount: (await loopsForMachine(m.id)).length
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/** Named machines only (pending/unnamed rows are mid-connect). Scoped to the
|
|
173
|
+
* given/active team when the gate is on; the full shared list in open mode. An
|
|
174
|
+
* explicit `teamId` (the `/t/<id>` route) scopes this request independent of the
|
|
175
|
+
* cookie, so a tab on /t/A and one on /t/B list different machines at once. */
|
|
176
|
+
var listMachines_createServerFn_handler = createServerRpc({
|
|
177
|
+
id: "aa46310016bb8a58b273a648ffd498c87f1f450d12827e30110a3b83ba6a27d9",
|
|
178
|
+
name: "listMachines",
|
|
179
|
+
filename: "src/server/machineFns.ts"
|
|
180
|
+
}, (opts) => listMachines.__executeServer(opts));
|
|
181
|
+
var listMachines = createServerFn({ method: "GET" }).validator((teamId) => teamId).handler(listMachines_createServerFn_handler, async ({ data: teamId }) => {
|
|
182
|
+
await ensureServer();
|
|
183
|
+
const scope = await requestScope(teamId);
|
|
184
|
+
const { enforce, userId, teamId: active } = scope;
|
|
185
|
+
if (enforce && !userId) return [];
|
|
186
|
+
const list = enforce ? await listMachinesForTeam(active) : await listMachines$1();
|
|
187
|
+
return Promise.all(list.filter((m) => m.name.trim()).map((m) => toSummary(m, scope)));
|
|
188
|
+
});
|
|
189
|
+
var createMachine_createServerFn_handler = createServerRpc({
|
|
190
|
+
id: "ed679b4e1e05e903a5d4ba4a70d9b9d883991ab22ed59b4d2d69078941818415",
|
|
191
|
+
name: "createMachine",
|
|
192
|
+
filename: "src/server/machineFns.ts"
|
|
193
|
+
}, (opts) => createMachine.__executeServer(opts));
|
|
194
|
+
var createMachine = createServerFn({ method: "POST" }).validator((teamId) => teamId).handler(createMachine_createServerFn_handler, async ({ data: teamId }) => {
|
|
195
|
+
await ensureServer();
|
|
196
|
+
const { enforce, userId, teamId: active } = await requestScope(teamId);
|
|
197
|
+
if (enforce && !userId) return { error: "not signed in" };
|
|
198
|
+
const token = mintDeviceToken();
|
|
199
|
+
const id = machineIdFromToken(token);
|
|
200
|
+
const owner = userId ?? "shared";
|
|
201
|
+
await rememberConnectKey(token, {
|
|
202
|
+
userId: owner,
|
|
203
|
+
teamId: active
|
|
204
|
+
});
|
|
205
|
+
await createMachine$1({
|
|
206
|
+
id,
|
|
207
|
+
userId: owner,
|
|
208
|
+
teamId: active,
|
|
209
|
+
name: "",
|
|
210
|
+
tokenHash: sha256(token),
|
|
211
|
+
token,
|
|
212
|
+
online: false
|
|
213
|
+
});
|
|
214
|
+
return {
|
|
215
|
+
id,
|
|
216
|
+
token
|
|
217
|
+
};
|
|
218
|
+
});
|
|
219
|
+
var machineStatus_createServerFn_handler = createServerRpc({
|
|
220
|
+
id: "169566e7637a22599b4eb32ee3775574e99677406922bbef7482a102036c33dd",
|
|
221
|
+
name: "machineStatus",
|
|
222
|
+
filename: "src/server/machineFns.ts"
|
|
223
|
+
}, (opts) => machineStatus.__executeServer(opts));
|
|
224
|
+
var machineStatus = createServerFn({ method: "GET" }).validator((id) => id).handler(machineStatus_createServerFn_handler, async ({ data: id }) => {
|
|
225
|
+
await ensureServer();
|
|
226
|
+
const { scope, machine } = await scopedMachine(id);
|
|
227
|
+
return machine ? toSummary(machine, scope) : null;
|
|
228
|
+
});
|
|
229
|
+
var finalizeMachine_createServerFn_handler = createServerRpc({
|
|
230
|
+
id: "27d7eba0b6a2257949392fdd56057275a5c5366484ae01faf3b5897a225ecd83",
|
|
231
|
+
name: "finalizeMachine",
|
|
232
|
+
filename: "src/server/machineFns.ts"
|
|
233
|
+
}, (opts) => finalizeMachine.__executeServer(opts));
|
|
234
|
+
var finalizeMachine = createServerFn({ method: "POST" }).validator((d) => d).handler(finalizeMachine_createServerFn_handler, async ({ data }) => {
|
|
235
|
+
await ensureServer();
|
|
236
|
+
const name = data.name?.trim();
|
|
237
|
+
if (!name) return { ok: false };
|
|
238
|
+
const { machine } = await scopedMachine(data.id);
|
|
239
|
+
if (!machine) return { ok: false };
|
|
240
|
+
return { ok: !!await updateMachine(data.id, { name }) };
|
|
241
|
+
});
|
|
242
|
+
var deleteMachine_createServerFn_handler = createServerRpc({
|
|
243
|
+
id: "a6384dc7154d9930422d29396f5de64b3ac69c62ad3824bc4a22d745fc07b293",
|
|
244
|
+
name: "deleteMachine",
|
|
245
|
+
filename: "src/server/machineFns.ts"
|
|
246
|
+
}, (opts) => deleteMachine.__executeServer(opts));
|
|
247
|
+
var deleteMachine = createServerFn({ method: "POST" }).validator((id) => id).handler(deleteMachine_createServerFn_handler, async ({ data: id }) => {
|
|
248
|
+
await ensureServer();
|
|
249
|
+
const { scope, machine } = await scopedMachine(id);
|
|
250
|
+
if (scope.enforce && !scope.userId) return {
|
|
251
|
+
ok: false,
|
|
252
|
+
error: "unauthorized"
|
|
253
|
+
};
|
|
254
|
+
if (!machine) return {
|
|
255
|
+
ok: false,
|
|
256
|
+
error: "machine not found"
|
|
257
|
+
};
|
|
258
|
+
const loops = await loopsForMachine(id);
|
|
259
|
+
if (loops.length > 0) return {
|
|
260
|
+
ok: false,
|
|
261
|
+
error: `This machine still has ${loops.length} loop${loops.length === 1 ? "" : "s"} — delete ${loops.length === 1 ? "it" : "them"} first.`
|
|
262
|
+
};
|
|
263
|
+
return { ok: await deleteMachine$1(id) };
|
|
264
|
+
});
|
|
265
|
+
//#endregion
|
|
266
|
+
export { createMachine_createServerFn_handler, deleteMachine_createServerFn_handler, finalizeMachine_createServerFn_handler, listMachines_createServerFn_handler, machineStatus_createServerFn_handler };
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { n as DefaultQueryCompiler, o as CompiledQuery, s as sql$1 } from "./auth-DY1DuYZd.mjs";
|
|
2
|
+
import { n as DEFAULT_MIGRATION_TABLE, t as DEFAULT_MIGRATION_LOCK_TABLE } from "./kysely-migration-tables-JkVUjPF_-bPAX9LR_.mjs";
|
|
3
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/node-sqlite-dialect-DhyOpJTX.js
|
|
4
|
+
var NodeSqliteAdapter = class {
|
|
5
|
+
get supportsCreateIfNotExists() {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
get supportsTransactionalDdl() {
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
get supportsMultipleConnections() {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
get supportsReturning() {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
async acquireMigrationLock() {}
|
|
18
|
+
async releaseMigrationLock() {}
|
|
19
|
+
get supportsOutput() {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
var NodeSqliteDriver = class {
|
|
24
|
+
#config;
|
|
25
|
+
#connectionMutex = new ConnectionMutex();
|
|
26
|
+
#db;
|
|
27
|
+
#connection;
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.#config = { ...config };
|
|
30
|
+
}
|
|
31
|
+
async init() {
|
|
32
|
+
this.#db = this.#config.database;
|
|
33
|
+
this.#connection = new NodeSqliteConnection(this.#db);
|
|
34
|
+
if (this.#config.onCreateConnection) await this.#config.onCreateConnection(this.#connection);
|
|
35
|
+
}
|
|
36
|
+
async acquireConnection() {
|
|
37
|
+
await this.#connectionMutex.lock();
|
|
38
|
+
return this.#connection;
|
|
39
|
+
}
|
|
40
|
+
async beginTransaction(connection) {
|
|
41
|
+
await connection.executeQuery(CompiledQuery.raw("begin"));
|
|
42
|
+
}
|
|
43
|
+
async commitTransaction(connection) {
|
|
44
|
+
await connection.executeQuery(CompiledQuery.raw("commit"));
|
|
45
|
+
}
|
|
46
|
+
async rollbackTransaction(connection) {
|
|
47
|
+
await connection.executeQuery(CompiledQuery.raw("rollback"));
|
|
48
|
+
}
|
|
49
|
+
async releaseConnection() {
|
|
50
|
+
this.#connectionMutex.unlock();
|
|
51
|
+
}
|
|
52
|
+
async destroy() {
|
|
53
|
+
this.#db?.close();
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
var NodeSqliteConnection = class {
|
|
57
|
+
#db;
|
|
58
|
+
constructor(db) {
|
|
59
|
+
this.#db = db;
|
|
60
|
+
}
|
|
61
|
+
executeQuery(compiledQuery) {
|
|
62
|
+
const { sql, parameters } = compiledQuery;
|
|
63
|
+
const stmt = this.#db.prepare(sql);
|
|
64
|
+
const params = parameters;
|
|
65
|
+
if (stmt.columns().length > 0) return Promise.resolve({ rows: stmt.all(...params) });
|
|
66
|
+
const { changes, lastInsertRowid } = stmt.run(...params);
|
|
67
|
+
return Promise.resolve({
|
|
68
|
+
rows: [],
|
|
69
|
+
numAffectedRows: BigInt(changes),
|
|
70
|
+
insertId: typeof lastInsertRowid === "bigint" ? lastInsertRowid : BigInt(lastInsertRowid)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
async *streamQuery() {
|
|
74
|
+
throw new Error("Streaming query is not supported by SQLite driver.");
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
var ConnectionMutex = class {
|
|
78
|
+
#promise;
|
|
79
|
+
#resolve;
|
|
80
|
+
async lock() {
|
|
81
|
+
while (this.#promise !== void 0) await this.#promise;
|
|
82
|
+
this.#promise = new Promise((resolve) => {
|
|
83
|
+
this.#resolve = resolve;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
unlock() {
|
|
87
|
+
const resolve = this.#resolve;
|
|
88
|
+
this.#promise = void 0;
|
|
89
|
+
this.#resolve = void 0;
|
|
90
|
+
resolve?.();
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
var NodeSqliteIntrospector = class {
|
|
94
|
+
#db;
|
|
95
|
+
constructor(db) {
|
|
96
|
+
this.#db = db;
|
|
97
|
+
}
|
|
98
|
+
async getSchemas() {
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
async getTables(options = { withInternalKyselyTables: false }) {
|
|
102
|
+
let query = this.#db.selectFrom("sqlite_schema").where("type", "=", "table").where("name", "not like", "sqlite_%").select("name").$castTo();
|
|
103
|
+
if (!options.withInternalKyselyTables) query = query.where("name", "!=", DEFAULT_MIGRATION_TABLE).where("name", "!=", DEFAULT_MIGRATION_LOCK_TABLE);
|
|
104
|
+
const tables = await query.execute();
|
|
105
|
+
return Promise.all(tables.map(({ name }) => this.#getTableMetadata(name)));
|
|
106
|
+
}
|
|
107
|
+
async #getTableMetadata(table) {
|
|
108
|
+
const db = this.#db;
|
|
109
|
+
const autoIncrementCol = (await db.selectFrom("sqlite_master").where("name", "=", table).select("sql").$castTo().execute())[0]?.sql?.split(/[\(\),]/)?.find((it) => it.toLowerCase().includes("autoincrement"))?.split(/\s+/)?.[0]?.replace(/["`]/g, "");
|
|
110
|
+
return {
|
|
111
|
+
name: table,
|
|
112
|
+
columns: (await db.selectFrom(sql$1`pragma_table_info(${table})`.as("table_info")).select([
|
|
113
|
+
"name",
|
|
114
|
+
"type",
|
|
115
|
+
"notnull",
|
|
116
|
+
"dflt_value"
|
|
117
|
+
]).execute()).map((col) => ({
|
|
118
|
+
name: col.name,
|
|
119
|
+
dataType: col.type,
|
|
120
|
+
isNullable: !col.notnull,
|
|
121
|
+
isAutoIncrementing: col.name === autoIncrementCol,
|
|
122
|
+
hasDefaultValue: col.dflt_value != null
|
|
123
|
+
})),
|
|
124
|
+
isView: false,
|
|
125
|
+
isForeign: false
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
var NodeSqliteQueryCompiler = class extends DefaultQueryCompiler {
|
|
130
|
+
getCurrentParameterPlaceholder() {
|
|
131
|
+
return "?";
|
|
132
|
+
}
|
|
133
|
+
getLeftIdentifierWrapper() {
|
|
134
|
+
return "\"";
|
|
135
|
+
}
|
|
136
|
+
getRightIdentifierWrapper() {
|
|
137
|
+
return "\"";
|
|
138
|
+
}
|
|
139
|
+
getAutoIncrement() {
|
|
140
|
+
return "autoincrement";
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
var NodeSqliteDialect = class {
|
|
144
|
+
#config;
|
|
145
|
+
constructor(config) {
|
|
146
|
+
this.#config = { ...config };
|
|
147
|
+
}
|
|
148
|
+
createDriver() {
|
|
149
|
+
return new NodeSqliteDriver(this.#config);
|
|
150
|
+
}
|
|
151
|
+
createQueryCompiler() {
|
|
152
|
+
return new NodeSqliteQueryCompiler();
|
|
153
|
+
}
|
|
154
|
+
createAdapter() {
|
|
155
|
+
return new NodeSqliteAdapter();
|
|
156
|
+
}
|
|
157
|
+
createIntrospector(db) {
|
|
158
|
+
return new NodeSqliteIntrospector(db);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
//#endregion
|
|
162
|
+
export { NodeSqliteDialect };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { C as createChannel$1, F as ensureServer, W as getChannel, j as deleteChannel$1, s as CHANNELS, vt as listChannels$1 } from "./boot-BbtG0ImW.mjs";
|
|
2
|
+
import { n as createServerFn } from "./ssr.mjs";
|
|
3
|
+
import { requestScope } from "./auth-DY1DuYZd.mjs";
|
|
4
|
+
import { t as createServerRpc } from "./createServerRpc-BD8Xn_0_.mjs";
|
|
5
|
+
//#region node_modules/.nitro/vite/services/ssr/assets/notifyFns-BcMRY5kP.js
|
|
6
|
+
/**
|
|
7
|
+
* Notification-channel server functions. Channels are per-team push targets a
|
|
8
|
+
* loop can route its run messages to. Secrets (bot token / chat id) live in the
|
|
9
|
+
* channel's `config` and are NEVER returned to the client — list/test surface
|
|
10
|
+
* only a redacted summary. Scoped to the request's team (see requestScope).
|
|
11
|
+
*
|
|
12
|
+
* Per-type behavior (validate / hint / send) lives in `CHANNELS` (gateway/notify);
|
|
13
|
+
* this module just wires it to auth + storage.
|
|
14
|
+
*/
|
|
15
|
+
function toSummary(c) {
|
|
16
|
+
return {
|
|
17
|
+
id: c.id,
|
|
18
|
+
type: c.type,
|
|
19
|
+
name: c.name,
|
|
20
|
+
hint: CHANNELS[c.type]?.hint(c.config) ?? "—"
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/** Resolve a channel and authorize it against the request's team — undefined when
|
|
24
|
+
* missing OR (gate on) owned by another team, so existence never leaks. Mirrors
|
|
25
|
+
* loopApi's ownedLoop for the channel routes. */
|
|
26
|
+
async function ownedChannel(id) {
|
|
27
|
+
const ch = await getChannel(id);
|
|
28
|
+
if (!ch) return void 0;
|
|
29
|
+
const { enforce, teamId } = await requestScope();
|
|
30
|
+
if (enforce && ch.teamId !== teamId) return void 0;
|
|
31
|
+
return ch;
|
|
32
|
+
}
|
|
33
|
+
/** GET — the team's channels (redacted summaries, newest first). */
|
|
34
|
+
var listChannels_createServerFn_handler = createServerRpc({
|
|
35
|
+
id: "ced5641f28e3e64d3b8773ea4c875b78ee305bd08caba90a2207e86ef1ab3327",
|
|
36
|
+
name: "listChannels",
|
|
37
|
+
filename: "src/server/notifyFns.ts"
|
|
38
|
+
}, (opts) => listChannels.__executeServer(opts));
|
|
39
|
+
var listChannels = createServerFn({ method: "GET" }).handler(listChannels_createServerFn_handler, async () => {
|
|
40
|
+
await ensureServer();
|
|
41
|
+
const { enforce, userId, teamId } = await requestScope();
|
|
42
|
+
if (enforce && !userId) return [];
|
|
43
|
+
return (await listChannels$1(teamId)).map(toSummary);
|
|
44
|
+
});
|
|
45
|
+
var createChannel_createServerFn_handler = createServerRpc({
|
|
46
|
+
id: "d6cb1ea6f7fdaf940fbbe91d6b0898a0d5ac2308f8bc572dc3b856824a1f4581",
|
|
47
|
+
name: "createChannel",
|
|
48
|
+
filename: "src/server/notifyFns.ts"
|
|
49
|
+
}, (opts) => createChannel.__executeServer(opts));
|
|
50
|
+
var createChannel = createServerFn({ method: "POST" }).validator((d) => d).handler(createChannel_createServerFn_handler, async ({ data }) => {
|
|
51
|
+
await ensureServer();
|
|
52
|
+
const { enforce, userId, teamId } = await requestScope();
|
|
53
|
+
if (enforce && !userId) return {
|
|
54
|
+
ok: false,
|
|
55
|
+
error: "not signed in"
|
|
56
|
+
};
|
|
57
|
+
const name = data.name?.trim();
|
|
58
|
+
if (!name) return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: "name required"
|
|
61
|
+
};
|
|
62
|
+
const kind = CHANNELS[data.type];
|
|
63
|
+
if (!kind) return {
|
|
64
|
+
ok: false,
|
|
65
|
+
error: "unknown channel type"
|
|
66
|
+
};
|
|
67
|
+
const cfg = data.config ?? {};
|
|
68
|
+
const missing = kind.required.filter((k) => !cfg[k]?.trim());
|
|
69
|
+
if (missing.length) return {
|
|
70
|
+
ok: false,
|
|
71
|
+
error: `${data.type} needs: ${missing.join(", ")}`
|
|
72
|
+
};
|
|
73
|
+
const keys = [...kind.required, ...kind.optional ?? []];
|
|
74
|
+
const config = Object.fromEntries(keys.filter((k) => cfg[k]?.trim()).map((k) => [k, cfg[k].trim()]));
|
|
75
|
+
const invalid = kind.validate?.(config);
|
|
76
|
+
if (invalid) return {
|
|
77
|
+
ok: false,
|
|
78
|
+
error: invalid
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
ok: true,
|
|
82
|
+
id: (await createChannel$1({
|
|
83
|
+
teamId,
|
|
84
|
+
type: data.type,
|
|
85
|
+
name,
|
|
86
|
+
config
|
|
87
|
+
})).id
|
|
88
|
+
};
|
|
89
|
+
});
|
|
90
|
+
var deleteChannel_createServerFn_handler = createServerRpc({
|
|
91
|
+
id: "9defc1b5d0f4316d61621e2c4614a70dc052ad6b7a3aa2ead00836f7d5cb5b4c",
|
|
92
|
+
name: "deleteChannel",
|
|
93
|
+
filename: "src/server/notifyFns.ts"
|
|
94
|
+
}, (opts) => deleteChannel.__executeServer(opts));
|
|
95
|
+
var deleteChannel = createServerFn({ method: "POST" }).validator((id) => id).handler(deleteChannel_createServerFn_handler, async ({ data: id }) => {
|
|
96
|
+
await ensureServer();
|
|
97
|
+
if (!await ownedChannel(id)) return {
|
|
98
|
+
ok: false,
|
|
99
|
+
error: "channel not found"
|
|
100
|
+
};
|
|
101
|
+
return { ok: await deleteChannel$1(id) };
|
|
102
|
+
});
|
|
103
|
+
var testChannel_createServerFn_handler = createServerRpc({
|
|
104
|
+
id: "a4e3ae06af7087a3dc291236cf6d5ad272e2f754884c1f948e75a18a4ebada93",
|
|
105
|
+
name: "testChannel",
|
|
106
|
+
filename: "src/server/notifyFns.ts"
|
|
107
|
+
}, (opts) => testChannel.__executeServer(opts));
|
|
108
|
+
var testChannel = createServerFn({ method: "POST" }).validator((id) => id).handler(testChannel_createServerFn_handler, async ({ data: id }) => {
|
|
109
|
+
await ensureServer();
|
|
110
|
+
const ch = await ownedChannel(id);
|
|
111
|
+
if (!ch) return {
|
|
112
|
+
ok: false,
|
|
113
|
+
error: "channel not found"
|
|
114
|
+
};
|
|
115
|
+
return CHANNELS[ch.type].send(ch.config, ch.name, "Pievo test message — this channel is wired up. ✓");
|
|
116
|
+
});
|
|
117
|
+
//#endregion
|
|
118
|
+
export { createChannel_createServerFn_handler, deleteChannel_createServerFn_handler, listChannels_createServerFn_handler, testChannel_createServerFn_handler };
|