matrix-nodejs-homeserver 0.2.0 → 0.3.1

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 (78) hide show
  1. package/README.md +29 -7
  2. package/dist/api/account.js +385 -351
  3. package/dist/api/admin.js +76 -60
  4. package/dist/api/appservice.js +37 -25
  5. package/dist/api/backup.js +73 -62
  6. package/dist/api/federation.js +172 -138
  7. package/dist/api/filters.js +4 -3
  8. package/dist/api/legacy.js +91 -78
  9. package/dist/api/media.js +70 -54
  10. package/dist/api/misc.js +46 -37
  11. package/dist/api/preview.js +4 -3
  12. package/dist/api/profile.js +108 -97
  13. package/dist/api/push.js +114 -99
  14. package/dist/api/relationships.js +64 -58
  15. package/dist/api/rooms.js +703 -580
  16. package/dist/api/rtc.d.ts +0 -1
  17. package/dist/api/rtc.js +48 -34
  18. package/dist/api/search.js +133 -127
  19. package/dist/api/slidingsync.js +41 -31
  20. package/dist/api/spaces.js +82 -77
  21. package/dist/api/sync.js +59 -50
  22. package/dist/api/threadsubs.js +72 -61
  23. package/dist/api/threepid.js +99 -66
  24. package/dist/api/uia.js +17 -16
  25. package/dist/api/user.js +221 -178
  26. package/dist/core/admin.d.ts +0 -1
  27. package/dist/core/admin.js +6 -5
  28. package/dist/core/adminroom.js +9 -8
  29. package/dist/core/appservices.d.ts +2 -1
  30. package/dist/core/appservices.js +5 -4
  31. package/dist/core/audit.d.ts +0 -1
  32. package/dist/core/authrules.js +26 -25
  33. package/dist/core/delayed.js +2 -1
  34. package/dist/core/events.js +11 -10
  35. package/dist/core/invitefilter.js +2 -1
  36. package/dist/core/keys.js +2 -1
  37. package/dist/core/m.d.ts +209 -0
  38. package/dist/core/m.js +182 -0
  39. package/dist/core/partialstate.js +2 -1
  40. package/dist/core/policy.js +4 -3
  41. package/dist/core/push.d.ts +0 -1
  42. package/dist/core/push.js +12 -11
  43. package/dist/core/pushrules.js +36 -35
  44. package/dist/core/rooms.js +76 -74
  45. package/dist/core/stateres.js +7 -6
  46. package/dist/federation/client.js +2 -1
  47. package/dist/federation/index.d.ts +1 -1
  48. package/dist/federation/index.js +30 -29
  49. package/dist/homeserver.d.ts +2 -1
  50. package/dist/homeserver.js +1 -0
  51. package/dist/http/handler.js +2 -23
  52. package/dist/http/input.js +2 -2
  53. package/dist/http/procedure.js +25 -0
  54. package/dist/http/router.d.ts +9 -26
  55. package/dist/http/router.js +10 -30
  56. package/dist/index.d.ts +2 -1
  57. package/dist/index.js +2 -1
  58. package/dist/vendor/zod/LICENSE +21 -0
  59. package/dist/vendor/zod/v4/classic/errors.js +54 -0
  60. package/dist/vendor/zod/v4/classic/parse.js +17 -0
  61. package/dist/vendor/zod/v4/classic/schemas.js +865 -0
  62. package/dist/vendor/zod/v4/core/api.js +512 -0
  63. package/dist/vendor/zod/v4/core/checks.js +300 -0
  64. package/dist/vendor/zod/v4/core/core.js +109 -0
  65. package/dist/vendor/zod/v4/core/doc.js +35 -0
  66. package/dist/vendor/zod/v4/core/errors.js +118 -0
  67. package/dist/vendor/zod/v4/core/json-schema-processors.js +428 -0
  68. package/dist/vendor/zod/v4/core/memoizer.js +255 -0
  69. package/dist/vendor/zod/v4/core/parse.js +206 -0
  70. package/dist/vendor/zod/v4/core/regexes.js +73 -0
  71. package/dist/vendor/zod/v4/core/registries.js +48 -0
  72. package/dist/vendor/zod/v4/core/schemas.js +1378 -0
  73. package/dist/vendor/zod/v4/core/to-json-schema.js +448 -0
  74. package/dist/vendor/zod/v4/core/util.js +537 -0
  75. package/dist/vendor/zod/v4/core/versions.js +8 -0
  76. package/dist/vendor/zod/v4/locales/en.js +110 -0
  77. package/package.json +3 -5
  78. package/dist/core/pushrules.d.ts +0 -1
@@ -1,4 +1,5 @@
1
1
  import { isObject } from "./json.js";
2
+ import { M, UNSTABLE } from "./m.js";
2
3
  import { SUPPORTED_ROOM_VERSIONS, eventIdOf, finalisePdu, redact, roomVersionFeatures, splitStateKey, stateKey, toClientEvent } from "./events.js";
3
4
  import { MatrixError, errors } from "./errors.js";
4
5
  import { generateRoomId, isValidUserId, parseId } from "./ids.js";
@@ -280,7 +281,7 @@ var RoomService = class {
280
281
  return state;
281
282
  }
