@protobase/server 0.59.1 → 0.59.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 (45) hide show
  1. package/dist/better-auth/store/migrations-table.js +1 -1
  2. package/dist/channels/binary-frame.js +44 -0
  3. package/dist/channels/channel-protocol.js +16 -3
  4. package/dist/channels/channel-refusals.js +1 -1
  5. package/dist/channels/channel-routes.js +22 -9
  6. package/dist/channels/channel-sender.d.ts +1 -1
  7. package/dist/channels/channel-sender.js +24 -12
  8. package/dist/channels/channel-socket.js +12 -7
  9. package/dist/channels/database-sends.js +57 -0
  10. package/dist/channels/sends-prune.js +15 -0
  11. package/dist/channels/sends-schema-sql.js +30 -0
  12. package/dist/channels/sends-schema.d.ts +7 -0
  13. package/dist/channels/sends-schema.js +18 -0
  14. package/dist/channels/sent.js +17 -1
  15. package/dist/create-admin.d.ts +5 -2
  16. package/dist/create-admin.js +33 -4
  17. package/dist/deps.d.ts +2 -0
  18. package/dist/index.d.ts +6 -2
  19. package/dist/index.js +6 -2
  20. package/dist/internal.d.ts +2 -1
  21. package/dist/internal.js +2 -1
  22. package/dist/meta.d.ts +2 -0
  23. package/dist/meta.js +1 -0
  24. package/dist/notifications/caller.js +2 -2
  25. package/dist/notifications/deliver.js +14 -2
  26. package/dist/notifications/push-job.js +5 -3
  27. package/dist/notifications/schema.js +7 -4
  28. package/dist/package.js +1 -1
  29. package/dist/realtime/database-broadcasts.js +2 -25
  30. package/dist/realtime/followed-poll.js +34 -0
  31. package/dist/realtime/realtime-prune.d.ts +5 -3
  32. package/dist/realtime/realtime-prune.js +8 -3
  33. package/dist/realtime/relay/realtime-options.d.ts +7 -0
  34. package/dist/realtime/relay/realtime-options.js +7 -1
  35. package/dist/status/do-not-disturb.d.ts +9 -0
  36. package/dist/status/do-not-disturb.js +15 -0
  37. package/dist/status/options.d.ts +15 -0
  38. package/dist/status/options.js +25 -0
  39. package/dist/status/routes.js +38 -0
  40. package/dist/status/schema-sql.js +19 -0
  41. package/dist/status/schema.d.ts +12 -0
  42. package/dist/status/schema.js +33 -0
  43. package/dist/status/status-input.js +33 -0
  44. package/dist/status/status-store.js +39 -0
  45. package/package.json +4 -4
