Start consolidating shared types in the monorepo (#34062)

* Start consolidating shared types in the monorepo

* Iterate

* Simplify api-extractor

* Iterate

* Fix lockfile
This commit is contained in:
Michael Telatynski
2026-07-06 13:49:32 +00:00
committed by GitHub
parent b6cbc3a9d8
commit d4f72dfa69
29 changed files with 519 additions and 389 deletions
+1
View File
@@ -102,6 +102,7 @@
"mkdirp": "^3.0.0",
"pacote": "^22.0.0",
"rimraf": "^6.0.0",
"shared-types": "workspace:*",
"tar": "^7.5.8",
"typescript": "catalog:",
"vitest": "catalog:"
+2 -1
View File
@@ -7,8 +7,9 @@ Please see LICENSE files in the repository root for full details.
import path, { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { type JsonObject } from "shared-types";
import { type JsonObject, loadJsonFile } from "./utils.js";
import { loadJsonFile } from "./utils.js";
const __dirname = dirname(fileURLToPath(import.meta.url));
+9 -24
View File
@@ -7,27 +7,12 @@ Please see LICENSE files in the repository root for full details.
import { app, dialog } from "electron";
import path from "node:path";
import { type ResolveDefaults, type DesktopConfigJson, type JsonDocument } from "shared-types";
import { getAsarPath } from "./asar.js";
import { type Json, loadJsonFile } from "./utils.js";
import { loadJsonFile } from "./utils.js";
export interface ConfigOptions {
brand: string;
help_url: string;
web_base_url: string;
modules?: string[];
sentry?: {
dsn?: string;
environment?: string;
};
update_base_url?: string;
// homeserver props
default_is_url?: string;
default_hs_url?: string;
default_server_name?: string;
default_server_config?: object;
}
export type ConfigOptions = ResolveDefaults<DesktopConfigJson, typeof DEFAULTS>;
const ConfigFilename = "config.json";
@@ -35,7 +20,7 @@ let config: ConfigOptions;
const homeserverProps = ["default_is_url", "default_hs_url", "default_server_name", "default_server_config"] as const;
function loadLocalConfigFile(location: string | undefined): Json {
function loadLocalConfigFile(location: string | undefined): JsonDocument {
if (location) {
console.log("Loading local config: " + location);
return loadJsonFile(location);
@@ -50,9 +35,9 @@ const DEFAULTS = {
brand: "Element",
help_url: "https://element.io/help",
web_base_url: "https://app.element.io/",
} satisfies ConfigOptions;
} satisfies DesktopConfigJson;
function applyDefaults(conf: ConfigOptions): void {
function applyDefaults(conf: DesktopConfigJson): asserts conf is ConfigOptions {
for (const k in DEFAULTS) {
const key = k as keyof typeof DEFAULTS;
conf[key] ||= DEFAULTS[key];
@@ -71,7 +56,9 @@ export function loadConfig(localConfigPath: string | undefined): Promise<ConfigO
try {
console.log(`Loading app config: ${path.join(asarPath, ConfigFilename)}`);
// XXX: we trust that we built the package with a sane config, but should use something like zod here in future
config = loadJsonFile(asarPath, ConfigFilename) as unknown as ConfigOptions;
const loadedConfig = loadJsonFile(asarPath, ConfigFilename) as unknown as DesktopConfigJson;
applyDefaults(loadedConfig);
config = loadedConfig;
} catch {
// it would be nice to check the error code here and bail if the config
// is unparsable, but we get MODULE_NOT_FOUND in the case of a missing
@@ -80,8 +67,6 @@ export function loadConfig(localConfigPath: string | undefined): Promise<ConfigO
config = { ...DEFAULTS };
}
applyDefaults(config);
try {
// Load local config and use it to override values from the one baked with the build
const localConfig = loadLocalConfigFile(localConfigPath);
+2 -8
View File
@@ -9,6 +9,7 @@ import crypto from "node:crypto";
import fs from "node:fs";
import path from "node:path";
import afs from "node:fs/promises";
import { type JsonDocument } from "shared-types";
/**
* Returns a random array of a specified size in unpadded base64
@@ -26,19 +27,12 @@ export async function randomArray(size: number): Promise<string> {
});
}
type JsonValue = null | string | number;
type JsonArray = Array<JsonValue | JsonObject | JsonArray>;
export interface JsonObject {
[key: string]: JsonObject | JsonArray | JsonValue;
}
export type Json = JsonArray | JsonObject;
/**
* Synchronously load a JSON file from the local filesystem.
* Unlike `require`, will never execute any javascript in a loaded file.
* @param paths - An array of path segments which will be joined using the system's path delimiter.
*/
export function loadJsonFile<T extends Json>(...paths: string[]): T {
export function loadJsonFile<T extends JsonDocument>(...paths: string[]): T {
const joinedPaths = path.join(...paths);
if (!fs.existsSync(joinedPaths)) {
+1
View File
@@ -217,6 +217,7 @@
"postcss-simple-vars": "7.0.1",
"process": "^0.11.10",
"semver": "^7.5.2",
"shared-types": "workspace:*",
"source-map-loader": "^5.0.0",
"stylelint": "^17.0.0",
"stylelint-config-standard": "^40.0.0",
-6
View File
@@ -20,7 +20,6 @@ import {
type ToMatchScreenshotOptions,
} from "@element-hq/element-web-playwright-common";
import type { IConfigOptions } from "../src/IConfigOptions";
import { type Credentials } from "./plugins/homeserver";
import { ElementAppPage } from "./pages/ElementAppPage";
import { Crypto } from "./pages/crypto";
@@ -32,11 +31,6 @@ import { type WorkerOptions, type Services, test as base } from "./services";
// See https://playwright.dev/docs/service-workers-experimental#how-to-enable
process.env["PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS"] = "1";
declare module "@element-hq/element-web-playwright-common" {
// Improve the type for the config fixture based on the real type
export interface Config extends Omit<IConfigOptions, "default_server_config"> {}
}
export interface CredentialsWithDisplayName extends Credentials {
displayName: string;
}
+2 -49
View File
@@ -10,55 +10,8 @@ import { type JSX, type JSXElementConstructor } from "react";
export type { NonEmptyArray, XOR, Writeable } from "matrix-js-sdk/src/matrix";
export type * from "shared-types/lib/utils";
export type ComponentClass = keyof JSX.IntrinsicElements | JSXElementConstructor<any>;
export type { Leaves } from "matrix-web-i18n";
export type KeysStartingWith<Input extends object, Str extends string> = {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
[P in keyof Input]: P extends `${Str}${infer _X}` ? P : never; // we don't use _X
}[keyof Input];
export type Defaultize<P, D> = P extends any
? string extends keyof P
? P
: Pick<P, Exclude<keyof P, keyof D>> &
Partial<Pick<P, Extract<keyof P, keyof D>>> &
Partial<Pick<D, Exclude<keyof D, keyof P>>>
: never;
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
export type DeepReadonly<T> = T extends (infer R)[]
? DeepReadonlyArray<R>
: T extends Function
? T
: T extends object
? DeepReadonlyObject<T>
: T;
/* eslint-enable @typescript-eslint/no-unsafe-function-type */
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
export type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
/**
* Returns a union type of the keys of the input Object type whose values are assignable to the given Item type.
* Based on https://stackoverflow.com/a/57862073
*/
export type Assignable<Object, Item> = {
[Key in keyof Object]: Object[Key] extends Item ? Key : never;
}[keyof Object];
/**
* Like `Partial` but for applied to all nested objects.
* Based on https://dev.to/perennialautodidact/adventures-in-typescript-deeppartial-2f2a
*/
export type DeepPartial<T> = T extends object
? {
[P in keyof T]?: DeepPartial<T[P]>;
}
: T;
+10 -203
View File
@@ -7,15 +7,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type IClientWellKnown } from "matrix-js-sdk/src/matrix";
import { type ResolveDefaults, type WebConfigJson } from "shared-types";
import { type ValidatedServerConfig } from "./utils/ValidatedServerConfig";
// Convention decision: All config options are lower_snake_case
// We use an isolated file for the interface so we can mess around with the eslint options.
/* eslint-disable camelcase */
/* eslint @typescript-eslint/naming-convention: ["error", { "selector": "property", "format": ["snake_case"] } ] */
import { type DEFAULTS } from "./SdkConfig.ts";
/**
* Bug reports are enabled but must only be locally
@@ -23,202 +18,14 @@ import { type ValidatedServerConfig } from "./utils/ValidatedServerConfig";
*/
export const BugReportEndpointURLLocal = "local";
// see element-web config.md for non-developer docs
export interface IConfigOptions {
// dev note: while true that this is arbitrary JSON, it's valuable to enforce that all
// config options are documented for "find all usages" sort of searching.
// [key: string]: any;
// Properties of this interface are roughly grouped by their subject matter, such as
// "instance customisation", "login stuff", "branding", etc. Use blank lines to denote
// a logical separation of properties, but keep similar ones near each other.
// Exactly one of the following must be supplied
default_server_config?: IClientWellKnown; // copy/paste of client well-known
default_server_name?: string; // domain to do well-known lookup on
default_hs_url?: string; // http url
default_is_url?: string; // used in combination with default_hs_url, but for the identity server
// This is intended to be overridden by app startup and not specified by the user
// This is also why it's allowed to have an interface that isn't snake_case
export interface ConfigOptions extends WebConfigJson {
/**
* This is not a real config field, we're just abusing the config structure to pass around a validated server config
*/
validated_server_config?: ValidatedServerConfig;
fallback_hs_url?: string;
disable_custom_urls?: boolean;
disable_guests?: boolean;
disable_login_language_selector?: boolean;
disable_3pid_login?: boolean;
brand: string;
branding: {
welcome_background_url: string | string[]; // chosen at random if array
logo_link_url: string;
auth_header_logo_url?: string;
auth_footer_links?: { text: string; url: string }[];
};
force_verification?: boolean; // if true, users must verify new logins
map_style_url?: string; // for location-shared maps
embedded_pages?: {
welcome_url?: string;
home_url?: string;
login_for_welcome?: boolean;
};
permalink_prefix?: string;
update_base_url?: string;
desktop_builds: {
available: boolean;
logo: string; // url
url: string; // download url
url_macos?: string;
url_win64?: string;
url_win64arm?: string;
url_linux?: string;
};
mobile_builds: {
ios: string | null; // download url
android: string | null; // download url
fdroid: string | null; // download url
};
mobile_guide_toast?: boolean;
mobile_guide_app_variant?: "element" | "element-classic" | "element-pro";
default_theme?: "light" | "dark" | string; // custom themes are strings
default_country_code?: string; // ISO 3166 alpha2 country code
default_federate?: boolean;
default_device_display_name?: string; // for device naming on login+registration
setting_defaults?: Record<string, any>; // <SettingName, Value>
integrations_ui_url?: string;
integrations_rest_url?: string;
integrations_widgets_urls?: string[];
default_widget_container_height?: number; // height in pixels
show_labs_settings: boolean;
features?: Record<string, boolean>; // <FeatureName, EnabledBool>
/**
* Bug report endpoint URL. "local" means the logs should not be uploaded.
*/
bug_report_endpoint_url?: typeof BugReportEndpointURLLocal | string; // omission disables bug reporting
sentry?: {
dsn: string;
environment?: string; // "production", etc
};
widget_build_url?: string; // url called to replace jitsi/call widget creation
widget_build_url_ignore_dm?: boolean;
audio_stream_url?: string;
jitsi?: {
preferred_domain: string;
};
jitsi_widget?: {
skip_built_in_welcome_screen?: boolean;
};
voip?: {
obey_asserted_identity?: boolean; // MSC3086
};
element_call: {
guest_spa_url?: string;
use_exclusively?: boolean;
brand?: string;
};
logout_redirect_url?: string;
sso_redirect_options?: ISsoRedirectOptions;
custom_translations_url?: string;
report_event?: {
admin_message_md: string; // message for how to contact the server owner when reporting an event
};
room_directory?: {
servers: string[];
};
posthog?: {
project_api_key: string;
api_host: string; // hostname
};
analytics_owner?: string; // defaults to `brand`
privacy_policy_url?: string; // location for cookie policy
enable_presence_by_hs_url?: Record<string, boolean>; // <HomeserverName, Enabled>
terms_and_conditions_links?: { url: string; text: string }[];
help_url: string;
help_encryption_url: string;
help_key_storage_url: string;
latex_maths_delims?: {
inline?: {
left?: string;
right?: string;
pattern?: {
tex?: string;
latex?: string;
};
};
display?: {
left?: string;
right?: string;
pattern?: {
tex?: string;
latex?: string;
};
};
};
sync_timeline_limit?: number;
dangerously_allow_unsafe_and_insecure_passwords?: boolean; // developer option
user_notice?: {
title: string;
description: string;
show_once?: boolean;
};
feedback: {
existing_issues_url: string;
new_issue_url: string;
};
/**
* Configuration for OIDC issuers where a static client_id has been issued for the app.
* Otherwise dynamic client registration is attempted.
* The issuer URL must have a trailing `/`.
* OPTIONAL
*/
oidc_static_clients?: {
[issuer: string]: { client_id: string };
};
/**
* Configuration for OIDC dynamic registration where a static OIDC client is not configured.
*/
oidc_metadata?: {
client_uri?: string;
logo_uri?: string;
tos_uri?: string;
policy_uri?: string;
contacts?: string[];
};
modules?: string[];
}
export interface ISsoRedirectOptions {
immediate?: boolean;
on_welcome_page?: boolean;
on_login_page?: boolean;
}
/**
* Type representing the effective config.json structure after DEFAULTS has been merged in
*/
export type IConfigOptions = ResolveDefaults<ConfigOptions, typeof DEFAULTS>;
+4 -4
View File
@@ -139,10 +139,10 @@ export class PosthogAnalytics {
}
public constructor(private readonly posthog: PostHog) {
const posthogConfig = SdkConfig.getObject("posthog");
if (posthogConfig) {
this.posthog.init(posthogConfig.get("project_api_key"), {
api_host: posthogConfig.get("api_host"),
const posthogConfig = SdkConfig.get("posthog");
if (posthogConfig?.project_api_key && posthogConfig?.api_host) {
this.posthog.init(posthogConfig.project_api_key, {
api_host: posthogConfig.api_host,
autocapture: false,
mask_all_text: true,
mask_all_element_attributes: true,
+7 -7
View File
@@ -8,15 +8,15 @@ Please see LICENSE files in the repository root for full details.
*/
import { mergeWith } from "lodash";
import { type DeepReadonly } from "shared-types";
import { SnakedObject } from "./utils/SnakedObject";
import { type IConfigOptions } from "./IConfigOptions";
import { type IConfigOptions, type ConfigOptions } from "./IConfigOptions";
import { isObject, objectClone } from "./utils/objects";
import { type DeepPartial, type DeepReadonly, type Defaultize } from "./@types/common";
import ElementDesktopLogoSvg from "../res/img/element-desktop-logo.svg";
// see element-web config.md for docs, or the IConfigOptions interface for dev docs
export const DEFAULTS: DeepReadonly<IConfigOptions> = {
export const DEFAULTS = {
brand: "Element",
branding: {
logo_link_url: "https://element.io",
@@ -69,13 +69,13 @@ export const DEFAULTS: DeepReadonly<IConfigOptions> = {
android: "https://play.google.com/store/apps/details?id=im.vector.app",
fdroid: "https://f-droid.org/repository/browse/?fdid=im.vector.app",
},
};
} satisfies ConfigOptions;
export type ConfigOptions = Defaultize<IConfigOptions, typeof DEFAULTS>;
export type { ConfigOptions };
function mergeConfig(
config: DeepReadonly<IConfigOptions>,
changes: DeepReadonly<DeepPartial<IConfigOptions>>,
changes: DeepReadonly<ConfigOptions>,
): DeepReadonly<IConfigOptions> {
// return { ...config, ...changes };
return mergeWith(objectClone(config), changes, (objValue, srcValue) => {
@@ -141,7 +141,7 @@ export default class SdkConfig {
SdkConfig.setInstance(mergeConfig(DEFAULTS, {})); // safe to cast - defaults will be applied
}
public static add(cfg: DeepPartial<ConfigOptions>): void {
public static add(cfg: DeepReadonly<ConfigOptions>): void {
SdkConfig.put(mergeConfig(SdkConfig.get(), cfg));
}
}
+6 -2
View File
@@ -707,7 +707,11 @@ export class ElementCall extends Call {
*/
private static appendAnalyticsParams(params: URLSearchParams, client: MatrixClient): void {
const posthogConfig = SdkConfig.get("posthog");
if (!posthogConfig || PosthogAnalytics.instance.getAnonymity() === Anonymity.Disabled) {
if (
!posthogConfig?.project_api_key ||
!posthogConfig?.api_host ||
PosthogAnalytics.instance.getAnonymity() === Anonymity.Disabled
) {
return;
}
@@ -725,7 +729,7 @@ export class ElementCall extends Call {
// We gate passing sentry behind analytics consent as EC shares data automatically without user-consent,
// unlike EW where data is shared upon an intentional user action (rageshake).
const sentryConfig = SdkConfig.get("sentry");
if (sentryConfig) {
if (sentryConfig?.dsn) {
params.append("sentryDsn", sentryConfig.dsn);
params.append("sentryEnvironment", sentryConfig.environment ?? "");
}
+2 -2
View File
@@ -10,6 +10,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type ReactNode } from "react";
import { STABLE_MSC4133_EXTENDED_PROFILES, UNSTABLE_MSC4133_EXTENDED_PROFILES } from "matrix-js-sdk/src/matrix";
import { type JsonDocument, type JsonValue } from "shared-types";
// Import these directly from shared-components to avoid circular deps
import { _t, _td } from "@element-hq/web-shared-components";
@@ -44,7 +45,6 @@ import FallbackIceServerController from "./controllers/FallbackIceServerControll
import { type IRightPanelForRoomStored } from "../stores/right-panel/RightPanelStoreIPanelState.ts";
import { type ILayoutSettings } from "../stores/widgets/WidgetLayoutStore.ts";
import { type ReleaseAnnouncementData } from "../stores/ReleaseAnnouncementStore.ts";
import { type Json, type JsonValue } from "../@types/json.ts";
import { type RecentEmojiData } from "../emojipicker/recent.ts";
import { type Assignable } from "../@types/common.ts";
import { SortingAlgorithm } from "../stores/room-list-v3/skip-list/sorters/index.ts";
@@ -121,7 +121,7 @@ export const labGroupNames: Record<LabGroup, TranslationKey> = {
[LabGroup.Ui]: _td("labs|group_ui"),
};
export type SettingValueType = Json | JsonValue | Record<string, unknown> | Record<string, unknown>[];
export type SettingValueType = JsonDocument | JsonValue | Record<string, unknown> | Record<string, unknown>[];
export interface IBaseSetting<T extends SettingValueType = SettingValueType> {
isFeature?: false | undefined;
+1 -1
View File
@@ -67,7 +67,7 @@
*
* "bundledPackages": [ "@my-company/*" ],
*/
"bundledPackages": [],
"bundledPackages": ["shared-types"],
/**
* Specifies what type of newlines API Extractor should use when writing output files. By default, the output files
@@ -125,8 +125,10 @@ export type ComposerApiTarget = {
view: "thread";
};
// Warning: (ae-forgotten-export) The symbol "WebConfigJson" needs to be exported by the entry point index.d.ts
//
// @public
export interface Config {
export interface Config extends WebConfigJson {
// (undocumented)
brand: string;
}
+1
View File
@@ -46,6 +46,7 @@
"matrix-widget-api": "^1.17.0",
"rollup-plugin-external-globals": "^0.13.0",
"semver": "^7.6.3",
"shared-types": "workspace:*",
"typescript": "catalog:",
"unplugin-dts": "catalog:",
"vite": "catalog:",
+2 -6
View File
@@ -5,14 +5,10 @@
"targets": {
"build": {
"cache": true,
"executor": "nx:run-commands",
"inputs": ["src"],
"outputs": ["{projectRoot}/lib"],
"options": {
"commands": ["vite build", "api-extractor run"],
"parallel": false,
"cwd": "packages/module-api"
}
"command": "vite build",
"options": { "cwd": "packages/module-api" }
},
"start": {
"command": "vite build --watch",
+3 -3
View File
@@ -5,16 +5,16 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type WebConfigJson } from "shared-types";
/**
* The configuration for the application.
* Should be extended via declaration merging.
* @public
*/
export interface Config {
export interface Config extends WebConfigJson {
// The branding name of the application
brand: string;
// Other config options are available but not specified in the types as that would make it difficult to change for element-web
// they are accessible at runtime all the same, see list at https://github.com/element-hq/element-web/blob/develop/docs/config.md
}
/**
+5 -1
View File
@@ -27,7 +27,11 @@ export default defineConfig({
sourcemap: true,
},
plugins: [
dts(),
dts({
bundleTypes: {
configPath: "./api-extractor.json",
},
}),
externalGlobals({
// Reuse React from the host app
react: "window.React",
+4 -20
View File
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { type Config as BaseConfig } from "@element-hq/element-web-module-api";
import { type Config } from "@element-hq/element-web-module-api";
import { test as base } from "./fixtures/index.js";
import { routeConfigJson } from "./utils/config_json.js";
@@ -22,27 +22,11 @@ export { populateLocalStorageWithCredentials } from "./fixtures/user.js";
// See https://playwright.dev/docs/service-workers-experimental#how-to-enable
process.env["PW_EXPERIMENTAL_SERVICE_WORKER_NETWORK_EVENTS"] = "1";
// We extend the Module API Config interface so that all modules
// which use declaration merging will have their config types correctly applied.
export interface Config extends BaseConfig {
default_server_config: {
"m.homeserver"?: {
base_url: string;
server_name?: string;
};
"m.identity_server"?: {
base_url: string;
server_name?: string;
};
};
enable_presence_by_hs_url?: Record<string, boolean>;
setting_defaults: Record<string, unknown>;
map_style_url?: string;
features: Record<string, boolean>;
modules?: string[];
}
export type { Config };
// This is deliberately quite a minimal config.json, so that we can test that the default settings actually work.
// We use the Module API Config interface so that all modules
// which use declaration merging will have their config types correctly applied.
export const CONFIG_JSON: Partial<Config> = {
default_server_config: {},
+217
View File
@@ -0,0 +1,217 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { DeepPartial } from "./utils";
import { ClientWellKnown } from "./matrix";
// Convention decision: All config options are lower_snake_case
// see docs/config.md for non-developer docs
/**
* Type describing the `config.json` format for Element Web
* All fields are optional here, consumers should validate that fields are present before assuming otherwise
*/
export interface WebConfigJson {
// dev note: while true that this is arbitrary JSON, it's valuable to enforce that all
// config options are documented for "find all usages" sort of searching.
// Properties of this interface are roughly grouped by their subject matter, such as
// "instance customisation", "login stuff", "branding", etc. Use blank lines to denote
// a logical separation of properties, but keep similar ones near each other.
// Exactly one of the following must be supplied
default_server_config?: DeepPartial<Pick<ClientWellKnown, "m.homeserver" | "m.identity_server">>;
default_server_name?: string; // domain to do well-known lookup on
default_hs_url?: string; // http url
default_is_url?: string; // used in combination with default_hs_url, but for the identity server
fallback_hs_url?: string;
disable_custom_urls?: boolean;
disable_guests?: boolean;
disable_login_language_selector?: boolean;
disable_3pid_login?: boolean;
brand?: string;
branding?: {
welcome_background_url?: string | string[]; // chosen at random if array
logo_link_url?: string;
auth_header_logo_url?: string;
auth_footer_links?: { text: string; url: string }[];
};
force_verification?: boolean; // if true, users must verify new logins
map_style_url?: string; // for location-shared maps
embedded_pages?: {
welcome_url?: string;
home_url?: string;
login_for_welcome?: boolean;
};
permalink_prefix?: string;
desktop_builds?: {
available?: boolean;
logo?: string; // url
url?: string; // download url
url_macos?: string;
url_win64?: string;
url_win64arm?: string;
url_linux?: string;
};
mobile_builds?: {
ios?: string; // download url
android?: string; // download url
fdroid?: string; // download url
};
mobile_guide_toast?: boolean;
mobile_guide_app_variant?: "element" | "element-classic" | "element-pro";
default_theme?: "light" | "dark" | string; // custom themes are strings
default_country_code?: string; // ISO 3166 alpha2 country code
default_federate?: boolean;
default_device_display_name?: string; // for device naming on login+registration
setting_defaults?: Record<string, any>; // <SettingName, Value>
integrations_ui_url?: string;
integrations_rest_url?: string;
integrations_widgets_urls?: string[];
default_widget_container_height?: number; // height in pixels
show_labs_settings?: boolean;
features?: Record<string, boolean>; // <FeatureName, EnabledBool>
/**
* Bug report endpoint URL. "local" means the logs should not be uploaded.
* Omission disables bug reporting
*/
bug_report_endpoint_url?: string;
sentry?: {
dsn?: string;
environment?: string; // "production", etc
};
widget_build_url?: string; // url called to replace jitsi/call widget creation
widget_build_url_ignore_dm?: boolean;
audio_stream_url?: string;
jitsi?: {
preferred_domain?: string;
};
jitsi_widget?: {
skip_built_in_welcome_screen?: boolean;
};
voip?: {
obey_asserted_identity?: boolean; // MSC3086
};
element_call?: {
guest_spa_url?: string;
use_exclusively?: boolean;
brand?: string;
};
logout_redirect_url?: string;
sso_redirect_options?: {
immediate?: boolean;
on_welcome_page?: boolean;
on_login_page?: boolean;
};
custom_translations_url?: string;
report_event?: {
admin_message_md?: string; // message for how to contact the server owner when reporting an event
};
room_directory?: {
servers?: string[];
};
posthog?: {
project_api_key?: string;
api_host?: string; // hostname
};
analytics_owner?: string; // defaults to `brand`
privacy_policy_url?: string; // location for cookie policy
enable_presence_by_hs_url?: Record<string, boolean>; // <HomeserverName, Enabled>
terms_and_conditions_links?: { url: string; text: string }[];
help_url?: string;
help_encryption_url?: string;
help_key_storage_url?: string;
latex_maths_delims?: {
inline?: {
left?: string;
right?: string;
pattern?: {
tex?: string;
latex?: string;
};
};
display?: {
left?: string;
right?: string;
pattern?: {
tex?: string;
latex?: string;
};
};
};
sync_timeline_limit?: number;
dangerously_allow_unsafe_and_insecure_passwords?: boolean; // developer option
user_notice?: {
title?: string;
description?: string;
show_once?: boolean;
};
feedback?: {
existing_issues_url?: string;
new_issue_url?: string;
};
/**
* Configuration for OIDC issuers where a static client_id has been issued for the app.
* Otherwise dynamic client registration is attempted.
* The issuer URL must have a trailing `/`.
* OPTIONAL
*/
oidc_static_clients?: {
[issuer: string]: { client_id: string };
};
/**
* Configuration for OIDC dynamic registration where a static OIDC client is not configured.
*/
oidc_metadata?: {
client_uri?: string;
logo_uri?: string;
tos_uri?: string;
policy_uri?: string;
contacts?: string[];
};
modules?: string[];
}
/**
* Type describing the `config.json` format for Element Desktop, a superset of Element Web's config.
* All fields are optional here, consumers should validate that fields are present before assuming otherwise
*/
export interface DesktopConfigJson extends WebConfigJson {
web_base_url?: string;
update_base_url?: string;
}
+11
View File
@@ -0,0 +1,11 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
export type * from "./config.json.d.ts";
export type * from "./utils.d.ts";
export type * from "./matrix.d.ts";
export type * from "./json.d.ts";
+1
View File
@@ -0,0 +1 @@
// Dummy file to make Node happy to import `shared-types` lib.
@@ -1,13 +1,20 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
/** Type representing a valid JSON value */
export type JsonValue = null | string | number | boolean;
/** Type representing a valid JSON array */
export type JsonArray = Array<JsonValue | JsonObject | JsonArray>;
/** Type representing a valid JSON object */
export interface JsonObject {
[key: string]: JsonObject | JsonArray | JsonValue;
}
export type Json = JsonArray | JsonObject;
/** Type representing a valid JSON document */
export type JsonDocument = JsonArray | JsonObject;
+43
View File
@@ -0,0 +1,43 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { JsonDocument } from "./json";
/**
* As specified by https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient
*/
export type ClientWellKnown = {
/**
* Used by clients to discover homeserver information.
*/
"m.homeserver": {
/**
* The base URL for the homeserver for client-server connections.
*/
base_url: string;
/**
* This field is not part of the spec but supported by Element Web's config.json
* @deprecated - we should figure out whether we want to keep this or not.
*/
server_name?: string;
};
/**
* Used by clients to discover identity server information.
*/
"m.identity_server"?: {
/**
* The base URL for the identity server for client-server connections.
*/
base_url: string;
};
} & {
/**
* Other properties
* Application-dependent keys using Java package naming convention.
*/
[key: string]: JsonDocument;
};
+83
View File
@@ -0,0 +1,83 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
/**
* Returns a union type of the keys of the Input type whose names start with the given string Str.
*/
export type KeysStartingWith<Input extends object, Str extends string> = {
[P in keyof Input]: P extends `${Str}${infer _X}` ? P : never; // we don't use _X
}[keyof Input];
/**
* Makes fields of T and its object children optional if they are defined in D.
* Useful for generating the input type for a given function if it applies an object of defaults.
*/
export type Defaultize<P, D> = P extends any
? string extends keyof P
? P
: Pick<P, Exclude<keyof P, keyof D>> &
Partial<Pick<P, Extract<keyof P, keyof D>>> &
Partial<Pick<D, Exclude<keyof D, keyof P>>>
: never;
/**
* Makes fields of T and its object children non-optional if they are defined in D.
* Useful for generating a type which allows you to know which fields will be defined once you apply default values.
*/
export type ResolveDefaults<T, D> = {
[K in keyof T as K extends keyof D ? K : never]-?: SafeIndex<D, K> extends object
? NonNullable<T[K]> extends any[]
? NonNullable<T[K]>
: NonNullable<T[K]> extends object
? ResolveDefaults<NonNullable<T[K]>, SafeIndex<D, K>>
: NonNullable<T[K]>
: NonNullable<T[K]>;
} & {
[K in keyof T as K extends keyof D ? never : K]: T[K];
} & {};
type SafeIndex<D, K> = K extends keyof D ? D[K] : never;
/**
* Applies the `readonly` modifier to all fields of T and its object children.
*/
export type DeepReadonly<T> = T extends (infer R)[]
? DeepReadonlyArray<R>
: T extends Function
? T
: T extends object
? DeepReadonlyObject<T>
: T;
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
type DeepReadonlyObject<T> = {
readonly [P in keyof T]: DeepReadonly<T[P]>;
};
/**
* Like `Partial` but requires at least one property to be present.
*/
export type AtLeastOne<T, U = { [K in keyof T]: Pick<T, K> }> = Partial<T> & U[keyof U];
/**
* Returns a union type of the keys of the input Object type whose values are assignable to the given Item type.
* Based on https://stackoverflow.com/a/57862073
*/
export type Assignable<Object, Item> = {
[Key in keyof Object]: Object[Key] extends Item ? Key : never;
}[keyof Object];
/**
* Like `Partial` but for applied to all nested objects.
* Based on https://dev.to/perennialautodidact/adventures-in-typescript-deeppartial-2f2a
*/
export type DeepPartial<T> = T extends object
? {
[P in keyof T]?: DeepPartial<T[P]>;
}
: T;
+20
View File
@@ -0,0 +1,20 @@
{
"name": "shared-types",
"type": "module",
"version": "0.0.0",
"private": true,
"description": "Shared types for Element Web & Desktop",
"author": "element-hq",
"license": "SEE LICENSE IN README.md",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": [
"lib"
],
"scripts": {
"lint:types": "tsc --noEmit"
},
"devDependencies": {
"typescript": "catalog:"
}
}
+13
View File
@@ -0,0 +1,13 @@
{
"$schema": "http://json.schemastore.org/tsconfig",
"compilerOptions": {
"rootDir": "./lib",
"target": "esnext",
"lib": ["es2024"],
"strict": true,
"types": [],
"allowImportingTsExtensions": true,
"noEmit": true
},
"include": ["lib"]
}
+55 -49
View File
@@ -241,9 +241,6 @@ catalogs:
react-dom:
specifier: ^19.0.0
version: 19.2.7
typescript:
specifier: 6.0.3
version: 6.0.3
unplugin-dts:
specifier: 1.0.1
version: 1.0.1
@@ -284,6 +281,7 @@ overrides:
protobufjs@7 <7.5.8: 7.6.1
'@protobufjs/utf8@1 <1.1.1': 1.1.1
yauzl: ^3.3.1
typescript: 6.0.3
packageExtensionsChecksum: sha256-EMEi1vcyzQthk7O/0AcntvnHgJaKCoFBlzp6iX/qNYk=
@@ -351,7 +349,7 @@ importers:
specifier: 0.56.0
version: 0.56.0
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
vitepress:
specifier: ^1.6.4
@@ -492,11 +490,14 @@ importers:
rimraf:
specifier: ^6.0.0
version: 6.1.3
shared-types:
specifier: workspace:*
version: link:../../packages/shared-types
tar:
specifier: ^7.5.8
version: 7.5.19
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
vitest:
specifier: 'catalog:'
@@ -1033,6 +1034,9 @@ importers:
semver:
specifier: ^7.5.2
version: 7.8.5
shared-types:
specifier: workspace:*
version: link:../../packages/shared-types
source-map-loader:
specifier: ^5.0.0
version: 5.0.0(webpack@5.108.3)
@@ -1055,7 +1059,7 @@ importers:
specifier: ^12.0.0
version: 12.0.4
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
util:
specifier: ^0.12.5
@@ -1164,7 +1168,7 @@ importers:
specifier: 'catalog:'
version: 19.2.7
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
vite:
specifier: 'catalog:'
@@ -1213,7 +1217,7 @@ importers:
specifier: ^12.0.1
version: 12.0.4
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
vite:
specifier: 'catalog:'
@@ -1235,7 +1239,7 @@ importers:
specifier: 25.9.3
version: 25.9.3
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
vite:
specifier: 'catalog:'
@@ -1293,7 +1297,7 @@ importers:
specifier: 'catalog:'
version: 19.2.7
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
vite:
specifier: 'catalog:'
@@ -1344,8 +1348,11 @@ importers:
semver:
specifier: ^7.6.3
version: 7.8.5
shared-types:
specifier: workspace:*
version: link:../shared-types
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
unplugin-dts:
specifier: 'catalog:'
@@ -1400,7 +1407,7 @@ importers:
specifier: ^4.17.12
version: 4.17.12
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
packages/shared-components:
@@ -1602,7 +1609,7 @@ importers:
specifier: ^4.1.2
version: 4.1.3(typedoc@0.28.19(typescript@6.0.3))
typescript:
specifier: 'catalog:'
specifier: 6.0.3
version: 6.0.3
unplugin-dts:
specifier: 'catalog:'
@@ -1617,6 +1624,12 @@ importers:
specifier: 'catalog:'
version: 4.1.9(@opentelemetry/api@1.9.1)(@types/node@25.9.3)(@vitest/browser-playwright@4.1.9)(@vitest/coverage-v8@4.1.9)(happy-dom@20.10.6)(jsdom@26.1.0(patch_hash=040623e87b1c8b676c2a705513c0276c0704dd1b23fc3a1bb77cde8128b64b5f))(vite@8.1.3(@types/node@25.9.3)(esbuild@0.27.4)(jiti@2.7.0)(sugarss@5.0.1(postcss@8.5.16))(terser@5.48.0)(yaml@2.8.4))
packages/shared-types:
devDependencies:
typescript:
specifier: 6.0.3
version: 6.0.3
packages:
'@action-validator/cli@0.6.0':
@@ -3383,7 +3396,7 @@ packages:
'@joshwooding/vite-plugin-react-docgen-typescript@0.7.0':
resolution: {integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==}
peerDependencies:
typescript: '>= 4.3.x'
typescript: 6.0.3
vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
@@ -5573,7 +5586,7 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
storybook: ^10.4.6
typescript: '>= 4.9.x'
typescript: 6.0.3
peerDependenciesMeta:
'@types/react':
optional: true
@@ -6148,32 +6161,32 @@ packages:
peerDependencies:
'@typescript-eslint/parser': ^8.61.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/parser@8.62.1':
resolution: {integrity: sha512-sPhE4iHuJDSvoAiec+Ro8JyXw8f0ql13HFR82P99nCm9GwTEKG0KYLvDe6REk8BCXuit6vJAv/Yxg5ABaNS2rA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/project-service@8.61.0':
resolution: {integrity: sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/project-service@8.61.1':
resolution: {integrity: sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/project-service@8.62.1':
resolution: {integrity: sha512-yQ3RgY5RkSBpsNS1Bx/JQEcA24FOSdfGktoyprAr5u18390UQdtVcfnEv4nIrIshNnavlVyZBKxQwT1fIAE6cg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/scope-manager@8.61.0':
resolution: {integrity: sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA==}
@@ -6191,26 +6204,26 @@ packages:
resolution: {integrity: sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/tsconfig-utils@8.61.1':
resolution: {integrity: sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/tsconfig-utils@8.62.1':
resolution: {integrity: sha512-xadytJqX9vJVQ2fdQjkcIVigwaOJNWkpjdLt6cEQ+xPnrI1fkp+/jZE/I97k9KUjqtpd25i0HeyZf3T6dutv2g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/type-utils@8.61.0':
resolution: {integrity: sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/types@8.61.0':
resolution: {integrity: sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg==}
@@ -6228,33 +6241,33 @@ packages:
resolution: {integrity: sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/typescript-estree@8.61.1':
resolution: {integrity: sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/typescript-estree@8.62.1':
resolution: {integrity: sha512-xMcW9oP9u7fAMXYs9A65CVmtLQe2r//oXINHfi8HV+oiqhih17sbLdhXr4540YWlgpDKQdY854OL5ZrdCiQsAA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/utils@8.61.0':
resolution: {integrity: sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/utils@8.61.1':
resolution: {integrity: sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
typescript: '>=4.8.4 <6.1.0'
typescript: 6.0.3
'@typescript-eslint/visitor-keys@8.61.0':
resolution: {integrity: sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ==}
@@ -7670,7 +7683,7 @@ packages:
resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==}
engines: {node: '>=14'}
peerDependencies:
typescript: '>=4.9.5'
typescript: 6.0.3
peerDependenciesMeta:
typescript:
optional: true
@@ -7679,7 +7692,7 @@ packages:
resolution: {integrity: sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg==}
engines: {node: '>=14'}
peerDependencies:
typescript: '>=4.9.5'
typescript: 6.0.3
peerDependenciesMeta:
typescript:
optional: true
@@ -8620,7 +8633,7 @@ packages:
'@typescript-eslint/eslint-plugin': ^8.0.0
eslint: ^8.57.0 || ^9.0.0 || ^10.0.0
jest: '*'
typescript: '>=4.8.4 <7.0.0'
typescript: 6.0.3
peerDependenciesMeta:
'@typescript-eslint/eslint-plugin':
optional: true
@@ -8655,7 +8668,7 @@ packages:
eslint-plugin-react-hooks: '*'
eslint-plugin-unicorn: <57
prettier: '*'
typescript: '*'
typescript: 6.0.3
eslint-plugin-n@17.24.0:
resolution: {integrity: sha512-/gC7/KAYmfNnPNOb3eu8vw+TdVnV0zhdQwexsw6FLXbhzroVj20vRn2qL8lDWDGnAQ2J8DhdfvXxX9EoxvERvw==}
@@ -11966,7 +11979,7 @@ packages:
react-docgen-typescript@2.4.0:
resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==}
peerDependencies:
typescript: '>= 4.3.x'
typescript: 6.0.3
react-docgen@8.0.3:
resolution: {integrity: sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==}
@@ -13186,12 +13199,12 @@ packages:
resolution: {integrity: sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==}
engines: {node: '>=18.12'}
peerDependencies:
typescript: '>=4.8.4'
typescript: 6.0.3
ts-declaration-location@1.0.7:
resolution: {integrity: sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==}
peerDependencies:
typescript: '>=4.0.0'
typescript: 6.0.3
ts-dedent@2.3.0:
resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==}
@@ -13271,7 +13284,7 @@ packages:
type-plus@8.0.0-beta.8:
resolution: {integrity: sha512-egrpXQq2tV0abCf99+n4SCD/stT76qEwPBI1q7BqiVUe5pHWc+bm4vsOiNR84SmZTv4SoEl9UOZUdkEbS3POdw==}
peerDependencies:
typescript: '>= 5.6.0'
typescript: 6.0.3
typed-array-buffer@1.0.3:
resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==}
@@ -13305,12 +13318,7 @@ packages:
engines: {node: '>= 18', pnpm: '>= 10'}
hasBin: true
peerDependencies:
typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x || 6.0.x
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
hasBin: true
typescript: 6.0.3
typescript@6.0.3:
resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==}
@@ -13428,7 +13436,7 @@ packages:
esbuild: 0.27.4
rolldown: '*'
rollup: '>=3'
typescript: '>=4'
typescript: 6.0.3
vite: '>=3'
webpack: ^4 || ^5
peerDependenciesMeta:
@@ -13730,7 +13738,7 @@ packages:
vue@3.5.31:
resolution: {integrity: sha512-iV/sU9SzOlmA/0tygSmjkEN6Jbs3nPoIPFhCMLD2STrjgOU8DX7ZtzMhg4ahVwf5Rp9KoFzcXeB1ZrVbLBp5/Q==}
peerDependencies:
typescript: '*'
typescript: 6.0.3
peerDependenciesMeta:
typescript:
optional: true
@@ -14282,7 +14290,7 @@ snapshots:
'@arcmantle/vite-plugin-import-css-sheet@1.0.14(patch_hash=8019aa9feca17db6bab3483612b4150c911d70b58fddc52bf2d7258a1484a747)':
dependencies:
lightningcss: 1.32.0
typescript: 5.9.3
typescript: 6.0.3
'@asamuzakjp/css-color@3.2.0':
dependencies:
@@ -16545,7 +16553,7 @@ snapshots:
resolve: 1.22.12
semver: 7.7.4
source-map: 0.6.1
typescript: 5.9.3
typescript: 6.0.3
transitivePeerDependencies:
- '@types/node'
@@ -27603,8 +27611,6 @@ snapshots:
typescript: 6.0.3
yaml: 2.8.4
typescript@5.9.3: {}
typescript@6.0.3: {}
ua-parser-js@1.0.40: {}
+2
View File
@@ -135,6 +135,8 @@ overrides:
"@protobufjs/utf8@1 <1.1.1": 1.1.1
# Workaround for https://github.com/electron/electron/issues/51619
yauzl: "^3.3.1"
# Convince api-extractor to use an up to date Typescript version
typescript: "catalog:"
minimumReleaseAgeExclude:
- "matrix-js-sdk"