@vibes.diy/api-svc 12.1.0 → 12.1.2

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 (73) hide show
  1. package/evento-handler-manifest.js +5 -0
  2. package/evento-handler-manifest.js.map +1 -1
  3. package/index.d.ts +2 -0
  4. package/index.js +2 -0
  5. package/index.js.map +1 -1
  6. package/intern/attempt-backend-fetch.d.ts +4 -0
  7. package/intern/attempt-backend-fetch.js +13 -0
  8. package/intern/attempt-backend-fetch.js.map +1 -1
  9. package/intern/attempt-backend-onchange.d.ts +4 -0
  10. package/intern/attempt-backend-onchange.js +12 -0
  11. package/intern/attempt-backend-onchange.js.map +1 -1
  12. package/intern/attempt-backend-scheduled.d.ts +4 -0
  13. package/intern/attempt-backend-scheduled.js +12 -0
  14. package/intern/attempt-backend-scheduled.js.map +1 -1
  15. package/intern/backend-db-callback.d.ts +1 -0
  16. package/intern/backend-db-callback.js +54 -8
  17. package/intern/backend-db-callback.js.map +1 -1
  18. package/intern/backend-do-addr.d.ts +6 -0
  19. package/intern/backend-do-addr.js +10 -1
  20. package/intern/backend-do-addr.js.map +1 -1
  21. package/intern/backend-do-control-plane.d.ts +34 -0
  22. package/intern/backend-do-control-plane.js +68 -0
  23. package/intern/backend-do-control-plane.js.map +1 -0
  24. package/intern/backend-log-callback.d.ts +20 -0
  25. package/intern/backend-log-callback.js +47 -0
  26. package/intern/backend-log-callback.js.map +1 -0
  27. package/intern/backend-log-op.d.ts +1 -0
  28. package/intern/backend-log-op.js +2 -0
  29. package/intern/backend-log-op.js.map +1 -0
  30. package/intern/backend-log-rate.d.ts +12 -0
  31. package/intern/backend-log-rate.js +25 -0
  32. package/intern/backend-log-rate.js.map +1 -0
  33. package/intern/backend-tick-liveness.d.ts +20 -0
  34. package/intern/backend-tick-liveness.js +26 -0
  35. package/intern/backend-tick-liveness.js.map +1 -0
  36. package/intern/client-log-ingest.d.ts +35 -0
  37. package/intern/client-log-ingest.js +119 -0
  38. package/intern/client-log-ingest.js.map +1 -0
  39. package/intern/load-selected-backend.d.ts +1 -0
  40. package/intern/load-selected-backend.js +1 -1
  41. package/intern/load-selected-backend.js.map +1 -1
  42. package/intern/notify-tick-silent.d.ts +10 -0
  43. package/intern/notify-tick-silent.js +31 -0
  44. package/intern/notify-tick-silent.js.map +1 -0
  45. package/intern/prune-vibe-logs.d.ts +13 -0
  46. package/intern/prune-vibe-logs.js +26 -0
  47. package/intern/prune-vibe-logs.js.map +1 -0
  48. package/intern/swr-html-cache-orchestrator.d.ts +2 -2
  49. package/intern/swr-html-cache-orchestrator.js +23 -10
  50. package/intern/swr-html-cache-orchestrator.js.map +1 -1
  51. package/intern/swr-html-cache.d.ts +3 -1
  52. package/intern/swr-html-cache.js +4 -3
  53. package/intern/swr-html-cache.js.map +1 -1
  54. package/package.json +12 -11
  55. package/public/app-documents-query-filter.d.ts +1 -0
  56. package/public/app-documents-query-filter.js +34 -6
  57. package/public/app-documents-query-filter.js.map +1 -1
  58. package/public/app-documents.d.ts +1 -1
  59. package/public/app-documents.js +1 -1
  60. package/public/app-documents.js.map +1 -1
  61. package/public/app-logs.d.ts +4 -0
  62. package/public/app-logs.js +109 -0
  63. package/public/app-logs.js.map +1 -0
  64. package/public/app-tick.d.ts +4 -0
  65. package/public/app-tick.js +143 -0
  66. package/public/app-tick.js.map +1 -0
  67. package/public/root-html-live-inputs.d.ts +2 -1
  68. package/public/root-html-live-inputs.js +5 -2
  69. package/public/root-html-live-inputs.js.map +1 -1
  70. package/public/serv-entry-point.js +4 -1
  71. package/public/serv-entry-point.js.map +1 -1
  72. package/types.d.ts +2 -0
  73. package/types.js.map +1 -1
