From cd8d1f410f803106f3894adcdbfa600f89151af1 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Wed, 6 Jul 2022 06:08:53 +0100 Subject: [PATCH] Add typed options for createRoom (#238) * Add CreateRoomOptions and associated enums * Update usages of createRoom * Cleanup PR * Add the new file * Apply suggestions from code review * Manual adjustments --- src/MatrixClient.ts | 16 ++-- src/index.ts | 1 + src/models/CreateRoom.ts | 144 +++++++++++++++++++++++++++++++ src/models/events/CreateEvent.ts | 7 +- test/MatrixClientTest.ts | 5 +- 5 files changed, 162 insertions(+), 11 deletions(-) create mode 100644 src/models/CreateRoom.ts diff --git a/src/MatrixClient.ts b/src/MatrixClient.ts index f30b9ab5..b078c44c 100644 --- a/src/MatrixClient.ts +++ b/src/MatrixClient.ts @@ -45,6 +45,7 @@ import { IWhoAmI } from "./models/Account"; import { RustSdkCryptoStorageProvider } from "./storage/RustSdkCryptoStorageProvider"; import { DMs } from "./DMs"; import { ServerVersions } from "./models/ServerVersions"; +import { RoomCreateOptions } from "./models/CreateRoom"; const SYNC_BACKOFF_MIN_MS = 5000; const SYNC_BACKOFF_MAX_MS = 15000; @@ -1339,15 +1340,14 @@ export class MatrixClient extends EventEmitter { } /** - * Creates a room. This does not break out the various options for creating a room - * due to the large number of possibilities. See the /createRoom endpoint in the - * spec for more information on what to provide for `properties`. Note that creating + * Creates a room. See the RoomCreateOptions interface + * for more information on what to provide for `properties`. Note that creating * a room may cause the bot/appservice to raise a join event. - * @param {any} properties the properties of the room. See the spec for more information + * @param {RoomCreateOptions} properties the properties of the room. * @returns {Promise} resolves to the room ID that represents the room */ @timedMatrixClientFunctionCall() - public createRoom(properties: any = {}): Promise { + public createRoom(properties: RoomCreateOptions = {}): Promise { return this.doRequest("POST", "/_matrix/client/v3/createRoom", null, properties).then(response => { return response['room_id']; }); @@ -1698,10 +1698,10 @@ export class MatrixClient extends EventEmitter { */ @timedMatrixClientFunctionCall() public async createSpace(opts: SpaceCreateOptions): Promise { - const roomCreateOpts = { + const roomCreateOpts: RoomCreateOptions = { name: opts.name, topic: opts.topic || "", - preset: opts.isPublic ? 'public_chat' : 'private_chat', + preset: opts.isPublic ? "public_chat" : "private_chat", room_alias_name: opts.localpart, initial_state: [ { @@ -1711,7 +1711,7 @@ export class MatrixClient extends EventEmitter { history_visibility: opts.isPublic ? 'world_readable' : 'shared', }, }, - ] as unknown[], + ], creation_content: { type: "m.space", }, diff --git a/src/index.ts b/src/index.ts index dec9947a..8b77b91e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -54,6 +54,7 @@ export * from "./models/Account"; export * from "./models/PowerLevelAction"; export * from "./models/ServerVersions"; export * from "./models/MatrixError"; +export * from "./models/CreateRoom"; // Unstable models export * from "./models/unstable/MediaInfo"; diff --git a/src/models/CreateRoom.ts b/src/models/CreateRoom.ts new file mode 100644 index 00000000..2a8f808b --- /dev/null +++ b/src/models/CreateRoom.ts @@ -0,0 +1,144 @@ +import { PowerLevelsEventContent } from "./events/PowerLevelsEvent"; +import { CreateEventContent } from "./events/CreateEvent"; + +/** + * "private_chat" sets: + * - join_rules to `invite` + * - history_visibility to `shared` + * - guest_access to `can_join` + * + * "trusted_private_chat" sets: + * - join_rules to `invite` + * - history_visibility to `shared` + * - guest_access to `can_join` + * - All invitees are given the same power level as the room creator. + * + * "public_chat" sets: + * - join_rules to `public` + * - history_visibility to `shared` + * - guest_access to `forbidden` + * @category Models + */ +export type RoomPreset = "private_chat" | "trusted_private_chat" | "public_chat"; + +/** + * "public" visibility indicates that the room will be shown in the published room list. + * + * "private" visibility indicates that the room will not be included in published room list. + * @category Models + */ +export type RoomVisibility = "public" | "private"; + +/** + * The options available when creating a room. + * @category Models + */ +export interface RoomCreateOptions { + /** + * Extra keys, such as m.federate, to be added to the content of the m.room.create event. + * The server will overwrite the following keys: `creator`, `room_version`. + * Future versions of the specification may allow the server to overwrite other keys. + */ + creation_content?: Omit; + + /** + * A list of state events to set in the new room. + * This allows the user to override the default state events set in the new room. + * The expected format of the state events are an object with `type`, `state_key` and `content` keys set. + * Takes precedence over events set by `preset`, but gets overridden by `name` and `topic` keys. + */ + initial_state?: { + /** + * The content of the event. + */ + content: any; + + /** + * The state_key of the state event. Defaults to an empty string. + */ + state_key?: string; + + /** + * The type of event to send. + */ + type: string; + }[]; + + /** + * A list of user IDs to invite to the room. This will tell the server to invite everyone in the list to the newly created room. + */ + invite?: string[]; + + invite_3pid?: { + /** + * The inviteeā€™s third party identifier. + */ + address: string; + + /** + * An access token previously registered with the identity server. + * Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version. + */ + id_access_token: string; + + /** + * The hostname+port of the identity server which should be used for third party identifier lookups. + */ + id_server: string; + + /** + * The kind of address being passed in the address field, for example `email`. + */ + medium: string; + }[]; + + /** + * This flag makes the server set the `is_direct` flag on the `m.room.member` events sent to the users in `invite` and `invite_3pid`. + */ + is_direct?: boolean; + + /** + * If this is included, an `m.room.name` event will be sent into the room to indicate the name of the room. + */ + name?: string; + + /** + * The power level content to override in the default power level event. + * This object is applied on top of the generated `m.room.power_levels` event content prior to it being sent to the room. + * Defaults to overriding nothing. + */ + power_level_content_override?: PowerLevelsEventContent; + + /** + * Convenience parameter for setting various default state events based on a preset. + * + * If unspecified, the server should use the `visibility` to determine which preset to use. + * A visbility of `public` equates to a preset of `public_chat` and `private` visibility equates to a preset of `private_chat`. + */ + preset?: RoomPreset; + + /** + * The desired room alias local part. + * If this is included, a room alias will be created and mapped to the newly created room. + * The alias will belong on the same homeserver which created the room. + */ + room_alias_name?: string; + + /** + * The room version to set for the room. + * If not provided, the homeserver is to use its configured default. + * If provided, the homeserver will return a `400` error with the errcode `M_UNSUPPORTED_ROOM_VERSION` if it does not support the room version. + */ + room_version?: string; + + /** + * If this is included, an `m.room.topic` event will be sent into the room to indicate the topic for the room. + */ + topic?: string; + + /** + * Sets the visibility of the room + * Rooms default to private visibility if this key is not included. + */ + visibility?: RoomVisibility; +} diff --git a/src/models/events/CreateEvent.ts b/src/models/events/CreateEvent.ts index 9f644e26..8ef210a9 100644 --- a/src/models/events/CreateEvent.ts +++ b/src/models/events/CreateEvent.ts @@ -22,7 +22,7 @@ export interface PreviousRoomInfo { * @category Matrix event contents * @see CreateEvent */ -export interface CreateEventContent { +export interface CreateEventContent extends Record { /** * The user ID who created the room. */ @@ -42,6 +42,11 @@ export interface CreateEventContent { * Information about the old room. */ predecessor?: PreviousRoomInfo; + + /** + * The type of the room, if applicable. For example, `m.space`. + */ + type?: string; } /** diff --git a/test/MatrixClientTest.ts b/test/MatrixClientTest.ts index f3de387f..b62967e4 100644 --- a/test/MatrixClientTest.ts +++ b/test/MatrixClientTest.ts @@ -18,6 +18,7 @@ import { OTKs, PowerLevelAction, redactObjectForLogging, + RoomCreateOptions, RoomDirectoryLookupResponse, RoomEvent, RustSdkCryptoStorageProvider, @@ -2748,8 +2749,8 @@ describe('MatrixClient', () => { const { client, http } = createTestClient(); const roomId = "!something:example.org"; - const properties = { - hello: "world", + const properties: RoomCreateOptions = { + name: "hello world", preset: "public_chat", };