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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
Vendored
+11
@@ -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";
|
||||
@@ -0,0 +1 @@
|
||||
// Dummy file to make Node happy to import `shared-types` lib.
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
/** Type representing a valid JSON document */
|
||||
export type JsonDocument = JsonArray | JsonObject;
|
||||
+43
@@ -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;
|
||||
};
|
||||
Vendored
+83
@@ -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;
|
||||
@@ -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:"
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
Reference in New Issue
Block a user