@@ -0,0 +1,68 @@
1
+ import { exception2Result, Result } from "@adviser/cement";
2
+ import { backendDoName, BACKEND_INTERNAL_AUTH_HEADER, BACKEND_OP_ARM, BACKEND_OP_HEADER, BACKEND_OP_STATUS, BACKEND_OWNER_HEADER, BACKEND_SLUG_HEADER, } from "./backend-do-addr.js";
3
+ function authHeaders(secret) {
4
+ if (secret === undefined)
5
+ return {};
6
+ return { [BACKEND_INTERNAL_AUTH_HEADER]: secret };
7
+ }
8
+ function alarmOwnerNamespace(env) {
9
+ if (env.BACKEND_ALARM_OWNER === "true") {
10
+ const ns = env.BACKEND_DO;
11
+ if (ns === undefined)
12
+ return Result.Err("BACKEND_ALARM_OWNER is set but this worker has no BACKEND_DO binding");
13
+ return Result.Ok(ns);
14
+ }
15
+ return Result.Err(`this environment (${env.ENVIRONMENT ?? "unknown"}) does not own scheduled-tick alarms, and has no binding to the worker that does — ` +
16
+ `run this against the alarm-owning endpoint. Acting on the local BackendDO here would report the wrong state and could arm a duplicate timer.`);
17
+ }
18
+ export function backendControlPlaneCallbacks(env) {
19
+ if (env.BACKEND_DO === undefined)
20
+ return {};
21
+ const rNs = alarmOwnerNamespace(env);
22
+ if (rNs.isErr()) {
23
+ const err = rNs.Err();
24
+ return {
25
+ backendControlPlane: {
26
+ tickStatus: () => Promise.resolve(Result.Err(err)),
27
+ arm: () => Promise.resolve(Result.Err(err)),
28
+ },
29
+ };
30
+ }
31
+ const ns = rNs.Ok();
32
+ const poke = async (ownerHandle, appSlug, op) => {
33
+ const stub = ns.get(ns.idFromName(backendDoName(ownerHandle, appSlug)));
34
+ const rRes = await exception2Result(() => stub.fetch(new Request(`https://internal/__backend_${op}`, {
35
+ method: "POST",
36
+ headers: {
37
+ [BACKEND_OWNER_HEADER]: ownerHandle,
38
+ [BACKEND_SLUG_HEADER]: appSlug,
39
+ [BACKEND_OP_HEADER]: op,
40
+ ...authHeaders(env.BACKEND_INTERNAL_SECRET),
41
+ },
42
+ })));
43
+ if (rRes.isErr())
44
+ return Result.Err(rRes.Err());
45
+ const res = rRes.Ok();
46
+ if (res.status >= 300)
47
+ return Result.Err(`backend ${op} poke got ${res.status}`);
48
+ return Result.Ok(res);
49
+ };
50
+ return {
51
+ backendControlPlane: {
52
+ tickStatus: async (ownerHandle, appSlug) => {
53
+ const rRes = await poke(ownerHandle, appSlug, BACKEND_OP_STATUS);
54
+ if (rRes.isErr())
55
+ return Result.Err(rRes.Err());
56
+ const rJson = await exception2Result(() => rRes.Ok().json());
57
+ if (rJson.isErr())
58
+ return Result.Err(rJson.Err());
59
+ return Result.Ok(rJson.Ok());
60
+ },
61
+ arm: async (ownerHandle, appSlug) => {
62
+ const rRes = await poke(ownerHandle, appSlug, BACKEND_OP_ARM);
63
+ return rRes.isErr() ? Result.Err(rRes.Err()) : Result.Ok();
64
+ },
65
+ },
66
+ };
67
+ }
68
+ //# sourceMappingURL=backend-do-control-plane.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-do-control-plane.js","sourceRoot":"","sources":["../../jsr/intern/backend-do-control-plane.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { BackendLogCallback } from "@vibes.diy/vibe-runtime/backend-executor.js";
2
+ import { type LogIdLatch, type VibeLogTrigger } from "@vibes.diy/api-types";
3
+ import { VibesApiSQLCtx } from "../types.js";
4
+ import { BackendLogRateWindow } from "./backend-log-rate.js";
5
+ export interface BackendLogCallbackBase {
6
+ readonly ownerHandle: string;
7
+ readonly appSlug: string;
8
+ readonly fsId: string;
9
+ readonly trigger: VibeLogTrigger;
10
+ readonly viewerHandle?: string | null;
11
+ readonly rate?: BackendLogRateWindow;
12
+ readonly idLatch?: LogIdLatch;
13
+ }
14
+ export declare function makeBackendLogCallback(vctx: VibesApiSQLCtx, base: BackendLogCallbackBase): {
15
+ readonly log: BackendLogCallback;
16
+ readonly flush: () => Promise<void>;
17
+ };
18
+ export declare function flushBackendLog(vctx: VibesApiSQLCtx, lane: {
19
+ readonly flush: () => Promise<void>;
20
+ }): Promise<void>;
@@ -0,0 +1,47 @@
1
+ import { exception2Result } from "@adviser/cement";
2
+ import { mintLogEventId, newLogIdLatch, normalizeLogLevel, truncateLogBody, } from "@vibes.diy/api-types";
3
+ import { BackendLogRateWindow } from "./backend-log-rate.js";
4
+ export function makeBackendLogCallback(vctx, base) {
5
+ const rate = base.rate ?? new BackendLogRateWindow();
6
+ const idLatch = base.idLatch ?? newLogIdLatch();
7
+ const buffered = [];
8
+ const log = async (op) => {
9
+ const body = typeof op?.body === "string" ? truncateLogBody(op.body) : "";
10
+ if (body.length === 0)
11
+ return { ok: true };
12
+ const now = Date.now();
13
+ if (!rate.admit(now))
14
+ return { ok: true };
15
+ buffered.push({
16
+ id: mintLogEventId(idLatch, now, vctx.sthis.nextId().str),
17
+ ownerHandle: base.ownerHandle,
18
+ appSlug: base.appSlug,
19
+ lane: "backend",
20
+ level: normalizeLogLevel(op?.level),
21
+ ts: new Date(now).toISOString(),
22
+ fsId: base.fsId,
23
+ trigger: base.trigger,
24
+ sessionId: null,
25
+ deviceHash: null,
26
+ viewerHandle: base.viewerHandle ?? null,
27
+ body,
28
+ country: null,
29
+ });
30
+ return { ok: true };
31
+ };
32
+ const flush = async () => {
33
+ if (buffered.length === 0)
34
+ return;
35
+ const rows = buffered.splice(0, buffered.length);
36
+ await exception2Result(() => vctx.sql.db.insert(vctx.sql.tables.vibeLogEvents).values(rows));
37
+ };
38
+ return { log, flush };
39
+ }
40
+ export async function flushBackendLog(vctx, lane) {
41
+ if (vctx.waitUntil) {
42
+ vctx.waitUntil(lane.flush());
43
+ return;
44
+ }
45
+ await lane.flush();
46
+ }
47
+ //# sourceMappingURL=backend-log-callback.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-log-callback.js","sourceRoot":"","sources":["../../jsr/intern/backend-log-callback.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EACL,cAAc,EACd,aAAa,EACb,iBAAiB,EACjB,eAAe,GAGhB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAsE7D,MAAM,UAAU,sBAAsB,CACpC,IAAoB,EACpB,IAA4B;IAE5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,oBAAoB,EAAE,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,aAAa,EAAE,CAAC;IAChD,MAAM,QAAQ,GAAuB,EAAE,CAAC;IAExC,MAAM,GAAG,GAAuB,KAAK,EAAE,EAAgB,EAA6B,EAAE;QACpF,MAAM,IAAI,GAAG,OAAO,EAAE,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1E,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAEvB,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC;YACZ,EAAE,EAAE,cAAc,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC;YACzD,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,IAAI,EAAE,SAAS;YACf,KAAK,EAAE,iBAAiB,CAAC,EAAE,EAAE,KAAK,CAAC;YACnC,EAAE,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE;YAC/B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,OAAO,EAAE,IAAI,CAAC,OAAO;YAGrB,SAAS,EAAE,IAAI;YACf,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,IAAI,CAAC,YAAY,IAAI,IAAI;YACvC,IAAI;YACJ,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;IACtB,CAAC,CAAC;IAEF,MAAM,KAAK,GAAG,KAAK,IAAmB,EAAE;QACtC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAClC,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAIjD,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/F,CAAC,CAAC;IAEF,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACxB,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAoB,EAAE,IAA6C;IACvG,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;QACnB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IACD,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1 @@
1
+ export { BACKEND_LOG_OP_URL, handleBackendLogOp } from "@vibes.diy/vibe-runtime/backend-executor.js";
@@ -0,0 +1,2 @@
1
+ export { BACKEND_LOG_OP_URL, handleBackendLogOp } from "@vibes.diy/vibe-runtime/backend-executor.js";
2
+ //# sourceMappingURL=backend-log-op.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-log-op.js","sourceRoot":"","sources":["../../jsr/intern/backend-log-op.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC"}
@@ -0,0 +1,12 @@
1
+ export interface LogRateLimits {
2
+ readonly burstLimit: number;
3
+ readonly burstWindowMs: number;
4
+ readonly sustainedLimit: number;
5
+ readonly sustainedWindowMs: number;
6
+ }
7
+ export declare class BackendLogRateWindow {
8
+ private stamps;
9
+ private readonly limits;
10
+ constructor(limits?: LogRateLimits);
11
+ admit(now: number): boolean;
12
+ }
@@ -0,0 +1,25 @@
1
+ import { LOG_BACKEND_BURST_LIMIT, LOG_BACKEND_BURST_WINDOW_MS, LOG_BACKEND_SUSTAINED_LIMIT, LOG_BACKEND_SUSTAINED_WINDOW_MS, } from "@vibes.diy/api-types";
2
+ const BACKEND_LOG_RATE_LIMITS = {
3
+ burstLimit: LOG_BACKEND_BURST_LIMIT,
4
+ burstWindowMs: LOG_BACKEND_BURST_WINDOW_MS,
5
+ sustainedLimit: LOG_BACKEND_SUSTAINED_LIMIT,
6
+ sustainedWindowMs: LOG_BACKEND_SUSTAINED_WINDOW_MS,
7
+ };
8
+ export class BackendLogRateWindow {
9
+ stamps = [];
10
+ limits;
11
+ constructor(limits = BACKEND_LOG_RATE_LIMITS) {
12
+ this.limits = limits;
13
+ }
14
+ admit(now) {
15
+ this.stamps = this.stamps.filter((s) => now - s < this.limits.sustainedWindowMs);
16
+ const inBurst = this.stamps.filter((s) => now - s < this.limits.burstWindowMs).length;
17
+ if (inBurst >= this.limits.burstLimit)
18
+ return false;
19
+ if (this.stamps.length >= this.limits.sustainedLimit)
20
+ return false;
21
+ this.stamps.push(now);
22
+ return true;
23
+ }
24
+ }
25
+ //# sourceMappingURL=backend-log-rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-log-rate.js","sourceRoot":"","sources":["../../jsr/intern/backend-log-rate.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,2BAA2B,EAC3B,2BAA2B,EAC3B,+BAA+B,GAChC,MAAM,sBAAsB,CAAC;AA+B9B,MAAM,uBAAuB,GAAkB;IAC7C,UAAU,EAAE,uBAAuB;IACnC,aAAa,EAAE,2BAA2B;IAC1C,cAAc,EAAE,2BAA2B;IAC3C,iBAAiB,EAAE,+BAA+B;CACnD,CAAC;AAEF,MAAM,OAAO,oBAAoB;IACvB,MAAM,GAAa,EAAE,CAAC;IACb,MAAM,CAAgB;IAGvC,YAAY,MAAM,GAAkB,uBAAuB;QACzD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAGD,KAAK,CAAC,GAAW;QACf,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC;QACtF,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACpD,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,CAAC,cAAc;YAAE,OAAO,KAAK,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ export declare const OVERDUE_GRACE_MULTIPLE = 3;
2
+ export declare const MIN_GRACE_MS: number;
3
+ export type TickLivenessState = "unscheduled" | "running" | "healthy" | "overdue" | "dead";
4
+ export interface TickLivenessInput {
5
+ readonly intervalMs: number | null;
6
+ readonly armedAt?: string;
7
+ readonly lastAttemptAt?: string;
8
+ readonly lastRunAt?: string;
9
+ readonly nextAlarmAt: number | null;
10
+ readonly ticking: boolean;
11
+ readonly now: number;
12
+ }
13
+ export interface TickLivenessVerdict {
14
+ readonly state: TickLivenessState;
15
+ readonly graceMs: number;
16
+ readonly silenceMs: number;
17
+ readonly overdueMs: number;
18
+ readonly nextExpectedAt: string | null;
19
+ }
20
+ export declare function tickLiveness(input: TickLivenessInput): TickLivenessVerdict;
@@ -0,0 +1,26 @@
1
+ export const OVERDUE_GRACE_MULTIPLE = 3;
2
+ export const MIN_GRACE_MS = 5 * 60_000;
3
+ function instant(iso) {
4
+ if (iso === undefined)
5
+ return undefined;
6
+ const ms = Date.parse(iso);
7
+ return Number.isFinite(ms) ? ms : undefined;
8
+ }
9
+ export function tickLiveness(input) {
10
+ const nextExpectedAt = input.nextAlarmAt === null ? null : new Date(input.nextAlarmAt).toISOString();
11
+ if (input.intervalMs === null) {
12
+ return { state: "unscheduled", graceMs: 0, silenceMs: 0, overdueMs: 0, nextExpectedAt: null };
13
+ }
14
+ const graceMs = Math.max(MIN_GRACE_MS, input.intervalMs * OVERDUE_GRACE_MULTIPLE);
15
+ const reference = instant(input.lastAttemptAt) ?? instant(input.lastRunAt) ?? instant(input.armedAt);
16
+ const silenceMs = reference === undefined ? 0 : Math.max(0, input.now - reference);
17
+ const overdueMs = Math.max(0, silenceMs - graceMs);
18
+ if (input.ticking) {
19
+ return { state: "running", graceMs, silenceMs, overdueMs, nextExpectedAt };
20
+ }
21
+ if (input.nextAlarmAt === null) {
22
+ return { state: "dead", graceMs, silenceMs, overdueMs, nextExpectedAt: null };
23
+ }
24
+ return { state: overdueMs > 0 ? "overdue" : "healthy", graceMs, silenceMs, overdueMs, nextExpectedAt };
25
+ }
26
+ //# sourceMappingURL=backend-tick-liveness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend-tick-liveness.js","sourceRoot":"","sources":["../../jsr/intern/backend-tick-liveness.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC;AAmDvC,SAAS,OAAO,CAAC,GAAuB;IACtC,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AAC9C,CAAC;AA0BD,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,cAAc,GAAG,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,WAAW,EAAE,CAAC;IACrG,IAAI,KAAK,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC9B,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IAChG,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,UAAU,GAAG,sBAAsB,CAAC,CAAC;IAGlF,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAErG,MAAM,SAAS,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC;IACnF,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QAGlB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;IAC7E,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;QAC/B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC;IAChF,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC;AACzG,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { type LogIdLatch } from "@vibes.diy/api-types";
2
+ import { VibesApiSQLCtx } from "../types.js";
3
+ export declare function exceedsClientLogByteCap(body: string): boolean;
4
+ export type ClientLogVisibility = "visible" | "hidden";
5
+ export interface ClientLogEvent {
6
+ readonly level: string;
7
+ readonly body: string;
8
+ readonly visibility: ClientLogVisibility | null;
9
+ readonly hiddenMs: number | null;
10
+ }
11
+ export interface ClientLogBatch {
12
+ readonly sessionId: string | null;
13
+ readonly deviceHash: string | null;
14
+ readonly fsId: string;
15
+ readonly viewerHandle: string | null;
16
+ readonly events: readonly ClientLogEvent[];
17
+ }
18
+ export declare function parseClientLogBatch(raw: unknown): ClientLogBatch | undefined;
19
+ export declare class ClientLogRateWindows {
20
+ private readonly windows;
21
+ admit(deviceHash: string, now: number): boolean;
22
+ get size(): number;
23
+ }
24
+ export interface ClientLogIngestBase {
25
+ readonly ownerHandle: string;
26
+ readonly appSlug: string;
27
+ readonly country: string | null;
28
+ readonly rate?: ClientLogRateWindows;
29
+ readonly idLatch?: LogIdLatch;
30
+ }
31
+ export interface ClientLogIngestResult {
32
+ readonly admitted: number;
33
+ readonly dropped: number;
34
+ }
35
+ export declare function ingestClientLogBatch(vctx: VibesApiSQLCtx, base: ClientLogIngestBase, batch: ClientLogBatch): Promise<ClientLogIngestResult>;
@@ -0,0 +1,119 @@
1
+ import { exception2Result } from "@adviser/cement";
2
+ import { LOG_CLIENT_BATCH_MAX_EVENTS, LOG_CLIENT_BURST_LIMIT, LOG_CLIENT_BURST_WINDOW_MS, LOG_CLIENT_DEVICE_WINDOWS_MAX, LOG_CLIENT_REQUEST_MAX_BYTES, LOG_CLIENT_SUSTAINED_LIMIT, LOG_CLIENT_SUSTAINED_WINDOW_MS, LOG_CLIENT_TRIGGER, mintLogEventId, newLogIdLatch, normalizeLogLevel, truncateLogBody, } from "@vibes.diy/api-types";
3
+ import { BackendLogRateWindow } from "./backend-log-rate.js";
4
+ const SESSION_ID_MAX = 64;
5
+ const DEVICE_HASH_MAX = 64;
6
+ const FS_ID_MAX = 128;
7
+ const VIEWER_HANDLE_MAX = 64;
8
+ const HIDDEN_MS_MAX = 7 * 24 * 60 * 60 * 1000;
9
+ const CLIENT_LOG_RATE_LIMITS = {
10
+ burstLimit: LOG_CLIENT_BURST_LIMIT,
11
+ burstWindowMs: LOG_CLIENT_BURST_WINDOW_MS,
12
+ sustainedLimit: LOG_CLIENT_SUSTAINED_LIMIT,
13
+ sustainedWindowMs: LOG_CLIENT_SUSTAINED_WINDOW_MS,
14
+ };
15
+ export function exceedsClientLogByteCap(body) {
16
+ return new TextEncoder().encode(body).length > LOG_CLIENT_REQUEST_MAX_BYTES;
17
+ }
18
+ function boundedString(v, max) {
19
+ if (typeof v !== "string")
20
+ return null;
21
+ const s = v.slice(0, max);
22
+ return s.length === 0 ? null : s;
23
+ }
24
+ function boundedHiddenMs(v) {
25
+ if (typeof v !== "number" || !Number.isFinite(v) || v < 0)
26
+ return null;
27
+ return Math.min(Math.floor(v), HIDDEN_MS_MAX);
28
+ }
29
+ function visibilityOf(v) {
30
+ return v === "visible" || v === "hidden" ? v : null;
31
+ }
32
+ export function parseClientLogBatch(raw) {
33
+ if (typeof raw !== "object" || raw === null)
34
+ return undefined;
35
+ const b = raw;
36
+ const rawEvents = Array.isArray(b.events) ? b.events : [];
37
+ const events = [];
38
+ for (const e of rawEvents.slice(0, LOG_CLIENT_BATCH_MAX_EVENTS)) {
39
+ if (typeof e !== "object" || e === null)
40
+ continue;
41
+ const ev = e;
42
+ const body = typeof ev.body === "string" ? truncateLogBody(ev.body) : "";
43
+ if (body.length === 0)
44
+ continue;
45
+ events.push({
46
+ level: normalizeLogLevel(ev.level),
47
+ body,
48
+ visibility: visibilityOf(ev.visibility),
49
+ hiddenMs: boundedHiddenMs(ev.hiddenMs),
50
+ });
51
+ }
52
+ if (events.length === 0)
53
+ return undefined;
54
+ return {
55
+ sessionId: boundedString(b.sessionId, SESSION_ID_MAX),
56
+ deviceHash: boundedString(b.deviceHash, DEVICE_HASH_MAX),
57
+ fsId: boundedString(b.fsId, FS_ID_MAX) ?? "unknown",
58
+ viewerHandle: boundedString(b.viewerHandle, VIEWER_HANDLE_MAX),
59
+ events,
60
+ };
61
+ }
62
+ export class ClientLogRateWindows {
63
+ windows = new Map();
64
+ admit(deviceHash, now) {
65
+ const existing = this.windows.get(deviceHash);
66
+ if (existing) {
67
+ this.windows.delete(deviceHash);
68
+ this.windows.set(deviceHash, existing);
69
+ return existing.admit(now);
70
+ }
71
+ if (this.windows.size >= LOG_CLIENT_DEVICE_WINDOWS_MAX) {
72
+ const oldest = this.windows.keys().next();
73
+ if (!oldest.done)
74
+ this.windows.delete(oldest.value);
75
+ }
76
+ const fresh = new BackendLogRateWindow(CLIENT_LOG_RATE_LIMITS);
77
+ this.windows.set(deviceHash, fresh);
78
+ return fresh.admit(now);
79
+ }
80
+ get size() {
81
+ return this.windows.size;
82
+ }
83
+ }
84
+ export async function ingestClientLogBatch(vctx, base, batch) {
85
+ const rate = base.rate ?? new ClientLogRateWindows();
86
+ const idLatch = base.idLatch ?? newLogIdLatch();
87
+ const key = batch.deviceHash ?? "unkeyed";
88
+ const now = Date.now();
89
+ const rows = [];
90
+ let dropped = 0;
91
+ for (const ev of batch.events) {
92
+ if (!rate.admit(key, now)) {
93
+ dropped++;
94
+ continue;
95
+ }
96
+ rows.push({
97
+ id: mintLogEventId(idLatch, now, vctx.sthis.nextId().str),
98
+ ownerHandle: base.ownerHandle,
99
+ appSlug: base.appSlug,
100
+ lane: "client",
101
+ level: ev.level,
102
+ ts: new Date(now).toISOString(),
103
+ fsId: batch.fsId,
104
+ trigger: LOG_CLIENT_TRIGGER,
105
+ sessionId: batch.sessionId,
106
+ deviceHash: batch.deviceHash,
107
+ viewerHandle: batch.viewerHandle,
108
+ body: ev.body,
109
+ country: base.country,
110
+ visibility: ev.visibility,
111
+ hiddenMs: ev.hiddenMs,
112
+ });
113
+ }
114
+ if (rows.length === 0)
115
+ return { admitted: 0, dropped };
116
+ await exception2Result(() => vctx.sql.db.insert(vctx.sql.tables.vibeLogEvents).values(rows));
117
+ return { admitted: rows.length, dropped };
118
+ }
119
+ //# sourceMappingURL=client-log-ingest.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-log-ingest.js","sourceRoot":"","sources":["../../jsr/intern/client-log-ingest.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,7 @@ export type LoadSelectedBackendResult = {
5
5
  readonly ok: true;