282
283
  async createEventOf(roomId) {
283
- return getState(await this.currentState(roomId), "m.room.create");
284
+ return getState(await this.currentState(roomId), M.ROOM.CREATE);
284
285
  }
285
286
  /**
286
287
  * State before an event with the given prev_events: the snapshot of a single
@@ -384,7 +385,7 @@ var RoomService = class {
384
385
  pdu.auth_events = pdu.auth_events.map((id) => [id, {}]);
385
386
  }
386
387
  if (!skipAuth) {
387
- if (features.v12) before.set(stateKey("m.room.create", ""), await this.createEventOf(roomId));
388
+ if (features.v12) before.set(stateKey(M.ROOM.CREATE, ""), await this.createEventOf(roomId));
388
389
  checkAuth(pdu, before, version);
389
390
  }
390
391
  if (Buffer.byteLength(JSON.stringify(pdu)) > MAX_EVENT_SIZE) throw errors.tooLarge("Event too large");
@@ -401,7 +402,7 @@ var RoomService = class {
401
402
  eventId,
402
403
  status: "persisted"
403
404
  };
404
- const createEvent = features.v12 ? pdu.type === "m.room.create" ? void 0 : opts.createEvent ?? await this.createEventOf(roomId) ?? await this.findCreateEvent(roomId) : void 0;
405
+ const createEvent = features.v12 ? pdu.type === M.ROOM.CREATE ? void 0 : opts.createEvent ?? await this.createEventOf(roomId) ?? await this.findCreateEvent(roomId) : void 0;
405
406
  const prevIds = (pdu.prev_events ?? []).map(eventIdOf);
406
407
  if (!opts.local) {
407
408
  const reject = async (reason) => {
@@ -436,7 +437,7 @@ var RoomService = class {
436
437
  };
437
438
  else before = await this.stateBefore(roomId, version, prevIds, createEvent);
438
439
  const beforeMap = await this.stateIdsToMap(before.ids);
439
- if (createEvent) beforeMap.set(stateKey("m.room.create", ""), createEvent);
440
+ if (createEvent) beforeMap.set(stateKey(M.ROOM.CREATE, ""), createEvent);
440
441
  const partial = !opts.local && !opts.backfill && await this.hs.partialState.isPartial(roomId);
441
442
  if (partial) {
442
443
  const authPdus = await this.getPdus((pdu.auth_events ?? []).map(eventIdOf));
@@ -469,7 +470,7 @@ var RoomService = class {
469
470
  }
470
471
  if (!opts.backfill && !opts.stateBefore && !partial) {
471
472
  const current = new Map(await this.currentState(roomId));
472
- if (createEvent) current.set(stateKey("m.room.create", ""), createEvent);
473
+ if (createEvent) current.set(stateKey(M.ROOM.CREATE, ""), createEvent);
473
474
  const softFail = async () => {
474
475
  const ids = pdu.state_key !== void 0 ? {
475
476
  ...before.ids,
@@ -539,7 +540,7 @@ var RoomService = class {
539
540
  }], { state_snapshot: snapshot });
540
541
  this.eventCache.delete(eventId);
541
542
  };
542
- const joinKey = stateKey("m.room.member", join.pdu.state_key);
543
+ const joinKey = stateKey(M.ROOM.MEMBER, join.pdu.state_key);
543
544
  await setSnapshot(joinEventId, await writeSnapshot({
544
545
  ...fullBefore,
545
546
  [joinKey]: joinEventId
@@ -586,7 +587,7 @@ var RoomService = class {
586
587
  continue;
587
588
  }
588
589
  const beforeMap = await this.stateIdsToMap(before.ids);
589
- if (createEvent) beforeMap.set(stateKey("m.room.create", ""), createEvent);
590
+ if (createEvent) beforeMap.set(stateKey(M.ROOM.CREATE, ""), createEvent);
590
591
  let allowed = true;
591
592
  let reason = "";
592
593
  if (!this.hs.isLocalUser(pdu.sender)) try {
@@ -627,7 +628,7 @@ var RoomService = class {
627
628
  touched.push(pdu.event_id);
628
629
  continue;
629
630
  }
630
- if (pdu.type === "m.room.member" && pdu.content?.membership === "join") joinedServers.add(pdu.state_key.slice(pdu.state_key.indexOf(":") + 1));
631
+ if (pdu.type === M.ROOM.MEMBER && pdu.content?.membership === "join") joinedServers.add(pdu.state_key.slice(pdu.state_key.indexOf(":") + 1));
631
632
  const isState = pdu.state_key !== void 0;
632
633
  const snapshot = !isState && before.snapshot !== null && before.snapshot !== 0 ? before.snapshot : await writeSnapshot(isState ? {
633
634
  ...before.ids,
@@ -698,7 +699,7 @@ var RoomService = class {
698
699
  ];
699
700
  if (!newIds[k]) {
700
701
  await db.delete("current_state", where);
701
- if (type === "m.room.member") await db.delete("memberships", [{
702
+ if (type === M.ROOM.MEMBER) await db.delete("memberships", [{
702
703
  field: "room_id",
703
704
  value: roomId
704
705
  }, {
@@ -713,7 +714,7 @@ var RoomService = class {
713
714
  state_key: sk,
714
715
  event_id: newIds[k]
715
716
  });
716
- if (type === "m.room.member") await db.upsert("memberships", {
717
+ if (type === M.ROOM.MEMBER) await db.upsert("memberships", {
717
718
  room_id: roomId,
718
719
  user_id: sk,
719
720
  membership: pdus.get(newIds[k])?.content?.membership ?? "leave",
@@ -732,7 +733,7 @@ var RoomService = class {
732
733
  });
733
734
  for (const k of Object.keys(oldIds)) {
734
735
  const [type, userId] = splitStateKey(k);
735
- if (type !== "m.room.member" || this.hs.isLocalUser(userId) || oldIds[k] === newIds[k]) continue;
736
+ if (type !== M.ROOM.MEMBER || this.hs.isLocalUser(userId) || oldIds[k] === newIds[k]) continue;
736
737
  if (!await this.hs.keys.isTracked(userId)) await this.hs.keys.dropRemoteCache(userId);
737
738
  }
738
739
  for (const s of this.hs.federation.serversInRoom(await this.currentState(roomId), false)) joinedServers.add(s);
@@ -784,7 +785,7 @@ var RoomService = class {
784
785
  unsigned.prev_sender = prevState.sender;
785
786
  unsigned.replaces_state = prevState.event_id;
786
787
  }
787
- if (pdu.type === "m.room.member" && ["invite", "knock"].includes(pdu.content.membership) && opts.local) unsigned[pdu.content.membership === "invite" ? "invite_room_state" : "knock_room_state"] = this.strippedState(beforeMap);
788
+ if (pdu.type === M.ROOM.MEMBER && ["invite", "knock"].includes(pdu.content.membership) && opts.local) unsigned[pdu.content.membership === "invite" ? "invite_room_state" : "knock_room_state"] = this.strippedState(beforeMap);
788
789
  const stored = Object.keys(unsigned).length ? {
789
790
  ...pdu,
790
791
  unsigned
@@ -794,9 +795,9 @@ var RoomService = class {
794
795
  room_id: roomId
795
796
  };
796
797
  const txnToken = opts.txnId && opts.deviceId ? txnTokenOf(sender, opts.deviceId) : null;
797
- const relation = pdu.content?.["m.relates_to"];
798
+ const relation = pdu.content?.[M.RELATES_TO];
798
799
  const redactsId = features.v11 ? pdu.content?.redacts : pdu.redacts;
799
- const redaction = pdu.type === "m.room.redaction" && typeof redactsId === "string" ? await this.prepareRedaction(redactsId, view, version) : null;
800
+ const redaction = pdu.type === M.ROOM.REDACTION && typeof redactsId === "string" ? await this.prepareRedaction(redactsId, view, version) : null;
800
801
  let newExtremities = null;
801
802
  let stateChanges = [];
802
803
  let newCurrentIds = null;
@@ -812,7 +813,7 @@ var RoomService = class {
812
813
  const snap = await this.snapshotOf(ext);
813
814
  if (snap !== null) sets.push(await this.snapshotIds(snap));
814
815
  }
815
- const createEvent = features.v12 ? beforeMap.get(stateKey("m.room.create", "")) ?? (pdu.type === "m.room.create" ? pdu : void 0) : void 0;
816
+ const createEvent = features.v12 ? beforeMap.get(stateKey(M.ROOM.CREATE, "")) ?? (pdu.type === M.ROOM.CREATE ? pdu : void 0) : void 0;
816
817
  newCurrentIds = await resolveState(sets, version, async (ids) => {
817
818
  const found = await this.getPdus(ids);
818
819
  if (ids.includes(eventId)) found.set(eventId, view);
@@ -847,7 +848,7 @@ var RoomService = class {
847
848
  field: "event_id",
848
849
  value: eventId
849
850
  }]);
850
- const edge = pdu.content?.["m.relationship"];
851
+ const edge = pdu.content?.[M.RELATIONSHIP];
851
852
  if (isObject(edge) && typeof edge.event_id === "string" && typeof edge.rel_type === "string") await db.upsert("event_edges", {
852
853
  event_id: eventId,
853
854
  room_id: roomId,
@@ -896,7 +897,7 @@ var RoomService = class {
896
897
  ];
897
898
  if (change.eventId === null) {
898
899
  await db.delete("current_state", where);
899
- if (type === "m.room.member") await db.delete("memberships", [{
900
+ if (type === M.ROOM.MEMBER) await db.delete("memberships", [{
900
901
  field: "room_id",
901
902
  value: roomId
902
903
  }, {
@@ -911,7 +912,7 @@ var RoomService = class {
911
912
  state_key: sk,
912
913
  event_id: change.eventId
913
914
  });
914
- if (type === "m.room.member") {
915
+ if (type === M.ROOM.MEMBER) {
915
916
  const member = changedPdus.get(change.eventId);
916
917
  await db.upsert("memberships", {
917
918
  room_id: roomId,
@@ -1106,15 +1107,15 @@ var RoomService = class {
1106
1107
  */
