trellis 3.2.2 → 3.2.3

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.
Files changed (39) hide show
  1. package/dist/browser/index.js +4 -4
  2. package/dist/{chunk-2W3MHTMG.js → chunk-2AACZRII.js} +122 -3
  3. package/dist/{chunk-H6JB3PZ3.js → chunk-5KSGGKET.js} +1 -1
  4. package/dist/{chunk-J2TXUFCZ.js → chunk-6RWGFC3N.js} +134 -20
  5. package/dist/{chunk-7ZFRVCUE.js → chunk-NWSW5YNS.js} +28 -14
  6. package/dist/{deploy-cli-C35HTITO.js → cli/deploy-cli.js} +5 -5
  7. package/dist/cli/index.js +5 -5
  8. package/dist/client/index.browser.js +2 -2
  9. package/dist/client/index.js +1 -1
  10. package/dist/client/sdk.browser.d.ts +28 -1
  11. package/dist/client/sdk.browser.d.ts.map +1 -1
  12. package/dist/client/sdk.browser.js +1 -1
  13. package/dist/client/sdk.js +1 -1
  14. package/dist/core/index.js +6 -6
  15. package/dist/db/index.js +5 -5
  16. package/dist/react/index.js +2 -2
  17. package/dist/react/schema-hooks.js +2 -2
  18. package/dist/server/cors.d.ts +13 -0
  19. package/dist/server/cors.d.ts.map +1 -0
  20. package/dist/server/deploy.d.ts +1 -1
  21. package/dist/server/deploy.d.ts.map +1 -1
  22. package/dist/server/deploy.js +9 -0
  23. package/dist/server/index.js +9 -9
  24. package/dist/server/server.d.ts.map +1 -1
  25. package/dist/{server-ZVWGLLRF.js → server-OGVWNDNK.js} +1 -1
  26. package/package.json +2 -2
  27. package/dist/chunk-FF36CQHZ.js +0 -61
  28. package/dist/chunk-IZX2PLIB.js +0 -1240
  29. package/dist/chunk-KIJITUZB.js +0 -419
  30. package/dist/chunk-SGMDTWJJ.js +0 -149
  31. package/dist/chunk-UQISRW6T.js +0 -203
  32. package/dist/db/trellis.css +0 -1
  33. package/dist/deploy-LQ7GUGJ5.js +0 -9
  34. package/dist/deploy-YNVG5E4E.js +0 -9
  35. package/dist/deploy-cli-24BCHAXY.js +0 -67
  36. package/dist/server-MB3OPSPI.js +0 -18
  37. package/dist/sprites-RU3E4XQN.js +0 -15
  38. package/dist/tenancy-NBLLGCNJ.js +0 -14
  39. /package/dist/{chunk-QB5ISE47.js → chunk-7DUMWO5L.js} +0 -0
@@ -3,6 +3,10 @@ import {
3
3
  liveEntity,
4
4
  liveQuery
5
5
  } from "../chunk-J3WYZO3Q.js";
6
+ import {
7
+ FetchError,
8
+ TrellisDb
9
+ } from "../chunk-6RWGFC3N.js";
6
10
  import "../chunk-WXSWA3MV.js";
