@omg-dev/server 0.4.29 → 0.4.31

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.mjs CHANGED
@@ -763,7 +763,7 @@ async function sendResumeReplay(client, sub, fromSeq) {
763
763
  replayed
764
764
  });
765
765
  }
766
- const RESERVED = new Set([
766
+ const RESERVED = /* @__PURE__ */ new Set([
767
767
  "id",
768
768
  "created_at",
769
769
  "updated_at",
@@ -802,7 +802,7 @@ const scopedTables = /* @__PURE__ */ new Set();
802
802
  function markScoped(table) {
803
803
  scopedTables.add(table);
804
804
  }
805
- const RESERVED_COLUMNS = new Set([
805
+ const RESERVED_COLUMNS = /* @__PURE__ */ new Set([
806
806
  "id",
807
807
  "_owner",
808
808
  "created_at",
@@ -1363,6 +1363,18 @@ function buildAutoCrudRoutes(schema) {
1363
1363
  return routes;
1364
1364
  }
1365
1365
  //#endregion
1366
+ //#region src/agent-url.ts
1367
+ const DEFAULT_AGENT_URL = "http://localhost:8080";
1368
+ /**
1369
+ * Base URL for the in-VM agent.
1370
+ *
1371
+ * Read lazily so local runtimes can inject the emulator URL before loading
1372
+ * user code without coupling the SDK to a particular process bootstrap.
1373
+ */
1374
+ function agentBase() {
1375
+ return process.env.OMG_AGENT_URL || process.env.VIBES_AGENT_URL || DEFAULT_AGENT_URL;
1376
+ }
1377
+ //#endregion
1366
1378
  //#region src/triggers.ts
1367
1379
  /**
1368
1380
  * Schedule a function to run on a cron expression (UTC, 5-field syntax).
@@ -1661,7 +1673,8 @@ function emitInProcess(topic, payload) {
1661
1673
  async function emitToOrchestrator(topic, payload) {
1662
1674
  const payloadStr = JSON.stringify(payload ?? null);
1663
1675
  if (payloadStr.length > MAX_EMIT_BYTES) throw new Error(`emit("${topic}"): payload exceeds ${MAX_EMIT_BYTES} bytes`);
1664
- const res = await fetch("http://localhost:8080/_emit", {
1676
+ const url = `${agentBase()}/_emit`;
1677
+ const res = await fetch(url, {
1665
1678
  method: "POST",
1666
1679
  headers: { "Content-Type": "application/json" },
1667
1680
  body: JSON.stringify({
@@ -1773,7 +1786,8 @@ function updateDevDelivery(id, patch) {
1773
1786
  async function scheduleToOrchestrator(atMs, topic, payload) {
1774
1787
  const payloadStr = JSON.stringify(payload ?? null);
1775
1788
  if (payloadStr.length > MAX_EMIT_BYTES) throw new Error(`schedule("${topic}"): payload exceeds ${MAX_EMIT_BYTES} bytes`);
1776
- const res = await fetch("http://localhost:8080/_schedule", {
1789
+ const url = `${agentBase()}/_schedule`;
1790
+ const res = await fetch(url, {
1777
1791
  method: "POST",
1778
1792
  headers: { "Content-Type": "application/json" },
1779
1793
  body: JSON.stringify({
@@ -1794,7 +1808,7 @@ async function scheduleToOrchestrator(atMs, topic, payload) {
1794
1808
  };
1795
1809
  }
1796
1810
  async function cancelOnOrchestrator(eventId) {
1797
- const url = `http://localhost:8080/_schedule/${encodeURIComponent(eventId)}`;
1811
+ const url = `${agentBase()}/_schedule/${encodeURIComponent(eventId)}`;
1798
1812
  const res = await fetch(url, { method: "DELETE" });
1799
1813
  if (!res.ok) {
1800
1814
  const text = await res.text().catch(() => "");
@@ -2150,7 +2164,7 @@ function handleWorkflowRequest(req) {
2150
2164
  return restateFetchHandler(req);
2151
2165
  }
2152
2166
  async function startViaAgent(name, payloadStr, opts) {
2153
- const res = await fetch("http://localhost:8080/_workflow/start", {
2167
+ const res = await fetch(`${agentBase()}/_workflow/start`, {
2154
2168
  method: "POST",
2155
2169
  headers: { "Content-Type": "application/json" },
2156
2170
  body: JSON.stringify({
@@ -2237,9 +2251,8 @@ const storage = {
2237
2251
  onUpload,
2238
2252
  onDelete
2239
2253
  };
2240
- const AGENT_BASE$1 = "http://localhost:8080";
2241
2254
  async function prodPresign(action, key, scope, userId, contentType) {
2242
- const res = await fetch(`${AGENT_BASE$1}/_storage/presign`, {
2255
+ const res = await fetch(`${agentBase()}/_storage/presign`, {
2243
2256
  method: "POST",
2244
2257
  headers: { "Content-Type": "application/json" },
2245
2258
  body: JSON.stringify({
@@ -2264,7 +2277,7 @@ async function prodPresign(action, key, scope, userId, contentType) {
2264
2277
  };
2265
2278
  }
2266
2279
  async function prodList(scope, userId, prefix, limit) {
2267
- const res = await fetch(`${AGENT_BASE$1}/_storage/list`, {
2280
+ const res = await fetch(`${agentBase()}/_storage/list`, {
2268
2281
  method: "POST",
2269
2282
  headers: { "Content-Type": "application/json" },
2270
2283
  body: JSON.stringify({
@@ -2287,7 +2300,7 @@ async function prodList(scope, userId, prefix, limit) {
2287
2300
  }));
2288
2301
  }
2289
2302
  async function prodDelete(key, scope, userId) {
2290
- const res = await fetch(`${AGENT_BASE$1}/_storage/delete`, {
2303
+ const res = await fetch(`${agentBase()}/_storage/delete`, {
2291
2304
  method: "POST",
2292
2305
  headers: { "Content-Type": "application/json" },
2293
2306
  body: JSON.stringify({
@@ -2405,7 +2418,7 @@ const NOTIFICATIONS_TABLE = "vibesNotifications";
2405
2418
  const PREFERENCES_TABLE = "vibesNotificationPreferences";
2406
2419
  const SUBSCRIPTIONS_TABLE = "vibesPushSubscriptions";
2407
2420
  const DELIVERIES_TABLE = "vibesNotificationDeliveries";
2408
- const notificationSystemCollectionNames = new Set([
2421
+ const notificationSystemCollectionNames = /* @__PURE__ */ new Set([
2409
2422
  NOTIFICATIONS_TABLE,
2410
2423
  PREFERENCES_TABLE,
2411
2424
  SUBSCRIPTIONS_TABLE,
@@ -2879,7 +2892,6 @@ self.addEventListener("notificationclick", (event) => {
2879
2892
  }
2880
2893
  //#endregion
2881
2894
  //#region src/billing.ts
2882
- const AGENT_BASE = "http://localhost:8080";
2883
2895
  const MICROS_PER_UNIT = 1e6;
2884
2896
  /**
2885
2897
  * Dollars (or whole credit units) → integer micro-units, for the amount
@@ -2890,7 +2902,7 @@ function usd(amount) {
2890
2902
  return Math.round(amount * MICROS_PER_UNIT);
2891
2903
  }
2892
2904
  async function agentPost(path, body, label) {
2893
- const res = await fetch(`${AGENT_BASE}${path}`, {
2905
+ const res = await fetch(`${agentBase()}${path}`, {
2894
2906
  method: "POST",
2895
2907
  headers: { "Content-Type": "application/json" },
2896
2908
  body: JSON.stringify(body)
@@ -2902,7 +2914,7 @@ async function agentPost(path, body, label) {
2902
2914
  return await res.json();
2903
2915
  }
2904
2916
  async function agentGet(path, label) {
2905
- const res = await fetch(`${AGENT_BASE}${path}`, {
2917
+ const res = await fetch(`${agentBase()}${path}`, {
2906
2918
  method: "GET",
2907
2919
  headers: { Accept: "application/json" }
2908
2920
  });
@@ -3156,7 +3168,7 @@ async function createVibesServer(opts) {
3156
3168
  ];
3157
3169
  function rebuildRoutes() {
3158
3170
  const explicit = new Set(explicitRoutes.map((r) => `${r.method} ${r.path}`));
3159
- const builtinKeys = new Set([...storageBuiltinRoutes.map((r) => `${r.method} ${r.path}`), ...notificationBuiltinRoutes.map((r) => `${r.method} ${r.path}`)]);
3171
+ const builtinKeys = /* @__PURE__ */ new Set([...storageBuiltinRoutes.map((r) => `${r.method} ${r.path}`), ...notificationBuiltinRoutes.map((r) => `${r.method} ${r.path}`)]);
3160
3172
  const builtinStorage = storageBuiltinRoutes.filter((r) => !explicit.has(`${r.method} ${r.path}`));
3161
3173
  const builtinNotifications = notificationBuiltinRoutes.filter((r) => !explicit.has(`${r.method} ${r.path}`));
3162
3174
  if (hasCollections(currentSchema) && opts.autoCrud !== false) routes = [
@@ -24,6 +24,8 @@ function walk(dir, out) {
24
24
  const EXPORT_TRIGGER_RE = /^export\s+const\s+(\w+)\s*(?::\s*[^=]+)?\s*=\s*(cron|on)\s*\(\s*(.+?)\s*,/gm;
25
25
  const EXPORT_STORAGE_HOOK_RE = /^export\s+const\s+(\w+)\s*(?::\s*[^=]+)?\s*=\s*storage\.(onUpload|onDelete)\s*\(/gm;
26
26
  var TriggerScanError = class extends Error {
27
+ file;
28
+ detail;
27
29
  constructor(file, detail) {
28
30
  super(`[vibes:triggers] ${file}: ${detail}`);
29
31
  this.file = file;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omg-dev/server",
3
- "version": "0.4.29",
3
+ "version": "0.4.31",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -14,14 +14,19 @@
14
14
  },
15
15
  "dependencies": {
16
16
  "@restatedev/restate-sdk": "1.14.5",
17
- "@omg-dev/auth": "0.4.29",
18
- "@omg-dev/schema": "0.4.29",
19
- "@omg-dev/stream": "0.4.29",
17
+ "@omg-dev/auth": "0.4.31",
18
+ "@omg-dev/schema": "0.4.31",
19
+ "@omg-dev/stream": "0.4.31",
20
20
  "web-push": "^3.6.7"
21
21
  },
22
22
  "scripts": {
23
23
  "build": "vp pack src/index.ts src/trigger-scan.ts --no-dts",
24
- "test": "vp test run"
24
+ "test": "vp test run",
25
+ "typecheck": "tsc6 --noEmit --allowImportingTsExtensions --types bun"
26
+ },
27
+ "devDependencies": {
28
+ "@types/bun": "^1.0.0",
29
+ "typescript": "npm:@typescript/typescript6@6.0.2"
25
30
  },
26
31
  "license": "MIT",
27
32
  "repository": {
@@ -0,0 +1,36 @@
1
+ import { afterEach, describe, expect, it } from "vitest"
2
+ import { agentBase } from "./agent-url.ts"
3
+
4
+ const originalOmgAgentUrl = process.env.OMG_AGENT_URL
5
+ const originalVibesAgentUrl = process.env.VIBES_AGENT_URL
6
+
7
+ afterEach(() => {
8
+ if (originalOmgAgentUrl === undefined) delete process.env.OMG_AGENT_URL
9
+ else process.env.OMG_AGENT_URL = originalOmgAgentUrl
10
+
11
+ if (originalVibesAgentUrl === undefined) delete process.env.VIBES_AGENT_URL
12
+ else process.env.VIBES_AGENT_URL = originalVibesAgentUrl
13
+ })
14
+
15
+ describe("agentBase", () => {
16
+ it("preserves the in-VM default when no override is set", () => {
17
+ delete process.env.OMG_AGENT_URL
18
+ delete process.env.VIBES_AGENT_URL
19
+
20
+ expect(agentBase()).toBe("http://localhost:8080")
21
+ })
22
+
23
+ it("uses VIBES_AGENT_URL as the compatibility override", () => {
24
+ delete process.env.OMG_AGENT_URL
25
+ process.env.VIBES_AGENT_URL = "http://127.0.0.1:4100"
26
+
27
+ expect(agentBase()).toBe("http://127.0.0.1:4100")
28
+ })
29
+
30
+ it("prefers OMG_AGENT_URL when both overrides are set", () => {
31
+ process.env.OMG_AGENT_URL = "http://127.0.0.1:4200"
32
+ process.env.VIBES_AGENT_URL = "http://127.0.0.1:4100"
33
+
34
+ expect(agentBase()).toBe("http://127.0.0.1:4200")
35
+ })
36
+ })
@@ -0,0 +1,11 @@
1
+ const DEFAULT_AGENT_URL = "http://localhost:8080"
2
+
3
+ /**
4
+ * Base URL for the in-VM agent.
5
+ *
6
+ * Read lazily so local runtimes can inject the emulator URL before loading
7
+ * user code without coupling the SDK to a particular process bootstrap.
8
+ */
9
+ export function agentBase(): string {
10
+ return process.env.OMG_AGENT_URL || process.env.VIBES_AGENT_URL || DEFAULT_AGENT_URL
11
+ }
package/src/billing.ts CHANGED
@@ -34,7 +34,8 @@
34
34
  // return Response.json(result)
35
35
  // }
36
36
 
37
- const AGENT_BASE = "http://localhost:8080"
37
+ import { agentBase } from "./agent-url.ts"
38
+
38
39
  const MICROS_PER_UNIT = 1_000_000
39
40
 
40
41
  /**
@@ -140,7 +141,7 @@ export interface GrantOptions {
140
141
  // out, throw on non-2xx with a truncated body for diagnosability.
141
142
 
142
143
  async function agentPost<T>(path: string, body: unknown, label: string): Promise<T> {
143
- const res = await fetch(`${AGENT_BASE}${path}`, {
144
+ const res = await fetch(`${agentBase()}${path}`, {
144
145
  method: "POST",
145
146
  headers: { "Content-Type": "application/json" },
146
147
  body: JSON.stringify(body),
@@ -153,7 +154,7 @@ async function agentPost<T>(path: string, body: unknown, label: string): Promise
153
154
  }
154
155
 
155
156
  async function agentGet<T>(path: string, label: string): Promise<T> {
156
- const res = await fetch(`${AGENT_BASE}${path}`, {
157
+ const res = await fetch(`${agentBase()}${path}`, {
157
158
  method: "GET",
158
159
  headers: { Accept: "application/json" },
159
160
  })
package/src/storage.ts CHANGED
@@ -31,6 +31,7 @@ import path from "node:path"
31
31
  import fs from "node:fs"
32
32
  import crypto from "node:crypto"
33
33
  import { ctxStore, ctx } from "./ctx.ts"
34
+ import { agentBase } from "./agent-url.ts"
34
35
 
35
36
  // ── Types ────────────────────────────────────────────────────────────────────
36
37
 
@@ -192,8 +193,6 @@ export const storage = {
192
193
 
193
194
  // ── prod-mode: HTTP to the agent ─────────────────────────────────────────────
194
195
 
195
- const AGENT_BASE = "http://localhost:8080"
196
-
197
196
  async function prodPresign(
198
197
  action: "put" | "get",
199
198
  key: string,
@@ -201,7 +200,7 @@ async function prodPresign(
201
200
  userId: string,
202
201
  contentType?: string,
203
202
  ): Promise<PresignedUploadResult> {
204
- const res = await fetch(`${AGENT_BASE}/_storage/presign`, {
203
+ const res = await fetch(`${agentBase()}/_storage/presign`, {
205
204
  method: "POST",
206
205
  headers: { "Content-Type": "application/json" },
207
206
  body: JSON.stringify({ action, key, scope, userId, contentType }),
@@ -221,7 +220,7 @@ async function prodPresign(
221
220
  }
222
221
 
223
222
  async function prodList(scope: StorageScope, userId: string, prefix: string, limit: number): Promise<StorageItem[]> {
224
- const res = await fetch(`${AGENT_BASE}/_storage/list`, {
223
+ const res = await fetch(`${agentBase()}/_storage/list`, {
225
224
  method: "POST",
226
225
  headers: { "Content-Type": "application/json" },
227
226
  body: JSON.stringify({ scope, userId, prefix, limit }),
@@ -247,7 +246,7 @@ async function prodList(scope: StorageScope, userId: string, prefix: string, lim
247
246
  }
248
247
 
249
248
  async function prodDelete(key: string, scope: StorageScope, userId: string): Promise<void> {
250
- const res = await fetch(`${AGENT_BASE}/_storage/delete`, {
249
+ const res = await fetch(`${agentBase()}/_storage/delete`, {
251
250
  method: "POST",
252
251
  headers: { "Content-Type": "application/json" },
253
252
  body: JSON.stringify({ key, scope, userId }),
package/src/triggers.ts CHANGED
@@ -25,6 +25,7 @@
25
25
  import path from "node:path"
26
26
  import fs from "node:fs"
27
27
  import { ctxStore, type VibesCtx } from "./ctx.ts"
28
+ import { agentBase } from "./agent-url.ts"
28
29
 
29
30
  // ── Public API ───────────────────────────────────────────────────────────────
30
31
 
@@ -480,7 +481,7 @@ async function emitToOrchestrator(topic: string, payload: unknown): Promise<{ su
480
481
  if (payloadStr.length > MAX_EMIT_BYTES) {
481
482
  throw new Error(`emit("${topic}"): payload exceeds ${MAX_EMIT_BYTES} bytes`)
482
483
  }
483
- const url = "http://localhost:8080/_emit"
484
+ const url = `${agentBase()}/_emit`
484
485
  const res = await fetch(url, {
485
486
  method: "POST",
486
487
  headers: { "Content-Type": "application/json" },
@@ -637,7 +638,7 @@ async function scheduleToOrchestrator(
637
638
  if (payloadStr.length > MAX_EMIT_BYTES) {
638
639
  throw new Error(`schedule("${topic}"): payload exceeds ${MAX_EMIT_BYTES} bytes`)
639
640
  }
640
- const url = "http://localhost:8080/_schedule"
641
+ const url = `${agentBase()}/_schedule`
641
642
  const res = await fetch(url, {
642
643
  method: "POST",
643
644
  headers: { "Content-Type": "application/json" },
@@ -664,7 +665,7 @@ async function scheduleToOrchestrator(
664
665
  }
665
666
 
666
667
  async function cancelOnOrchestrator(eventId: string): Promise<{ cancelled: number }> {
667
- const url = `http://localhost:8080/_schedule/${encodeURIComponent(eventId)}`
668
+ const url = `${agentBase()}/_schedule/${encodeURIComponent(eventId)}`
668
669
  const res = await fetch(url, { method: "DELETE" })
669
670
  if (!res.ok) {
670
671
  const text = await res.text().catch(() => "")
package/src/workflows.ts CHANGED
@@ -38,6 +38,7 @@
38
38
  import path from "node:path"
39
39
  import fs from "node:fs"
40
40
  import { ctxStore, type VibesCtx } from "./ctx.ts"
41
+ import { agentBase } from "./agent-url.ts"
41
42
 
42
43
  // ── Public API ───────────────────────────────────────────────────────────────
43
44
 
@@ -417,7 +418,7 @@ async function startViaAgent(
417
418
  payloadStr: string,
418
419
  opts: StartWorkflowOptions,
419
420
  ): Promise<{ runId: string }> {
420
- const res = await fetch("http://localhost:8080/_workflow/start", {
421
+ const res = await fetch(`${agentBase()}/_workflow/start`, {
421
422
  method: "POST",
422
423
  headers: { "Content-Type": "application/json" },
423
424
  body: JSON.stringify({