@@ -0,0 +1,33 @@
1
+ import { badRequest } from "../problem.js";
2
+ import { availabilities, statusTextProblem } from "@protobase/schema/internal";
3
+ import { z } from "zod";
4
+ //#region src/status/status-input.ts
5
+ const body = z.strictObject({
6
+ availability: z.enum(availabilities),
7
+ text: z.string().nullable(),
8
+ clearsAt: z.iso.datetime({ offset: true }).nullable()
9
+ });
10
+ /**
11
+ * The status a request sets, checked: an availability, a one-line text of at most `maxStatusText` characters, kept
12
+ * trimmed, an empty one as none, and a clear time to come or `null` for never. Anything else, a user named in it
13
+ * too, is a 400 that says what is wrong.
14
+ */
15
+ const statusInput = (given, now = /* @__PURE__ */ new Date()) => {
16
+ const parsed = body.safeParse(given);
17
+ if (!parsed.success) {
18
+ const issue = parsed.error.issues[0];
19
+ throw badRequest("invalid-status", `Send { availability, text, clearsAt }: ${issue.path.join(".") || "the body"} ${issue.message.toLowerCase()}`);
20
+ }
21
+ const { availability, clearsAt } = parsed.data;
22
+ const text = parsed.data.text?.trim() || null;
23
+ const problem = text === null ? void 0 : statusTextProblem(text);
24
+ if (problem) throw badRequest("invalid-status-text", problem);
25
+ if (clearsAt !== null && Date.parse(clearsAt) <= now.getTime()) throw badRequest("invalid-clear-time", "A status clears at a time still to come, or never");
26
+ return {
27
+ availability,
28
+ text,
29
+ clearsAt: clearsAt === null ? null : new Date(clearsAt).toISOString()
30
+ };
31
+ };
32
+ //#endregion
33
+ export { statusInput };
@@ -0,0 +1,39 @@
1
+ import { qualified } from "../notifications/schema-sql.js";
2
+ import { sql } from "kysely";
3
+ //#region src/status/status-store.ts
4
+ const statusOf = (row) => ({
5
+ userId: String(row.user_id),
6
+ availability: row.availability,
7
+ text: row.text,
8
+ clearsAt: row.clears_at?.toISOString() ?? null
9
+ });
10
+ const holds = sql`(clears_at is null or clears_at > now())`;
11
+ /** The person's own status, as it holds now; `undefined` when they have none. */
12
+ const ownStatus = async (db, tables, userId) => {
13
+ const statuses = sql.raw(qualified(tables.statuses));
14
+ const { rows } = await sql`select user_id, availability, text, clears_at from ${statuses} where user_id = ${userId} and ${holds}`.execute(db);
15
+ return rows[0] && statusOf(rows[0]);
16
+ };
17
+ /** The statuses that hold now of everyone who shares an organization with `viewerId`, their own included when they have one. */
18
+ const visibleStatuses = async (db, tables, viewerId) => {
19
+ const statuses = sql.raw(qualified(tables.statuses));
20
+ const members = sql.raw(qualified(tables.members));
21
+ const { rows } = await sql`select s.user_id, s.availability, s.text, s.clears_at from ${statuses} s
22
+ where ${holds} and exists (select from ${members} own join ${members} other on other.organization_id = own.organization_id
23
+ where own.user_id = ${viewerId} and other.user_id = s.user_id)
24
+ order by s.user_id`.execute(db);
25
+ return rows.map(statusOf);
26
+ };
27
+ /** Sets the person's status, replacing the one they had; one that says nothing, automatic without a text, clears it. */
28
+ const setStatus = async (db, tables, userId, input) => {
29
+ if (input.availability === "automatic" && input.text === null) return clearStatus(db, tables, userId);
30
+ const statuses = sql.raw(qualified(tables.statuses));
31
+ await sql`insert into ${statuses} (user_id, availability, text, clears_at, updated_at) values (${userId}, ${input.availability}, ${input.text}, ${input.clearsAt}, now())
32
+ on conflict (user_id) do update set availability = excluded.availability, text = excluded.text, clears_at = excluded.clears_at, updated_at = excluded.updated_at`.execute(db);
33
+ };
34
+ /** Clears the person's status, whether or not they had one. */
35
+ const clearStatus = async (db, tables, userId) => {
36
+ await sql`delete from ${sql.raw(qualified(tables.statuses))} where user_id = ${userId}`.execute(db);
37
+ };
38
+ //#endregion
39
+ export { clearStatus, ownStatus, setStatus, visibleStatuses };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.59.1",
3
+ "version": "0.59.3",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -42,9 +42,9 @@
42
42
  "@better-auth/sso": "^1.7.12",
43
43
  "@livekit/protocol": "1.53.1",
44
44
  "@modelcontextprotocol/server": "^2.3.1",
45
- "@protobase/layout": "0.59.1",
46
- "@protobase/query": "0.59.1",
47
- "@protobase/schema": "0.59.1",
45
+ "@protobase/layout": "0.59.3",
46
+ "@protobase/query": "0.59.3",
47
+ "@protobase/schema": "0.59.3",
48
48
  "@react-email/render": "^2.1.0",
49
49
  "@scalar/hono-api-reference": "^0.12.10",
50
50
  "@sentry/core": "^11.7.0",