diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b4e4934f..1eecd5ac 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -293,7 +293,7 @@ jobs: node-version: 24 - name: JS Type Check run: | - npx -p typescript tsc -p radicale/web/jsconfig.json + npx -y -p typescript@7.0.2 tsc -p radicale/web/jsconfig.json lint: name: Lint diff --git a/radicale/web/internal_data/js/api/api.js b/radicale/web/internal_data/js/api/api.js index 30ee46bb..41cfe8b8 100644 --- a/radicale/web/internal_data/js/api/api.js +++ b/radicale/web/internal_data/js/api/api.js @@ -28,7 +28,7 @@ import { create_request, to_error_message } from "./common.js"; * Find the principal collection. * @param {?string} user * @param {?string} password - * @param {function(?Collection, ?string):void} callback Returns result or error + * @param {(collection: Collection | null, error: string | null) => void} callback Returns result or error * @return {XMLHttpRequest} */ export function get_principal(user, password, callback) { @@ -81,7 +81,7 @@ export function get_principal(user, password, callback) { * @param {string} user * @param {?string} password * @param {Collection} collection - * @param {function(?Array, ?string):void} callback Returns result or error + * @param {(collections: Array | null, error: string | null) => void} callback Returns result or error * @return {XMLHttpRequest} */ export function get_collections(user, password, collection, callback) { @@ -267,7 +267,7 @@ function _parse_collection(response, collection_href) { * @param {?string} password * @param {string} collection_href Must always start and end with /. * @param {File} file - * @param {function(?string):void} callback Returns error or null + * @param {(error: string | null) => void} callback Returns error or null * @return {XMLHttpRequest} */ export function upload_collection(user, password, collection_href, file, callback) { @@ -291,7 +291,7 @@ export function upload_collection(user, password, collection_href, file, callbac * @param {string} user * @param {?string} password * @param {Collection} collection - * @param {function(?string):void} callback Returns error or null + * @param {(error: string | null) => void} callback Returns error or null * @return {XMLHttpRequest} */ export function delete_collection(user, password, collection, callback) { @@ -315,7 +315,7 @@ export function delete_collection(user, password, collection, callback) { * @param {?string} password * @param {Collection} collection * @param {boolean} create - * @param {function(?string):void} callback Returns error or null + * @param {(error: string | null) => void} callback Returns error or null * @return {XMLHttpRequest} */ function create_edit_collection(user, password, collection, create, callback) { @@ -394,7 +394,7 @@ function create_edit_collection(user, password, collection, create, callback) { * @param {string} user * @param {?string} password * @param {Collection} collection - * @param {function(?string):void} callback Returns error or null + * @param {(error: string | null) => void} callback Returns error or null * @return {XMLHttpRequest} */ export function create_collection(user, password, collection, callback) { @@ -405,7 +405,7 @@ export function create_collection(user, password, collection, callback) { * @param {string} user * @param {?string} password * @param {Collection} collection - * @param {function(?string):void} callback Returns error or null + * @param {(error: string | null) => void} callback Returns error or null * @return {XMLHttpRequest} */ export function edit_collection(user, password, collection, callback) { diff --git a/radicale/web/internal_data/js/api/sharing.js b/radicale/web/internal_data/js/api/sharing.js index e83f440b..f5841348 100644 --- a/radicale/web/internal_data/js/api/sharing.js +++ b/radicale/web/internal_data/js/api/sharing.js @@ -41,9 +41,9 @@ import { create_request, to_error_message } from "./common.js"; * @param {?string} password * @param {string} path * @param {object} body - * @param {function(string):void} on_success - * @param {?function():void} on_not_found - * @param {?function(string):void} on_error + * @param {(response: string) => void} on_success + * @param {(() => void) | null} on_not_found + * @param {((error: string) => void) | null} on_error * @returns {XMLHttpRequest} */ function call_sharing_api( @@ -92,7 +92,7 @@ function call_sharing_api( /** * @param {string} user * @param {?string} password - * @param {function(import("../api/sharing.js").ServerFeatures, ?string):void} callback + * @param {(features: import("../api/sharing.js").ServerFeatures, error: string | null) => void} callback */ export function discover_server_features(user, password, callback) { call_sharing_api( @@ -163,12 +163,12 @@ export const BDAY_CONFIG = Object.freeze([ ]); export class ShareConfig { + /** @type {Record} */ + _values = {}; /** * @param {ShareConfig|Record} [data] */ constructor(data = {}) { - /** @type {Record} */ - this._values = {}; let rawData = data; if (data instanceof ShareConfig) { rawData = data._values; @@ -310,8 +310,8 @@ export class Share { /** @type {number} */ this.TimestampUpdated = data.TimestampUpdated || 0; /** @type {Object} */ this.Properties = data.Properties || {}; /** @type {string} */ this.Conversion = data.Conversion || ""; - /** @type {ShareActions} */ this._Actions = new ShareActions(); - this.Actions = data.Actions || {}; + /** @type {ShareActions} */ + this._Actions = data.Actions instanceof ShareActions ? data.Actions : new ShareActions(data.Actions || {}); } /** @@ -351,7 +351,7 @@ export class Share { * @param {string} user * @param {?string} password * @param {?import("../models/collection.js").Collection} collection - * @param {function(Array, ?string):void} callback + * @param {(shares: Array, error: string | null) => void} callback */ export function reload_sharing_list(user, password, collection, callback) { let body = collection ? { PathMapped: decodeURIComponent(collection.href) } : {}; @@ -412,7 +412,7 @@ export function get_property_key(type, property) { * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function add_share_by_token( user, @@ -452,7 +452,7 @@ export function add_share_by_token( * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function add_share_by_map( user, @@ -494,7 +494,7 @@ export function add_share_by_map( * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function delete_share_by_token( user, @@ -526,7 +526,7 @@ export function delete_share_by_token( * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function delete_share_by_map( user, @@ -557,7 +557,7 @@ export function delete_share_by_map( * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function update_share_by_token( user, @@ -597,7 +597,7 @@ export function update_share_by_token( * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function update_share_by_map( user, @@ -641,7 +641,7 @@ export function update_share_by_map( * @param {string} user * @param {?string} password * @param {Share} share - * @param {function(?string):void} callback + * @param {(error: string | null) => void} callback */ export function update_incoming_share( user, diff --git a/radicale/web/internal_data/js/scenes/CollectionsScene.js b/radicale/web/internal_data/js/scenes/CollectionsScene.js index eee39a47..59a5cbf9 100644 --- a/radicale/web/internal_data/js/scenes/CollectionsScene.js +++ b/radicale/web/internal_data/js/scenes/CollectionsScene.js @@ -42,7 +42,7 @@ export class CollectionsScene { * @param {string} user * @param {?string} password * @param {Collection} principal_collection The princial collection - * @param {function(?string):void} onerror Called when an error occurs, before the + * @param {(error: string | null) => void} onerror Called when an error occurs, before the * scene is popped. */ constructor(user, password, principal_collection, onerror) { diff --git a/radicale/web/internal_data/js/scenes/ShareCollectionScene.js b/radicale/web/internal_data/js/scenes/ShareCollectionScene.js index 09683cf4..ddffc894 100644 --- a/radicale/web/internal_data/js/scenes/ShareCollectionScene.js +++ b/radicale/web/internal_data/js/scenes/ShareCollectionScene.js @@ -169,10 +169,10 @@ function update_share_list(user, password, collection, errorHandler) { * @param {import('../api/sharing.js').Share} share * @param {HTMLElement} template * @param {string} delete_label - * @param {function(string, string, import('../api/sharing.js').Share, function(?string):void):void} delete_action - * @param {function():void} [onDeleteSuccess] Optional extra callback after a successful delete. + * @param {(user: string, password: string | null, share: import('../api/sharing.js').Share, callback: (error: string | null) => void) => void} delete_action + * @param {(() => void) | null} [onDeleteSuccess] Optional extra callback after a successful delete. */ -function add_share_row_node(user, password, collection, share, template, delete_label, delete_action, onDeleteSuccess) { +function add_share_row_node(user, password, collection, share, template, delete_label, delete_action, onDeleteSuccess = null) { let pathortoken = share["PathOrToken"] || ""; let node = /** @type {HTMLElement} */ (template.cloneNode(true)); node.classList.remove("hidden"); diff --git a/radicale/web/internal_data/js/utils/collections_cache.js b/radicale/web/internal_data/js/utils/collections_cache.js index d0b6e7cc..fa65ab0b 100644 --- a/radicale/web/internal_data/js/utils/collections_cache.js +++ b/radicale/web/internal_data/js/utils/collections_cache.js @@ -31,7 +31,7 @@ class CollectionsCache { this.server_features = null; /** @type {?XMLHttpRequest} */ this.collections_req = null; /** @type {?XMLHttpRequest} */ this.shares_req = null; - /** @type {?Array<{ onerror: function(string):void, displayData: function(Array):void }>} */ + /** @type {Array<{ onerror: (error: string) => void, displayData: (shares: Array) => void }> | null} */ this._sharing_callbacks = null; } @@ -54,8 +54,8 @@ class CollectionsCache { * @param {string} user * @param {?string} password * @param {import("../models/collection.js").Collection} principal_collection - * @param {function(string):void} onerror - * @param {function(Array, Array, boolean):void} displayData + * @param {(error: string) => void} onerror + * @param {(collections: Array, shares: Array, loaded: boolean) => void} displayData */ getChildCollections(user, password, principal_collection, onerror, displayData) { if (this.child_collections !== null && this.incoming_shares !== null) { @@ -105,8 +105,8 @@ class CollectionsCache { /** * @param {string} user * @param {?string} password - * @param {function(string):void} onerror - * @param {function(Array):void} displayData + * @param {(error: string) => void} onerror + * @param {(shares: Array) => void} displayData */ getSharingList(user, password, onerror, displayData) { if (this.incoming_shares !== null) { @@ -140,8 +140,8 @@ class CollectionsCache { /** * @param {string} user * @param {?string} password - * @param {function(string):void} onerror - * @param {function(import("../api/sharing.js").ServerFeatures):void} displayData + * @param {(error: string) => void} onerror + * @param {(features: import("../api/sharing.js").ServerFeatures) => void} displayData */ getServerFeatures(user, password, onerror, displayData) { if (this.server_features !== null) { diff --git a/radicale/web/internal_data/js/utils/form_validator.js b/radicale/web/internal_data/js/utils/form_validator.js index 6a5d3a94..989215f4 100644 --- a/radicale/web/internal_data/js/utils/form_validator.js +++ b/radicale/web/internal_data/js/utils/form_validator.js @@ -30,13 +30,13 @@ export class FormValidator { */ constructor(error_handler) { this.error_handler = error_handler; - /** @type {Array<{field: HTMLInputElement, validation_method: function(): ?string}>} */ + /** @type {Array<{field: HTMLInputElement, validation_method: () => string | null}>} */ this.validation_methods = []; } /** * @param {HTMLInputElement} field - * @param {function(): ?string} validation_method + * @param {() => string | null} validation_method */ addValidator(field, validation_method) { this.validation_methods.push({ field, validation_method }); @@ -67,7 +67,7 @@ export class FormValidator { * Validates that the input is not empty. * @param {HTMLInputElement} input * @param {string} field_name - * @returns{function(): ?string} + * @returns {() => string | null} */ export function validate_non_empty(input, field_name) { return () => { @@ -83,7 +83,7 @@ export function validate_non_empty(input, field_name) { * @param {HTMLInputElement} input * @param {string} target * @param {string} field_name - * @returns {function(): ?string} + * @returns {() => string | null} */ export function validate_not_empty_or_equals(input, target, field_name) { return () => { @@ -102,7 +102,7 @@ export function validate_not_empty_or_equals(input, target, field_name) { * Validates that the input is a valid HREF. * @param {HTMLInputElement} input * @param {string} field_name - * @returns {function(): ?string} + * @returns {() => string | null} */ export function validate_href(input, field_name) { return () => { @@ -124,7 +124,7 @@ export function validate_href(input, field_name) { * Validates that the input is a valid color. * @param {HTMLInputElement} input * @param {string} field_name - * @returns {function(): ?string} + * @returns {() => string | null} */ export function validate_color(input, field_name) { return () => { @@ -144,7 +144,7 @@ export function validate_color(input, field_name) { * @param {HTMLInputElement} input * @param {string} target * @param {string} field_name - * @returns {function(): ?string} + * @returns {() => string | null} */ export function validate_equals(input, target, field_name) { return () => { @@ -160,7 +160,7 @@ export function validate_equals(input, target, field_name) { * Validates that at least one file is selected in a file input. * @param {HTMLInputElement} input * @param {string} field_name - * @returns {function(): ?string} + * @returns {() => string | null} */ export function validate_files(input, field_name) { return () => { @@ -175,7 +175,7 @@ export function validate_files(input, field_name) { * Validates that the input is a valid integer (if not empty). * @param {HTMLInputElement} input * @param {string} field_name - * @returns {function(): ?string} + * @returns {() => string | null} */ export function validate_integer(input, field_name) { return () => { diff --git a/radicale/web/internal_data/js/utils/misc.js b/radicale/web/internal_data/js/utils/misc.js index 4444b892..ed39c5f0 100644 --- a/radicale/web/internal_data/js/utils/misc.js +++ b/radicale/web/internal_data/js/utils/misc.js @@ -156,7 +156,7 @@ export function get_element(node, selector) { * * @param {string} str * @param {number} max - * @returns {str} + * @returns {string} */ export function trim_to_max(str, max) { if (str.length > max - 2) {