1107
1108
  strippedState(state) {
1108
1109
  const types = [
1109
- "m.room.create",
1110
- "m.room.join_rules",
1111
- "m.room.name",
1112
- "m.room.avatar",
1113
- "m.room.canonical_alias",
1114
- "m.room.encryption",
1115
- "m.room.topic"
1110
+ M.ROOM.CREATE,
1111
+ M.ROOM.JOIN_RULES,
1112
+ M.ROOM.NAME,
1113
+ M.ROOM.AVATAR,
1114
+ M.ROOM.CANONICAL_ALIAS,
1115
+ M.ROOM.ENCRYPTION,
1116
+ M.ROOM.TOPIC
1116
1117
  ];
1117
- const create = getState(state, "m.room.create");
1118
+ const create = getState(state, M.ROOM.CREATE);
1118
1119
  const version = typeof create?.content?.room_version === "string" ? create.content.room_version : "1";
1119
1120
  const f = roomVersionFeatures(version);
1120
1121
  const out = [];
@@ -1124,7 +1125,7 @@ var RoomService = class {
1124
1125
  const { unsigned, ...full } = ev;
1125
1126
  const wire = { ...full };
1126
1127
  if (!f.legacyEventIds) delete wire.event_id;
1127
- if (f.v12 && t === "m.room.create") delete wire.room_id;
1128
+ if (f.v12 && t === M.ROOM.CREATE) delete wire.room_id;
1128
1129
  out.push(wire);
1129
1130
  }
1130
1131
  return out;
@@ -1143,7 +1144,7 @@ var RoomService = class {
1143
1144
  },
1144
1145
  {
1145
1146
  field: "type",
1146
- value: "m.room.member"
1147
+ value: M.ROOM.MEMBER
1147
1148
  },
1148
1149
  {
1149
1150
  field: "state_key",
@@ -1160,18 +1161,18 @@ var RoomService = class {
1160
1161
  const ids = await this.snapshotIds(raw.snapshot);
1161
1162
  let membership = "leave";
1162
1163
  if (userId) {
1163
- const memId = ids[stateKey("m.room.member", userId)];
1164
+ const memId = ids[stateKey(M.ROOM.MEMBER, userId)];
1164
1165
  membership = memId ? (await this.getEvent(memId))?.pdu.content?.membership ?? "leave" : "leave";
1165
1166
  }
1166
1167
  const ev = userId ? {
1167
1168
  ...raw,
1168
1169
  viewerMembership: membership
1169
1170
  } : raw;
1170
- if (userId && ev.pdu.type === "m.room.member" && ev.pdu.state_key === userId) {
1171
+ if (userId && ev.pdu.type === M.ROOM.MEMBER && ev.pdu.state_key === userId) {
1171
1172
  out.push(ev);
1172
1173
  continue;
1173
1174
  }
1174
- const hvId = ids[stateKey("m.room.history_visibility", "")];
1175
+ const hvId = ids[stateKey(M.ROOM.HISTORY_VISIBILITY, "")];
1175
1176
  const hv = hvId ? (await this.getEvent(hvId))?.pdu.content?.history_visibility ?? "shared" : "shared";
1176
1177
  if (hv === "world_readable") {
1177
1178
  out.push(ev);
@@ -1200,7 +1201,7 @@ var RoomService = class {
1200
1201
  async canPeek(roomId, userId) {
1201
1202
  const state = await this.currentState(roomId);
1202
1203
  const membership = membershipOf(state, userId);
1203
- const hv = getState(state, "m.room.history_visibility")?.content?.history_visibility ?? "shared";
1204
+ const hv = getState(state, M.ROOM.HISTORY_VISIBILITY)?.content?.history_visibility ?? "shared";
1204
1205
  return {
1205
1206
  joined: membership === "join",
1206
1207
  worldReadable: hv === "world_readable",
@@ -1210,7 +1211,7 @@ var RoomService = class {
1210
1211
  /** The state snapshot visible to a user who is no longer joined (state at their leave). */
1211
1212
  async membershipEvent(roomId, userId) {
1212
1213
  const state = await this.currentState(roomId);
1213
- const ev = getState(state, "m.room.member", userId);
1214
+ const ev = getState(state, M.ROOM.MEMBER, userId);
1214
1215
  return ev?.event_id ? this.getEvent(ev.event_id) : null;
1215
1216
  }
1216
1217
  formatEvent(ev, viewer, opts = {}) {
@@ -1278,7 +1279,7 @@ var RoomService = class {
1278
1279
  if (features.v12) {
1279
1280
  prebuiltCreate = finalisePdu({
1280
1281
  sender,
1281
- type: "m.room.create",
1282
+ type: M.ROOM.CREATE,
1282
1283
  state_key: "",
1283
1284
  content: createContent,
1284
1285
  origin_server_ts: Date.now(),
@@ -1301,30 +1302,31 @@ var RoomService = class {
1301
1302
  const pdu = prebuiltCreate;
1302
1303
  await this.withLock(roomId, () => this.persistEvent(roomId, version, pdu, { local: true }));
1303
1304
  } else await send({
1304
- type: "m.room.create",
1305
+ type: M.ROOM.CREATE,
1305
1306
  state_key: "",
1306
1307
  content: createContent
1307
1308
  });
1309
+ const profile = await this.hs.profile(sender);
1308
1310
  await send({
1309
- type: "m.room.member",
1311
+ type: M.ROOM.MEMBER,
1310
1312
  state_key: sender,
1311
1313
  content: {
1312
1314
  membership: "join",
1313
- ...await this.hs.profile(sender)
1315
+ ...profile
1314
1316
  }
1315
1317
  });
1316
1318
  const pl = {
1317
1319
  users: features.v12 ? {} : { [sender]: 100 },
1318
1320
  users_default: 0,
1319
1321
  events: {
1320
- "m.room.name": 50,
1321
- "m.room.power_levels": 100,
1322
- "m.room.history_visibility": 100,
1323
- "m.room.canonical_alias": 50,
1324
- "m.room.avatar": 50,
1325
- "m.room.tombstone": features.v12 ? 150 : 100,
1326
- "m.room.server_acl": 100,
1327
- "m.room.encryption": 100
1322
+ [M.ROOM.NAME]: 50,
1323
+ [M.ROOM.POWER_LEVELS]: 100,
1324
+ [M.ROOM.HISTORY_VISIBILITY]: 100,
1325
+ [M.ROOM.CANONICAL_ALIAS]: 50,
1326
+ [M.ROOM.AVATAR]: 50,
1327
+ [M.ROOM.TOMBSTONE]: features.v12 ? 150 : 100,
1328
+ [M.ROOM.SERVER_ACL]: 100,
1329
+ [M.ROOM.ENCRYPTION]: 100
1328
1330
  },
1329
1331
  events_default: 0,
1330
1332
  state_default: 50,
@@ -1338,7 +1340,7 @@ var RoomService = class {
1338
1340
  const override = body.power_level_content_override;
1339
1341
  if (override !== void 0 && !isObject(override)) throw errors.badJson("power_level_content_override must be an object");
1340
1342
  const initialState = body.initial_state ?? [];
1341
- const initialPl = initialState.find((e) => e?.type === "m.room.power_levels" && (e.state_key ?? "") === "");
1343
+ const initialPl = initialState.find((e) => e?.type === M.ROOM.POWER_LEVELS && (e.state_key ?? "") === "");
1342
1344
  const predecessor = createContent.predecessor?.room_id;
1343
1345
  if (typeof predecessor === "string") await copyRoomPushRules(this.hs, sender, predecessor, roomId);
1344
1346
  const plContent = {
@@ -1348,7 +1350,7 @@ var RoomService = class {
1348
1350
  };
1349
1351
  validatePowerLevelContent(plContent, creators);
1350
1352
  await send({
1351
- type: "m.room.power_levels",
1353
+ type: M.ROOM.POWER_LEVELS,
1352
1354
  state_key: "",
1353
1355
  content: plContent
1354
1356
  });
@@ -1359,13 +1361,13 @@ var RoomService = class {
1359
1361
  creator: sender
1360
1362
  });
1361
1363
  await send({
1362
- type: "m.room.canonical_alias",
1364
+ type: M.ROOM.CANONICAL_ALIAS,
1363
1365
  state_key: "",
1364
1366
  content: { alias }
1365
1367
  });
1366
1368
  }
1367
- const presetState = [["m.room.join_rules", { join_rule: preset === "public_chat" ? "public" : "invite" }], ["m.room.history_visibility", { history_visibility: "shared" }]];
1368
- if (preset !== "public_chat") presetState.push(["m.room.guest_access", { guest_access: "can_join" }]);
1369
+ const presetState = [[M.ROOM.JOIN_RULES, { join_rule: preset === "public_chat" ? "public" : "invite" }], [M.ROOM.HISTORY_VISIBILITY, { history_visibility: "shared" }]];
1370
+ if (preset !== "public_chat") presetState.push([M.ROOM.GUEST_ACCESS, { guest_access: "can_join" }]);
1369
1371
  const initialKeys = new Set(initialState.map((e) => stateKey(e?.type, e?.state_key ?? "")));
1370
1372
  for (const [type, content] of presetState) if (!initialKeys.has(stateKey(type, ""))) await send({
1371
1373
  type,
@@ -1374,7 +1376,7 @@ var RoomService = class {
1374
1376
  });
1375
1377
  for (const ev of initialState) {
1376
1378
  if (!isObject(ev) || typeof ev.type !== "string" || !isObject(ev.content)) throw errors.badJson("Invalid initial_state event");
1377
- if (ev.type === "m.room.power_levels" || ev.type === "m.room.create" || ev.type === "m.room.member") continue;
1379
+ if (ev.type === M.ROOM.POWER_LEVELS || ev.type === M.ROOM.CREATE || ev.type === M.ROOM.MEMBER) continue;
1378
1380
  await send({
1379
1381
  type: ev.type,
1380
1382
  state_key: ev.state_key ?? "",
@@ -1382,16 +1384,16 @@ var RoomService = class {
1382
1384
  });
1383
1385
  }
1384
1386
  if (body.name !== void 0) await send({
1385
- type: "m.room.name",
1387
+ type: M.ROOM.NAME,
1386
1388
  state_key: "",
1387
1389
  content: { name: body.name }
1388
1390
  });
1389
1391
  if (body.topic !== void 0) await send({
1390
- type: "m.room.topic",
1392
+ type: M.ROOM.TOPIC,
1391
1393
  state_key: "",
1392
1394
  content: {
1393
1395
  topic: body.topic,
1394
- "m.topic": { "m.text": [{
1396
+ [M.TOPIC]: { [M.TEXT]: [{
1395
1397
  mimetype: "text/plain",
1396
1398
  body: body.topic
1397
1399
  }] }
@@ -1451,7 +1453,7 @@ var RoomService = class {
1451
1453
  if (!await this.exists(roomId)) return false;
1452
1454
  for (const [key, ev] of await this.currentState(roomId)) {
1453
1455
  const [type, userId] = splitStateKey(key);
1454
- if (type === "m.room.member" && ev.content?.membership === "join" && this.hs.isLocalUser(userId)) return true;
1456
+ if (type === M.ROOM.MEMBER && ev.content?.membership === "join" && this.hs.isLocalUser(userId)) return true;
1455
1457
  }
1456
1458
  return false;
1457
1459
  }
@@ -1536,9 +1538,9 @@ var RoomService = class {
1536
1538
  ...await this.hs.profile(userId)
1537
1539
  };
1538
1540
  if (extra.reason) content.reason = extra.reason;
1539
- const existing = getState(state, "m.room.member", userId);
1541
+ const existing = getState(state, M.ROOM.MEMBER, userId);
1540
1542
  if (existing?.content?.membership === "join" && JSON.stringify(existing.content) === JSON.stringify(content)) return roomId;
1541
- const joinRule = getState(state, "m.room.join_rules")?.content?.join_rule;
1543
+ const joinRule = getState(state, M.ROOM.JOIN_RULES)?.content?.join_rule;
1542
1544
  const current = membershipOf(state, userId);
1543
1545
  if ((joinRule === "restricted" || joinRule === "knock_restricted") && current !== "join" && current !== "invite") {
1544
1546
  const via = await this.findRestrictedAuthoriser(userId, state, version);
@@ -1548,7 +1550,7 @@ var RoomService = class {
1548
1550
  const servers = /* @__PURE__ */ new Set();
1549
1551
  for (const [k, ev] of state) {
1550
1552
  const [type, member] = splitStateKey(k);
1551
- if (type === "m.room.member" && ev.content?.membership === "join" && !this.hs.isLocalUser(member) && userLevel(pl, member) >= pl.invite) servers.add(member.slice(member.indexOf(":") + 1));
1553
+ if (type === M.ROOM.MEMBER && ev.content?.membership === "join" && !this.hs.isLocalUser(member) && userLevel(pl, member) >= pl.invite) servers.add(member.slice(member.indexOf(":") + 1));
1552
1554
  }
1553
1555
  if (servers.size) {
1554
1556
  await this.hs.federation.joinRemoteRoom(userId, roomId, [...servers], content);
@@ -1557,30 +1559,30 @@ var RoomService = class {
1557
1559
  }
1558
1560
  }
1559
1561
  await this.sendEvent(roomId, userId, {
1560
- type: "m.room.member",
1562
+ type: M.ROOM.MEMBER,
1561
1563
  state_key: userId,
1562
1564
  content
1563
1565
  });
1564
- const predecessor = getState(state, "m.room.create")?.content?.predecessor?.room_id;
1566
+ const predecessor = getState(state, M.ROOM.CREATE)?.content?.predecessor?.room_id;
1565
1567
  if (typeof predecessor === "string") await copyRoomPushRules(this.hs, userId, predecessor, roomId);
1566
1568
  return roomId;
1567
1569
  }
1568
1570
  /** Whether an allowed room exists that we can't check (or the user is joined to), so another server might authorise. */
1569
1571
  async mayQualifyRemotely(userId, state) {
1570
- const allow = getState(state, "m.room.join_rules")?.content?.allow;
1572
+ const allow = getState(state, M.ROOM.JOIN_RULES)?.content?.allow;
1571
1573
  if (!Array.isArray(allow)) return false;
1572
1574
  for (const rule of allow) {
1573
- if (rule?.type !== "m.room_membership" || typeof rule.room_id !== "string") continue;
1575
+ if (rule?.type !== M.ROOM_MEMBERSHIP || typeof rule.room_id !== "string") continue;
1574
1576
  if (!await this.serverIsJoined(rule.room_id)) return true;
1575
1577
  if (await this.membership(rule.room_id, userId) === "join") return true;
1576
1578
  }
1577
1579
  return false;
1578
1580
  }
1579
1581
  async findRestrictedAuthoriser(userId, state, version) {
1580
- const allow = getState(state, "m.room.join_rules")?.content?.allow;
1582
+ const allow = getState(state, M.ROOM.JOIN_RULES)?.content?.allow;
1581
1583
  if (!Array.isArray(allow)) return null;
1582
1584
  let permitted = false;
1583
- for (const rule of allow) if (rule?.type === "m.room_membership" && typeof rule.room_id === "string" && await this.exists(rule.room_id)) {
1585
+ for (const rule of allow) if (rule?.type === M.ROOM_MEMBERSHIP && typeof rule.room_id === "string" && await this.exists(rule.room_id)) {
1584
1586
  if (await this.membership(rule.room_id, userId) === "join") {
1585
1587
  permitted = true;
1586
1588
  break;
@@ -1590,7 +1592,7 @@ var RoomService = class {
1590
1592
  const pl = powerLevels(state, version);
1591
1593
  for (const [k, ev] of state) {
1592
1594
  const [type, key] = splitStateKey(k);
1593
- if (type === "m.room.member" && ev.content?.membership === "join" && this.hs.isLocalUser(key) && userLevel(pl, key) >= pl.invite) return key;
1595
+ if (type === M.ROOM.MEMBER && ev.content?.membership === "join" && this.hs.isLocalUser(key) && userLevel(pl, key) >= pl.invite) return key;
1594
1596
  }
1595
1597
  return null;
1596
1598
  }
@@ -1601,7 +1603,7 @@ var RoomService = class {
1601
1603
  field: "user_id",
1602
1604
  value: target
1603
1605
  }]) && !await this.hs.appservices.queryUser(target)) throw errors.notFound("Unknown user");
1604
- if (local && await inviteDecision(this.hs, target, sender) === "block") throw new MatrixError(403, "M_FORBIDDEN", "This user does not accept invites from you", { "org.matrix.msc4155.errcode": "M_INVITE_BLOCKED" });
1606
+ if (local && await inviteDecision(this.hs, target, sender) === "block") throw new MatrixError(403, "M_FORBIDDEN", "This user does not accept invites from you", { [UNSTABLE.ORG.MATRIX.MSC4155.ERRCODE]: "M_INVITE_BLOCKED" });
1605
1607
  await this.requireJoined(roomId, sender);
1606
1608
  const state = await this.currentState(roomId);
1607
1609
  if (membershipOf(state, target) === "invite") return;
@@ -1612,7 +1614,7 @@ var RoomService = class {
1612
1614
  if (opts.thirdPartyInvite) content.third_party_invite = opts.thirdPartyInvite;
1613
1615
  if (local) {
1614
1616
  await this.sendEvent(roomId, sender, {
1615
- type: "m.room.member",
1617
+ type: M.ROOM.MEMBER,
1616
1618
  state_key: target,
1617
1619
  content
1618
1620
  });
@@ -1622,12 +1624,12 @@ var RoomService = class {
1622
1624
  await this.withLock(roomId, async () => {
1623
1625
  const version = await this.roomVersion(roomId);
1624
1626
  const pdu = await this.buildLocalEvent(roomId, version, sender, {
1625
- type: "m.room.member",
1627
+ type: M.ROOM.MEMBER,
1626
1628
  state_key: target,
1627
1629
  content
1628
1630
  });
1629
1631
  const inviteState = [...this.strippedState(await this.currentState(roomId))];
1630
- const senderMember = getState(await this.currentState(roomId), "m.room.member", sender);
1632
+ const senderMember = getState(await this.currentState(roomId), M.ROOM.MEMBER, sender);
1631
1633
  if (senderMember) {
1632
1634
  const { unsigned, ...full } = senderMember;
1633
1635
  inviteState.push(this.hs.federation.toFederationPdu(full, version));
@@ -1646,11 +1648,11 @@ var RoomService = class {
1646
1648
  const content = { membership };
1647
1649
  if (reason) content.reason = reason;
1648
1650
  if (membership === "ban" || membership === "leave" && sender !== target) {
1649
- const prev = getState(await this.currentState(roomId), "m.room.member", target);
1651
+ const prev = getState(await this.currentState(roomId), M.ROOM.MEMBER, target);
1650
1652
  if (prev?.content?.displayname) content.displayname = prev.content.displayname;
1651
1653
  }
1652
1654
  await this.sendEvent(roomId, sender, {
1653
- type: "m.room.member",
1655
+ type: M.ROOM.MEMBER,
1654
1656
  state_key: target,
1655
1657
  content
1656
1658
  });
@@ -1689,7 +1691,7 @@ var RoomService = class {
1689
1691
  leave = finalisePdu({
1690
1692
  room_id: roomId,
1691
1693
  sender: userId,
1692
- type: "m.room.member",
1694
+ type: M.ROOM.MEMBER,
1693
1695
  state_key: userId,
1694
1696
  content,
1695
1697
  origin_server_ts: Date.now(),
@@ -1704,7 +1706,7 @@ var RoomService = class {
1704
1706
  async propagateProfile(userId) {
1705
1707
  const profile = await this.hs.profile(userId);
1706
1708
  for (const roomId of await this.roomsForUser(userId)) {
1707
- const prev = getState(await this.currentState(roomId), "m.room.member", userId);
1709
+ const prev = getState(await this.currentState(roomId), M.ROOM.MEMBER, userId);
1708
1710
  if (!prev) continue;
1709
1711
  const content = {
1710
1712
  ...prev.content,
@@ -1715,7 +1717,7 @@ var RoomService = class {
1715
1717
  if (profile.avatar_url === void 0) delete content.avatar_url;
1716
1718
  try {
1717
1719
  await this.sendEvent(roomId, userId, {
1718
- type: "m.room.member",
1720
+ type: M.ROOM.MEMBER,
1719
1721
  state_key: userId,
1720
1722
  content
1721
1723
  });
@@ -1,7 +1,8 @@
1
+ import { M } from "./m.js";
1
2
  import { eventIdOf, roomVersionFeatures, stateKey } from "./events.js";
2
3
  import { authEventKeys, checkAuth, powerLevels, userLevel } from "./authrules.js";
3
4
  //#region src/core/stateres.ts
4
- const isPowerEvent = (ev) => ev.type === "m.room.power_levels" && ev.state_key === "" || ev.type === "m.room.join_rules" && ev.state_key === "" || ev.type === "m.room.create" && ev.state_key === "" || ev.type === "m.room.member" && ["leave", "ban"].includes(ev.content?.membership) && ev.sender !== ev.state_key;
5
+ const isPowerEvent = (ev) => ev.type === M.ROOM.POWER_LEVELS && ev.state_key === "" || ev.type === M.ROOM.JOIN_RULES && ev.state_key === "" || ev.type === M.ROOM.CREATE && ev.state_key === "" || ev.type === M.ROOM.MEMBER && ["leave", "ban"].includes(ev.content?.membership) && ev.sender !== ev.state_key;
5
6
  const authIds = (ev) => (ev.auth_events ?? []).map(eventIdOf);
6
7
  var EventCache = class {
7
8
  events = /* @__PURE__ */ new Map();
@@ -66,7 +67,7 @@ async function resolveState(stateSets, roomVersion, source, createEvent) {
66
67
  for (const id of await cache.authChain(powerEvents)) if (full.has(id)) control.add(id);
67
68
  let resolved = await iterativeAuthChecks(cache, await reverseTopologicalPowerSort(cache, control, roomVersion, createEvent), v21 ? {} : { ...unconflicted }, roomVersion, createEvent);
68
69
  const remaining = [...full].filter((id) => !control.has(id));
69
- const mainline = await mainlineOf(cache, resolved[stateKey("m.room.power_levels", "")]);
70
+ const mainline = await mainlineOf(cache, resolved[stateKey(M.ROOM.POWER_LEVELS, "")]);
70
71
  const positions = /* @__PURE__ */ new Map();
71
72
  for (const id of remaining) positions.set(id, await mainlinePosition(cache, id, mainline));
72
73
  remaining.sort((a, b) => {
@@ -107,7 +108,7 @@ async function senderPowerLevel(cache, ev, roomVersion, createEvent) {
107
108
  const a = cache.get(id);
108
109
  if (a && a.state_key !== void 0) state.set(stateKey(a.type, a.state_key), a);
109
110
  }
110
- if (createEvent) state.set(stateKey("m.room.create", ""), createEvent);
111
+ if (createEvent) state.set(stateKey(M.ROOM.CREATE, ""), createEvent);
111
112
  const level = userLevel(powerLevels(state, roomVersion), ev.sender);
112
113
  return Number.isFinite(level) ? level : Number.MAX_SAFE_INTEGER;
113
114
  }
@@ -160,7 +161,7 @@ async function iterativeAuthChecks(cache, ids, base, roomVersion, createEvent) {
160
161
  const sev = sid ? cache.get(sid) : void 0;
161
162
  if (sev) authState.set(k, sev);
162
163
  }
163
- if (createEvent) authState.set(stateKey("m.room.create", ""), createEvent);
164
+ if (createEvent) authState.set(stateKey(M.ROOM.CREATE, ""), createEvent);
164
165
  try {
165
166
  checkAuth(ev, authState, roomVersion);
166
167
  state[stateKey(ev.type, ev.state_key)] = id;
@@ -179,7 +180,7 @@ async function mainlineOf(cache, plId) {
179
180
  await cache.load(authIds(ev));
180
181
  current = authIds(ev).find((a) => {
181
182
  const e = cache.get(a);
182
- return e?.type === "m.room.power_levels" && e.state_key === "";
183
+ return e?.type === M.ROOM.POWER_LEVELS && e.state_key === "";
183
184
  });
184
185
  }
185
186
  const positions = /* @__PURE__ */ new Map();
@@ -199,7 +200,7 @@ async function mainlinePosition(cache, id, mainline) {
199
200
  await cache.load(authIds(ev));
200
201
  current = authIds(ev).find((a) => {
201
202
  const e = cache.get(a);
202
- return e?.type === "m.room.power_levels" && e.state_key === "";
203
+ return e?.type === M.ROOM.POWER_LEVELS && e.state_key === "";
203
204
  });
204
205
  }
205
206
  return 0;
@@ -1,5 +1,6 @@
1
1
  import { canonicalJson } from "../core/json.js";
2
2
  import { unpaddedBase64 } from "../core/crypto.js";
3
+ import { M } from "../core/m.js";
3
4
  import { MatrixError } from "../core/errors.js";
4
5
  import { sign } from "node:crypto";
5
6
  import { resolveSrv } from "node:dns/promises";
@@ -149,7 +150,7 @@ var FederationClient = class {
149
150
  }, "GET", "/.well-known/matrix/server", void 0, {}, 5e3);
150
151
  if (res.status !== 200) return null;
151
152
  const body = JSON.parse(res.body.toString("utf8"));
152
- return typeof body["m.server"] === "string" && body["m.server"] ? body["m.server"] : null;
153
+ return typeof body[M.SERVER] === "string" && body[M.SERVER] ? body[M.SERVER] : null;
153
154
  } catch {
154
155
  return null;
155
156
  }
@@ -7,7 +7,7 @@ import { TransactionSender } from "./sender.js";
7
7
  import { Homeserver } from "../homeserver.js";
8
8
  //#region src/federation/index.d.ts
9
9
  export interface FederationOptions {
10
- /** Enable federation. Default: true. */
10
+ /** Enable federation (talking to other homeservers). Default: false, so that a server only joins the network on purpose. */
11
11
  enabled?: boolean;
12
12
  /** Join remote rooms with partial state first (MSC3902 "faster joins"). Default true. */
13
13
  fasterJoins?: boolean;