6
6
  readonly source: string;
7
7
  readonly parsed: BackendConfigParseResult;
8
+ readonly fsId: string;
8
9
  } | {
9
10
  readonly ok: false;
10
11
  readonly reason: LoadSelectedBackendReason;
@@ -19,7 +19,7 @@ export async function loadSelectedBackend(vctx, ownerHandle, appSlug) {
19
19
  const source = rSource.Ok();
20
20
  if (source.length === 0)
21
21
  return { ok: false, reason: "source_unreadable" };
22
- return { ok: true, source, parsed: parseBackendConfig(source) };
22
+ return { ok: true, source, parsed: parseBackendConfig(source), fsId: row.fsId };
23
23
  }
24
24
  export async function resolveBackendSchedule(vctx, ownerHandle, appSlug) {
25
25
  const loaded = await loadSelectedBackend(vctx, ownerHandle, appSlug);
@@ -1 +1 @@
1
- {"version":3,"file":"load-selected-backend.js","sourceRoot":"","sources":["../../jsr/intern/load-selected-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAiC,MAAM,iDAAiD,CAAC;AAEpH,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAqBvC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAoB,EACpB,WAAmB,EACnB,OAAe;IAEf,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAClG,IAAI,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAElE,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAqB,CAAC;IAC9D,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,gBAAgB,CAAC,CAAC;IAC5E,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAE/E,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrF,IAAI,OAAO,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC;IAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAE3E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;AAClE,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAoB,EAAE,WAAmB,EAAE,OAAe;IACrG,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,IAAI,IAAI,CAAC;AACpD,CAAC;AAGD,KAAK,UAAU,UAAU,CAAC,IAAoB,EAAE,QAAgB;IAC9D,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,IAAI,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAC7F,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAChE,CAAC"}
1
+ {"version":3,"file":"load-selected-backend.js","sourceRoot":"","sources":["../../jsr/intern/load-selected-backend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAAiC,MAAM,iDAAiD,CAAC;AAEpH,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,MAAM,gBAAgB,GAAG,aAAa,CAAC;AAiCvC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAoB,EACpB,WAAmB,EACnB,OAAe;IAEf,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,sBAAsB,CAAC,IAAI,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC;IAClG,IAAI,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAC7D,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,EAAE,CAAC;IACtB,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAElE,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAqB,CAAC;IAC9D,MAAM,WAAW,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,gBAAgB,CAAC,CAAC;IAC5E,IAAI,WAAW,KAAK,SAAS;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAE/E,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrF,IAAI,OAAO,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,EAAE,EAAE,CAAC;IAC5B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAE3E,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;AAClF,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,IAAoB,EAAE,WAAmB,EAAE,OAAe;IACrG,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IACrE,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,WAAW,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/D,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,UAAU,IAAI,IAAI,CAAC;AACpD,CAAC;AAGD,KAAK,UAAU,UAAU,CAAC,IAAoB,EAAE,QAAgB;IAC9D,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,IAAI,KAAK,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,IAAI,QAAQ,QAAQ,EAAE,CAAC,CAAC;IAC7F,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAChE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { EmitNotificationCtx } from "./emit-notification.js";
2
+ import { TickLivenessState } from "./backend-tick-liveness.js";
3
+ export interface TickSilentNotifyInput {
4
+ readonly ownerHandle: string;
5
+ readonly appSlug: string;
6
+ readonly state: TickLivenessState;
7
+ readonly silenceMs: number;
8
+ readonly now?: number;
9
+ }
10
+ export declare function notifyTickSilent(qctx: EmitNotificationCtx, input: TickSilentNotifyInput): Promise<void>;
@@ -0,0 +1,31 @@
1
+ import { eq } from "drizzle-orm/sql/expressions";
2
+ import { emitNotification } from "./emit-notification.js";
3
+ import { humanizeDuration } from "@vibes.diy/api-types";
4
+ export async function notifyTickSilent(qctx, input) {
5
+ if (input.state !== "dead" && input.state !== "overdue")
6
+ return;
7
+ const hb = qctx.sql.tables.handleBinding;
8
+ const owner = await qctx.sql.db
9
+ .select({ userId: hb.userId })
10
+ .from(hb)
11
+ .where(eq(hb.handle, input.ownerHandle))
12
+ .limit(1)
13
+ .then((r) => r[0]);
14
+ if (owner === undefined)
15
+ return;
16
+ const app = `${input.ownerHandle}/${input.appSlug}`;
17
+ const since = input.silenceMs > 0 ? ` It last tried about ${humanizeDuration(input.silenceMs)} ago.` : "";
18
+ const body = input.state === "dead"
19
+ ? `The scheduled task in ${app} had no timer registered, so it was not going to run again. We restarted it.${since}`
20
+ : `The scheduled task in ${app} has not run for about ${humanizeDuration(input.silenceMs)}.`;
21
+ const day = new Date(input.now ?? Date.now()).toISOString().slice(0, 10);
22
+ await emitNotification(qctx, {
23
+ userId: owner.userId,
24
+ notificationType: "app-message",
25
+ ownerHandle: input.ownerHandle,
26
+ appSlug: input.appSlug,
27
+ body,
28
+ dedupeKey: `tick-silent:${app}:${day}`,
29
+ });
30
+ }
31
+ //# sourceMappingURL=notify-tick-silent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify-tick-silent.js","sourceRoot":"","sources":["../../jsr/intern/notify-tick-silent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,6BAA6B,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAuB,MAAM,wBAAwB,CAAC;AAE/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAgDxD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAyB,EAAE,KAA4B;IAC5F,IAAI,KAAK,CAAC,KAAK,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO;IAEhE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,EAAE;SAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC;SAC7B,IAAI,CAAC,EAAE,CAAC;SACR,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;SACvC,KAAK,CAAC,CAAC,CAAC;SACR,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO;IAEhC,MAAM,GAAG,GAAG,GAAG,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;IAGpD,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,wBAAwB,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1G,MAAM,IAAI,GACR,KAAK,CAAC,KAAK,KAAK,MAAM;QACpB,CAAC,CAAC,yBAAyB,GAAG,+EAA+E,KAAK,EAAE;QACpH,CAAC,CAAC,yBAAyB,GAAG,0BAA0B,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC;IAEjG,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACzE,MAAM,gBAAgB,CAAC,IAAI,EAAE;QAC3B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,gBAAgB,EAAE,aAAa;QAC/B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI;QACJ,SAAS,EAAE,eAAe,GAAG,IAAI,GAAG,EAAE;KACvC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { cfDrizzle, VibesApiTables } from "@vibes.diy/api-sql";
2
+ export interface PruneVibeLogsSql {
3
+ readonly db: ReturnType<typeof cfDrizzle>["db"];
4
+ readonly tables: VibesApiTables;
5
+ }
6
+ export declare const PRUNE_BATCH_SIZE = 5000;
7
+ export declare const PRUNE_MAX_BATCHES = 20;
8
+ export interface PruneVibeLogsResult {
9
+ readonly deleted: number;
10
+ readonly prunedThrough: string;
11
+ readonly capped: boolean;
12
+ }
13
+ export declare function pruneVibeLogEvents(sql: PruneVibeLogsSql, nowMs: number): Promise<PruneVibeLogsResult>;
@@ -0,0 +1,26 @@
1
+ import { and, asc, lt, lte } from "drizzle-orm/sql/expressions";
2
+ import { logRetentionIdFloor } from "@vibes.diy/api-types";
3
+ export const PRUNE_BATCH_SIZE = 5000;
4
+ export const PRUNE_MAX_BATCHES = 20;
5
+ export async function pruneVibeLogEvents(sql, nowMs) {
6
+ const t = sql.tables.vibeLogEvents;
7
+ const prunedThrough = logRetentionIdFloor(nowMs);
8
+ let deleted = 0;
9
+ for (let batch = 0; batch < PRUNE_MAX_BATCHES; batch++) {
10
+ const victims = await sql.db
11
+ .select({ id: t.id })
12
+ .from(t)
13
+ .where(lt(t.id, prunedThrough))
14
+ .orderBy(asc(t.id))
15
+ .limit(PRUNE_BATCH_SIZE);
16
+ if (victims.length === 0)
17
+ return { deleted, prunedThrough, capped: false };
18
+ const lastId = victims[victims.length - 1].id;
19
+ await sql.db.delete(t).where(and(lt(t.id, prunedThrough), lte(t.id, lastId)));
20
+ deleted += victims.length;
21
+ if (victims.length < PRUNE_BATCH_SIZE)
22
+ return { deleted, prunedThrough, capped: false };
23
+ }
24
+ return { deleted, prunedThrough, capped: true };
25
+ }
26
+ //# sourceMappingURL=prune-vibe-logs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prune-vibe-logs.js","sourceRoot":"","sources":["../../jsr/intern/prune-vibe-logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAe3D,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAQrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAoCpC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAqB,EAAE,KAAa;IAC3E,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC;IACnC,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACjD,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,iBAAiB,EAAE,KAAK,EAAE,EAAE,CAAC;QAKvD,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,EAAE;aACzB,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;aACpB,IAAI,CAAC,CAAC,CAAC;aACP,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,CAAC;aAC9B,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;aAClB,KAAK,CAAC,gBAAgB,CAAC,CAAC;QAC3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAU3E,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;QAC9E,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;QAE1B,IAAI,OAAO,CAAC,MAAM,GAAG,gBAAgB;YAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;IAC1F,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAClD,CAAC"}
@@ -11,6 +11,6 @@ export interface ServeRootHtmlWithSwrOpts {
11
11
  readonly waitUntil: (p: Promise<unknown>) => void;
12
12
  readonly workspaceNpmUrl?: string;
13
13
  }
14
- export declare function bareRootHtmlSwrKey(origin: string, workspaceNpmUrl: string | undefined): string;
15
- export declare function pinnedRootHtmlSwrKey(origin: string, npmUrl: string): string;
14
+ export declare function bareRootHtmlSwrKey(origin: string, workspaceNpmUrl: string | undefined, fsId?: string): string;
15
+ export declare function pinnedRootHtmlSwrKey(origin: string, npmUrl: string, fsId?: string): string;
16
16
  export declare function serveRootHtmlWithSwr(opts: ServeRootHtmlWithSwrOpts): Promise<Response>;