7
11
  import {
8
12
  entityMutations
@@ -28,10 +32,6 @@ import {
28
32
  resolveRelations,
29
33
  whereCondition
30
34
  } from "../chunk-JUEMDWLU.js";
31
- import {
32
- FetchError,
33
- TrellisDb
34
- } from "../chunk-J2TXUFCZ.js";
35
35
  import {
36
36
  BroadcastChannelTransport,
37
37
  DEFAULT_MAX_RECORDS,
@@ -682,6 +682,55 @@ function computeDiff(prev, next) {
682
682
  return { added, updated, removed };
683
683
  }
684
684
 
685
+ // src/server/cors.ts
686
+ var DEFAULT_METHODS = "GET, POST, PUT, DELETE, OPTIONS";
687
+ var DEFAULT_HEADERS = "Content-Type, Authorization";
688
+ function corsEnabledForConfig(apiKey) {
689
+ return Boolean(process.env.TRELLIS_CORS_ORIGINS) || Boolean(apiKey);
690
+ }
691
+ function allowedOrigins() {
692
+ const raw = process.env.TRELLIS_CORS_ORIGINS?.trim();
693
+ if (!raw || raw === "*") return "*";
694
+ return raw.split(",").map((s) => s.trim()).filter(Boolean);
695
+ }
696
+ function corsHeaders(req) {
697
+ const origins = allowedOrigins();
698
+ const requestOrigin = req.headers.get("Origin");
699
+ let allowOrigin = "*";
700
+ if (origins !== "*") {
701
+ if (requestOrigin && origins.includes(requestOrigin)) {
702
+ allowOrigin = requestOrigin;
703
+ } else if (origins.length === 1) {
704
+ allowOrigin = origins[0];
705
+ } else {
706
+ allowOrigin = origins[0] ?? "*";
707
+ }
708
+ }
709
+ return {
710
+ "Access-Control-Allow-Origin": allowOrigin,
711
+ "Access-Control-Allow-Methods": DEFAULT_METHODS,
712
+ "Access-Control-Allow-Headers": DEFAULT_HEADERS,
713
+ Vary: "Origin"
714
+ };
715
+ }
716
+ function withCors(req, res) {
717
+ const headers = new Headers(res.headers);
718
+ for (const [key, value] of Object.entries(corsHeaders(req))) {
719
+ headers.set(key, value);
720
+ }
721
+ return new Response(res.body, {
722
+ status: res.status,
723
+ statusText: res.statusText,
724
+ headers
725
+ });
726
+ }
727
+ function corsPreflightResponse(req) {
728
+ return new Response(null, {
729
+ status: 204,
730
+ headers: corsHeaders(req)
731
+ });
732
+ }
733
+
685
734
  // src/server/server.ts
686
735
  var __moduleDir = import.meta.dir ?? dirname(fileURLToPath(import.meta.url));
687
736
  async function startServer(opts) {
@@ -698,7 +747,8 @@ function buildServerContext(opts) {
698
747
  };
699
748
  const meter = new UsageMeter();
700
749
  const subs = new SubscriptionManager(pool, permissions ?? null, meter);
701
- const handleHttp = async (req) => {
750
+ const enableCors = corsEnabledForConfig(config.apiKey);
751
+ const handleHttpInner = async (req) => {
702
752
  const url = new URL(req.url);
703
753
  const path = url.pathname;
704
754
  const auth = await resolveAuth(
@@ -721,9 +771,30 @@ function buildServerContext(opts) {
721
771
  return json(err.toResponse(), 403);
722
772
  }
723
773
  const msg = err instanceof Error ? err.message : String(err);
724
- return json({ error: "Internal Server Error", message: msg }, 500);
774
+ if (process.env.TRELLIS_DEBUG) {
775
+ console.error(
776
+ `[trellis] ${req.method} ${path} \u2192 500:`,
777
+ msg
778
+ );
779
+ }
780
+ return json(
781
+ {
782
+ error: "Internal Server Error",
783
+ message: msg,
784
+ method: req.method,
785
+ path
786
+ },
787
+ 500
788
+ );
725
789
  }
726
790
  };
791
+ const handleHttp = async (req) => {
792
+ if (enableCors && req.method === "OPTIONS") {
793
+ return corsPreflightResponse(req);
794
+ }
795
+ const res = await handleHttpInner(req);
796
+ return enableCors ? withCors(req, res) : res;
797
+ };
727
798
  return { port, authConfig, subs, handleHttp };
728
799
  }
729
800
  async function startServerNode(opts) {
@@ -964,8 +1035,56 @@ async function handleQuery(req, auth, tenantId, ctx) {
964
1035
  executionTime: result.executionTime
965
1036
  });
966
1037
  }
1038
+ async function readJsonObject(req, route2) {
1039
+ const raw = await req.text();
1040
+ if (!raw.trim()) {
1041
+ if (process.env.TRELLIS_DEBUG) {
1042
+ console.warn(`[trellis] ${req.method} ${route2}: empty request body`);
1043
+ }
1044
+ return {
1045
+ ok: false,
1046
+ response: json(
1047
+ {
1048
+ error: "Bad Request",
1049
+ message: "Request body is empty \u2014 client may not have sent JSON (common on iOS HTTP dev)",
1050
+ method: req.method,
1051
+ path: route2,
1052
+ bodyBytes: 0
1053
+ },
1054
+ 400
1055
+ )
1056
+ };
1057
+ }
1058
+ try {
1059
+ const data = JSON.parse(raw);
1060
+ return { ok: true, data };
1061
+ } catch (err) {
1062
+ const msg = err instanceof Error ? err.message : String(err);
1063
+ if (process.env.TRELLIS_DEBUG) {
1064
+ console.warn(
1065
+ `[trellis] ${req.method} ${route2}: invalid JSON (${raw.length}B):`,
1066
+ msg
1067
+ );
1068
+ }
1069
+ return {
1070
+ ok: false,
1071
+ response: json(
1072
+ {
1073
+ error: "Bad Request",
1074
+ message: `Invalid JSON: ${msg}`,
1075
+ method: req.method,
1076
+ path: route2,
1077
+ bodyBytes: raw.length
1078
+ },
1079
+ 400
1080
+ )
1081
+ };
1082
+ }
1083
+ }
967
1084
  async function handleCreateOntology(req, auth, tenantId, ctx) {
968
- const schema = await req.json();
1085
+ const parsed = await readJsonObject(req, "/ontologies");
1086
+ if (!parsed.ok) return parsed.response;
1087
+ const schema = parsed.data;
969
1088
  if (!schema || !schema["@id"] || !Array.isArray(schema.fields)) {
970
1089
  return json(
971
1090
  { error: "A SchemaDefinition (with @id and fields) is required" },
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TrellisDb
3
- } from "./chunk-J2TXUFCZ.js";
3
+ } from "./chunk-6RWGFC3N.js";
4
4
 
5
5
  // src/react/provider.tsx
6
6
  import React, {
@@ -7,6 +7,37 @@ function browserOnlyRemoteError(feature) {
7
7
  `${feature} is not available in browser bundles. Use remote mode with \`new TrellisDb({ url })\`, or import \`trellis/client\` in Node.`
8
8
  );
9
9
  }
10
+ function randomId() {
11
+ if (typeof globalThis.crypto?.randomUUID === "function") {
12
+ return globalThis.crypto.randomUUID();
13
+ }
14
+ return `${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 11)}`;
15
+ }
16
+ function needsXhrForBody() {
17
+ if (typeof globalThis.window !== "undefined" && window.__TRELLIS_NATIVE_HTTP__) {
18
+ return false;
19
+ }
20
+ if (typeof navigator === "undefined") return false;
21
+ const ua = navigator.userAgent;
22
+ if (/iPad|iPhone|iPod/i.test(ua)) return true;
23
+ if (navigator.platform === "MacIntel" && navigator.maxTouchPoints > 1) return true;
24
+ if (/AppleWebKit/i.test(ua) && /KHTML, like Gecko\)/i.test(ua) && !/Safari\/|Chrome\/|Chromium\/|Edg\/|Version\//i.test(ua)) {
25
+ return true;
26
+ }
27
+ return false;
28
+ }
29
+ function xhrRequest(method, url, headers, body) {
30
+ return new Promise((resolve, reject) => {
31
+ const xhr = new XMLHttpRequest();
32
+ xhr.open(method, url);
33
+ for (const [key, value] of Object.entries(headers)) {
34
+ xhr.setRequestHeader(key, value);
35
+ }
36
+ xhr.onload = () => resolve({ status: xhr.status, text: xhr.responseText });
37
+ xhr.onerror = () => reject(new Error(`XHR network error on ${method} ${url}`));
38
+ xhr.send(body);
39
+ });
40
+ }
10
41
  var TrellisDb = class {
11
42
  opts;
12
43
  _ws = null;
@@ -101,10 +132,21 @@ var TrellisDb = class {
101
132
  */
102
133
  async registerType(schema) {
103
134
  const def = "@id" in schema ? schema : schema.definition;
135
+ const label = def?.label ?? (def?.["@id"] ? String(def["@id"]).replace(/^trellis:/, "") : "unknown");
136
+ if (!def?.["@id"]) {
137
+ throw new Error(`registerType(${label}): schema is missing a definition with @id`);
138
+ }
104
139
  try {
105
140
  await this._fetch("POST", "/ontologies", def);
106
141
  } catch (err) {
107
142
  if (err instanceof FetchError && err.status === 409) return;
143
+ if (err instanceof FetchError) {
144
+ const serverMsg = typeof err.body?.message === "string" ? String(err.body.message) : err.message;
145
+ throw new FetchError(err.status, serverMsg, err.body, {
146
+ ...err.context,
147
+ operation: `registerType(${label})`
148
+ });
149
+ }
108
150
  throw err;
109
151
  }
110
152
  }
@@ -176,7 +218,7 @@ var TrellisDb = class {
176
218
  * Callback is fired immediately with the initial result, then on every update.
177
219
  */
178
220
  subscribe(eql, callback, opts) {
179
- const subId = `sub_${crypto.randomUUID()}`;
221
+ const subId = `sub_${randomId()}`;
180
222
  this._subCallbacks.set(subId, callback);
181
223
  this._ensureWs().then((ws) => {
182
224
  ws.send(
@@ -184,6 +226,7 @@ var TrellisDb = class {
184
226
  type: "subscribe",
185
227
  id: subId,
186
228
  query: eql,
229
+ ...this.opts.tenantId ? { tenantId: this.opts.tenantId } : {},
187
230
  ...opts?.entityType ? { entityType: opts.entityType } : {},
188
231
  ...opts?.resolve ? { resolve: opts.resolve } : {}
189
232
  })
@@ -214,23 +257,69 @@ var TrellisDb = class {
214
257
  // -------------------------------------------------------------------------
215
258
  // Private
216
259
  // -------------------------------------------------------------------------
260
+ /**
261
+ * Tenant isolation, not authorization: when `tenantId` is supplied out-of-band
262
+ * (not bound to the JWT), the server trusts the query param. Safe for ephemeral
263
+ * showcase rooms with unguessable ids; real multi-tenant auth must bind the
264
+ * tenant to the auth token instead. Skipped when the JWT already carries it.
265
+ */
266
+ _applyTenant(path) {
267
+ const tenantId = this.opts.tenantId;
268
+ if (!tenantId) return path;
269
+ const sep = path.includes("?") ? "&" : "?";
270
+ return `${path}${sep}tenantId=${encodeURIComponent(tenantId)}`;
271
+ }
217
272
  async _fetch(method, path, body) {
218
- const url = `${this.opts.url}${path}`;
219
- const res = await fetch(url, {
220
- method,
221
- headers: {
222
- "Content-Type": "application/json",
223
- ...this.opts.apiKey ? { Authorization: `Bearer ${this.opts.apiKey}` } : {}
224
- },
225
- body: body !== void 0 ? JSON.stringify(body) : void 0
226
- });
227
- const data = await res.json();
228
- if (!res.ok)
229
- throw new FetchError(
230
- res.status,
231
- data?.message ?? res.statusText,
232
- data
233
- );
273
+ const url = `${this.opts.url}${this._applyTenant(path)}`;
274
+ let jsonBody;
275
+ if (body !== void 0) {
276
+ jsonBody = JSON.stringify(body);
277
+ if (jsonBody === void 0) {
278
+ throw new Error(`Request body is not JSON-serializable (${method} ${path})`);
279
+ }
280
+ }
281
+ const headers = {
282
+ "Content-Type": "application/json",
283
+ ...this.opts.apiKey ? { Authorization: `Bearer ${this.opts.apiKey}` } : {}
284
+ };
285
+ const transport = jsonBody !== void 0 && needsXhrForBody() ? "xhr" : "fetch";
286
+ headers["X-Trellis-Transport"] = transport;
287
+ const bodyBytes = jsonBody ? new TextEncoder().encode(jsonBody).byteLength : 0;
288
+ let status;
289
+ let text;
290
+ if (transport === "xhr" && jsonBody !== void 0) {
291
+ ({ status, text } = await xhrRequest(method, url, headers, jsonBody));
292
+ } else {
293
+ const res = await fetch(url, {
294
+ method,
295
+ headers,
296
+ body: jsonBody
297
+ });
298
+ status = res.status;
299
+ text = await res.text();
300
+ }
301
+ let data = null;
302
+ if (text) {
303
+ try {
304
+ data = JSON.parse(text);
305
+ } catch {
306
+ data = { raw: text };
307
+ }
308
+ }
309
+ if (status < 200 || status >= 300) {
310
+ const server = data;
311
+ const message = typeof server?.message === "string" && server.message || typeof server?.error === "string" && server.error || "request failed";
312
+ const err = new FetchError(status, message, data, {
313
+ method,
314
+ path,
315
+ url,
316
+ requestBodyBytes: bodyBytes,
317
+ responseBytes: text.length,
318
+ transport
319
+ });
320
+ console.error("[trellis]", err.toString());
321
+ throw err;
322
+ }
234
323
  return data;
235
324
  }
236
325
  _ensureWs() {
@@ -274,12 +363,37 @@ var TrellisDb = class {
274
363
  return this._wsPromise;
275
364
  }
276
365
  };
277
- var FetchError = class extends Error {
278
- constructor(status, message, body) {
279
- super(`HTTP ${status}: ${message}`);
366
+ var FetchError = class _FetchError extends Error {
367
+ constructor(status, message, body, context = {}) {
368
+ super(_FetchError.format(status, message, context));
280
369
  this.status = status;
281
370
  this.body = body;
282
371
  this.name = "FetchError";
372
+ this.context = context;
373
+ }
374
+ context;
375
+ static format(status, message, ctx) {
376
+ const parts = [`HTTP ${status}`];
377
+ if (ctx.operation) parts.push(ctx.operation);
378
+ if (ctx.method && ctx.path) parts.push(`${ctx.method} ${ctx.path}`);
379
+ parts.push(message);
380
+ if (ctx.requestBodyBytes !== void 0) {
381
+ parts.push(`sent ${ctx.requestBodyBytes}B`);
382
+ }
383
+ if (ctx.responseBytes !== void 0) {
384
+ parts.push(`response ${ctx.responseBytes}B`);
385
+ }
386
+ if (ctx.transport) parts.push(ctx.transport);
387
+ return parts.join(" \xB7 ");
388
+ }
389
+ toString() {
390
+ const extra = [];
391
+ if (this.body && typeof this.body === "object") {
392
+ const b = this.body;
393
+ if (typeof b.path === "string") extra.push(`server ${b.method} ${b.path}`);
394
+ if (typeof b.bodyBytes === "number") extra.push(`server saw ${b.bodyBytes}B`);
395
+ }
396
+ return extra.length ? `${this.message} (${extra.join(", ")})` : this.message;
283
397
  }
284
398
  };
285
399
 
@@ -10,13 +10,12 @@ import {
10
10
  import {
11
11
  updateConfig
12
12
  } from "./chunk-JA7AIHRK.js";
13
- import {
14
- __require
15
- } from "./chunk-KFQGP6VL.js";
16
13
 
17
14
  // src/server/deploy.ts
15
+ import { execFile } from "child_process";
18
16
  import { existsSync, writeFileSync, mkdirSync } from "fs";
19
17
  import { join, resolve } from "path";
18
+ import { promisify } from "util";
20
19
 
21
20
  // src/server/deploy-meta.ts
22
21
  var DEPLOY_NAME_RE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
@@ -109,16 +108,22 @@ async function deploy(opts) {
109
108
  if (!bunPath.includes("bun")) {
110
109
  throw new Error(`Bun install failed on sprite ${name}: ${bunPath || "(no output)"}`);
111
110
  }
112
- onProgress("Starting server...");
113
- await runSpriteExec(
114
- name,
115
- 'pkill -f "/home/sprite/trellis-db/server.js" 2>/dev/null || true'
116
- ).catch(() => {
117
- });
111
+ onProgress("Starting server (sprite-env service)...");
118
112
  const bun = bunPath.trim().split("\n").pop().trim();
119
113
  await runSpriteExec(
120
114
  name,
121
- `cd /home/sprite/trellis-db && (nohup ${bun} run server.js >> server.log 2>&1 </dev/null &); exit 0`
115
+ `
116
+ export PATH="$HOME/.bun/bin:$PATH"
117
+ ENV="/.sprite/bin/sprite-env"
118
+ BUN="${bun}"
119
+ $ENV services delete trellis-db 2>/dev/null || true
120
+ $ENV services create trellis-db \\
121
+ --cmd "$BUN" \\
122
+ --args run,server.js \\
123
+ --dir /home/sprite/trellis-db \\
124
+ --http-port ${listenPort} \\
125
+ --no-stream
126
+ `.trim()
122
127
  );
123
128
  onProgress("Waiting for health check...");
124
129
  await waitForDeployHealth(url, 6e4);
@@ -162,8 +167,6 @@ function generateSecret(prefix) {
162
167
  return `${prefix}${b64}`;
163
168
  }
164
169
  async function runBun(args) {
165
- const { execFile } = __require("child_process");
166
- const { promisify } = __require("util");
167
170
  const execFileAsync = promisify(execFile);
168
171
  try {
169
172
  await execFileAsync("bun", args);
@@ -173,10 +176,21 @@ async function runBun(args) {
173
176
  );
174
177
  }
175
178
  }
179
+ function resolveTrellisImports() {
180
+ const root = process.env.TRELLIS_NODE_ROOT?.trim();
181
+ if (root) {
182
+ return {
183
+ server: join(root, "dist/server/index.js").replace(/\\/g, "/"),
184
+ client: join(root, "dist/client/index.js").replace(/\\/g, "/")
185
+ };
186
+ }
187
+ return { server: "trellis/server", client: "trellis/client" };
188
+ }
176
189
  function generateServerEntrypoint(opts) {
190
+ const { server, client } = resolveTrellisImports();
177
191
  return `
178
- import { TenantPool, startServer } from 'trellis/server';
179
- import { readConfig, defaultLocalConfig, writeConfig } from 'trellis/client';
192
+ import { TenantPool, startServer } from '${server}';
193
+ import { readConfig, defaultLocalConfig, writeConfig } from '${client}';
180
194
  import { join } from 'path';
181
195
  import { existsSync } from 'fs';
182
196
 
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  DeployNameError,
3
3
  deploy
4
- } from "./chunk-7ZFRVCUE.js";
5
- import "./chunk-CAG4FULI.js";
4
+ } from "../chunk-NWSW5YNS.js";
5
+ import "../chunk-CAG4FULI.js";
6
6
  import {
7
7
  configPath
8
- } from "./chunk-JA7AIHRK.js";
9
- import "./chunk-KFQGP6VL.js";
8
+ } from "../chunk-JA7AIHRK.js";
9
+ import "../chunk-KFQGP6VL.js";
10
10
 
11
11
  // src/cli/deploy-cli.ts
12
12
  import chalk from "chalk";
@@ -35,7 +35,7 @@ function printDeploySuccess(result, configDir, stub) {
35
35
  async function runDeployCli(opts) {
36
36
  const configDir = opts.configDir ?? ".";
37
37
  const port = opts.port === void 0 ? void 0 : typeof opts.port === "string" ? parseInt(opts.port, 10) : opts.port;
38
- const { readConfig } = await import("./config-PFTP67TR.js");
38
+ const { readConfig } = await import("../config-PFTP67TR.js");
39
39
  const config = readConfig(configDir);
40
40
  const label = opts.stub ? "Stub deploy" : "Deploying to Sprites";
41
41
  console.log(chalk.bold(`${label}: ${opts.name}...`));
package/dist/cli/index.js CHANGED
@@ -4467,7 +4467,7 @@ db.command("init").description("Initialize a new Trellis DB in the current direc
4467
4467
  db.command("serve").description("Start the Trellis DB HTTP + WebSocket server").option("-p, --port <port>", "Override port from config").option("--config-dir <dir>", "Directory containing .trellis-db.json", ".").action(async (opts) => {
4468
4468
  const { readConfig } = await import("../config-PFTP67TR.js");
4469
4469
  const { TenantPool } = await import("../tenancy-POMWQP6M.js");
4470
- const { startServer } = await import("../server-ZVWGLLRF.js");
4470
+ const { startServer } = await import("../server-OGVWNDNK.js");
4471
4471
  const config = readConfig(opts.configDir);
4472
4472
  if (!config) {
4473
4473
  console.error(
@@ -4489,7 +4489,7 @@ db.command("serve").description("Start the Trellis DB HTTP + WebSocket server").
4489
4489
  backendOpts ? { backend: backendOpts } : void 0
4490
4490
  );
4491
4491
  await pool.preload(DEFAULT_TENANT);
4492
- const { startServerCrossRuntime } = await import("../server-ZVWGLLRF.js");
4492
+ const { startServerCrossRuntime } = await import("../server-OGVWNDNK.js");
4493
4493
  const server = await startServerCrossRuntime({ port, config, pool });
4494
4494
  console.log(chalk4.green(`\u2713 Trellis DB running`));
4495
4495
  console.log(chalk4.dim(` URL: http://localhost:${port}`));
@@ -4621,7 +4621,7 @@ function registerDeployOptions(cmd) {
4621
4621
  );
4622
4622
  }
4623
4623
  async function handleDeployCommand(opts) {
4624
- const { runDeployCli } = await import("../deploy-cli-C35HTITO.js");
4624
+ const { runDeployCli } = await import("./deploy-cli.js");
4625
4625
  await runDeployCli(opts);
4626
4626
  }
4627
4627
  registerDeployOptions(
@@ -4644,7 +4644,7 @@ async function getSpriteName(spriteOption) {
4644
4644
  vmProgram.command("create <name>").description("Create a new Sprite and deploy Trellis DB").option("-k, --api-key <key>", "API key (auto-generated if omitted)").option("-p, --port <port>", "Port (default: 3000)", "3000").action(async (name, cmdOpts) => {
4645
4645
  const { runSpriteCmd, assertSpriteCli } = await import("../sprites-KQGTGM6W.js");
4646
4646
  const { trackSprite } = await import("../vm-config-JI4OXKDQ.js");
4647
- const { deploy } = await import("../deploy-LQ7GUGJ5.js");
4647
+ const { deploy } = await import("../server/deploy.js");
4648
4648
  try {
4649
4649
  await assertSpriteCli();
4650
4650
  console.log(`Creating Sprite: ${name}...`);
@@ -4950,7 +4950,7 @@ vmProgram.command("status").description("Show detailed status of the active Spri
4950
4950
  vmProgram.command("code [name]").description("Create Sprite, deploy Trellis, open in browser").action(async (nameOpt) => {
4951
4951
  const { runSpriteCmd, assertSpriteCli } = await import("../sprites-KQGTGM6W.js");
4952
4952
  const { loadVmConfig, trackSprite, getActiveSprite } = await import("../vm-config-JI4OXKDQ.js");
4953
- const { deploy } = await import("../deploy-LQ7GUGJ5.js");
4953
+ const { deploy } = await import("../server/deploy.js");
4954
4954
  const openUrl = (url) => {
4955
4955
  const cmd = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : null;
4956
4956
  if (!cmd) {
@@ -3,11 +3,11 @@ import {
3
3
  liveEntity,
4
4
  liveQuery
5
5
  } from "../chunk-J3WYZO3Q.js";
6
- import "../chunk-JUEMDWLU.js";
7
6
  import {
8
7
  FetchError,
9
8
  TrellisDb
10
- } from "../chunk-J2TXUFCZ.js";
9
+ } from "../chunk-6RWGFC3N.js";
10
+ import "../chunk-JUEMDWLU.js";
11
11
  import {
12
12
  BatchSignal,
13
13
  Signal
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  FetchError,
15
15
  TrellisDb
16
- } from "../chunk-QB5ISE47.js";
16
+ } from "../chunk-7DUMWO5L.js";
17
17
  import "../chunk-L5N5PR2S.js";
18
18
  import "../chunk-GU374KWZ.js";
19
19
  import {
@@ -15,6 +15,14 @@ export interface SubscribeOptions {
15
15
  entityType?: string;
16
16
  resolve?: ResolveSpec;
17
17
  }
18
+ declare global {
19
+ interface Window {
20
+ /** Set by host app when WKWebView drops fetch POST bodies (XHR fallback). */
21
+ __TRELLIS_USE_XHR__?: boolean;
22
+ /** Host patched fetch via Tauri plugin-http — always use fetch, never XHR. */
23
+ __TRELLIS_NATIVE_HTTP__?: boolean;
24
+ }
25
+ }
18
26
  export declare class TrellisDb {
19
27
  private opts;
20
28
  private _ws;
@@ -93,12 +101,31 @@ export declare class TrellisDb {
93
101
  * Close open client resources.
94
102
  */
95
103
  close(): void;
104
+ /**
105
+ * Tenant isolation, not authorization: when `tenantId` is supplied out-of-band
106
+ * (not bound to the JWT), the server trusts the query param. Safe for ephemeral
107
+ * showcase rooms with unguessable ids; real multi-tenant auth must bind the
108
+ * tenant to the auth token instead. Skipped when the JWT already carries it.
109
+ */
110
+ private _applyTenant;
96
111
  private _fetch;
97
112
  private _ensureWs;
98
113
  }
114
+ export interface FetchErrorContext {
115
+ method?: string;
116
+ path?: string;
117
+ url?: string;
118
+ operation?: string;
119
+ requestBodyBytes?: number;
120
+ responseBytes?: number;
121
+ transport?: 'fetch' | 'xhr';
122
+ }
99
123
  export declare class FetchError extends Error {
100
124
  status: number;
101
125
  body?: unknown | undefined;
102
- constructor(status: number, message: string, body?: unknown | undefined);
126
+ readonly context: FetchErrorContext;
127
+ constructor(status: number, message: string, body?: unknown | undefined, context?: FetchErrorContext);
128
+ static format(status: number, message: string, ctx: FetchErrorContext): string;
129
+ toString(): string;
103
130
  }
104
131
  //# sourceMappingURL=sdk.browser.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.browser.d.ts","sourceRoot":"","sources":["../../src/client/sdk.browser.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sdk.browser.d.ts","sourceRoot":"","sources":["../../src/client/sdk.browser.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  FetchError,
3
3
  TrellisDb
4
- } from "../chunk-J2TXUFCZ.js";
4
+ } from "../chunk-6RWGFC3N.js";
5
5
  import "../chunk-KFQGP6VL.js";
6
6
  export {
7
7
  FetchError,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  FetchError,
3
3
  TrellisDb
4
- } from "../chunk-QB5ISE47.js";
4
+ } from "../chunk-7DUMWO5L.js";
5
5
  import "../chunk-KFQGP6VL.js";
6
6
  export {
7
7
  FetchError,
@@ -1,9 +1,3 @@
1
- import {
2
- SqlJsKernelBackend
3
- } from "../chunk-LNUIGRDZ.js";
4
- import {
5
- createKernelBackend
6
- } from "../chunk-FKQO5A3H.js";
7
1
  import {
8
2
  OntologyRegistry,
9
3
  agentOntology,
@@ -14,6 +8,12 @@ import {
14
8
  validateEntity,
15
9
  validateStore
16
10
  } from "../chunk-YCM7ZYEZ.js";
11
+ import {
12
+ SqlJsKernelBackend
13
+ } from "../chunk-LNUIGRDZ.js";
14
+ import {
15
+ createKernelBackend
16
+ } from "../chunk-FKQO5A3H.js";
17
17
  import {
18
18
  ExprEvaluator,
19
19
  attachStandardMiddleware,