mirror of
https://github.com/flarum/framework.git
synced 2025-01-27 13:07:32 +08:00
Convert extend util to TypeScript (#2928)
* Allow using file extension in core compat imports Necessary for extend imports to have proper typings as we also have an unrelated extend/index.js file * Add .ts file extension to extend imports for typings * Fix changes to proxifyCompat regex breaking non-core import paths * Move utility types to global types Co-authored-by: David Wheatley <hi@davwheat.dev>
This commit is contained in:
parent
a07171cf1f
commit
1a695dee2c
18
framework/core/js/src/@types/global.d.ts
vendored
18
framework/core/js/src/@types/global.d.ts
vendored
|
@ -1,3 +1,21 @@
|
||||||
|
/**
|
||||||
|
* UTILITY TYPES
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type that returns an array of all keys of a provided object that are of
|
||||||
|
* of the provided type, or a subtype of the type.
|
||||||
|
*/
|
||||||
|
declare type KeysOfType<Type extends object, Match> = {
|
||||||
|
[Key in keyof Type]-?: Type[Key] extends Match ? Key : never;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type that matches one of the keys of an object that is of the provided
|
||||||
|
* type, or a subtype of it.
|
||||||
|
*/
|
||||||
|
declare type KeyOfType<Type extends object, Match> = KeysOfType<Type, Match>[keyof Type];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Please import `app` from a namespace instead of using it as a global variable.
|
* @deprecated Please import `app` from a namespace instead of using it as a global variable.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,7 +14,7 @@ import mapRoutes from './utils/mapRoutes';
|
||||||
import RequestError from './utils/RequestError';
|
import RequestError from './utils/RequestError';
|
||||||
import ScrollListener from './utils/ScrollListener';
|
import ScrollListener from './utils/ScrollListener';
|
||||||
import liveHumanTimes from './utils/liveHumanTimes';
|
import liveHumanTimes from './utils/liveHumanTimes';
|
||||||
import { extend } from './extend';
|
import { extend } from './extend.ts';
|
||||||
|
|
||||||
import Forum from './models/Forum';
|
import Forum from './models/Forum';
|
||||||
import User from './models/User';
|
import User from './models/User';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import * as extend from './extend';
|
import * as extend from './extend.ts';
|
||||||
import Session from './Session';
|
import Session from './Session';
|
||||||
import Store from './Store';
|
import Store from './Store';
|
||||||
import BasicEditorDriver from './utils/BasicEditorDriver';
|
import BasicEditorDriver from './utils/BasicEditorDriver';
|
||||||
|
|
|
@ -19,23 +19,27 @@
|
||||||
* // something that needs to be run on creation and update
|
* // something that needs to be run on creation and update
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @param {object} object The object that owns the method
|
* @param object The object that owns the method
|
||||||
* @param {string|string[]} methods The name or names of the method(s) to extend
|
* @param methods The name or names of the method(s) to extend
|
||||||
* @param {function} callback A callback which mutates the method's output
|
* @param callback A callback which mutates the method's output
|
||||||
*/
|
*/
|
||||||
export function extend(object, methods, callback) {
|
export function extend<T extends object, K extends KeyOfType<T, Function>>(
|
||||||
|
object: T,
|
||||||
|
methods: K | K[],
|
||||||
|
callback: (this: T, val: ReturnType<T[K]>, ...args: Parameters<T[K]>) => void
|
||||||
|
) {
|
||||||
const allMethods = Array.isArray(methods) ? methods : [methods];
|
const allMethods = Array.isArray(methods) ? methods : [methods];
|
||||||
|
|
||||||
allMethods.forEach((method) => {
|
allMethods.forEach((method: K) => {
|
||||||
const original = object[method];
|
const original: Function | undefined = object[method];
|
||||||
|
|
||||||
object[method] = function (...args) {
|
object[method] = function (this: T, ...args: Parameters<T[K]>) {
|
||||||
const value = original ? original.apply(this, args) : undefined;
|
const value = original ? original.apply(this, args) : undefined;
|
||||||
|
|
||||||
callback.apply(this, [value].concat(args));
|
callback.apply(this, [value, ...args]);
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
};
|
} as T[K];
|
||||||
|
|
||||||
Object.assign(object[method], original);
|
Object.assign(object[method], original);
|
||||||
});
|
});
|
||||||
|
@ -64,19 +68,23 @@ export function extend(object, methods, callback) {
|
||||||
* // something that needs to be run on creation and update
|
* // something that needs to be run on creation and update
|
||||||
* });
|
* });
|
||||||
*
|
*
|
||||||
* @param {object} object The object that owns the method
|
* @param object The object that owns the method
|
||||||
* @param {string|string[]} method The name or names of the method(s) to override
|
* @param methods The name or names of the method(s) to override
|
||||||
* @param {function} newMethod The method to replace it with
|
* @param newMethod The method to replace it with
|
||||||
*/
|
*/
|
||||||
export function override(object, methods, newMethod) {
|
export function override<T extends object, K extends KeyOfType<T, Function>>(
|
||||||
|
object: T,
|
||||||
|
methods: K | K[],
|
||||||
|
newMethod: (this: T, orig: T[K], ...args: Parameters<T[K]>) => void
|
||||||
|
) {
|
||||||
const allMethods = Array.isArray(methods) ? methods : [methods];
|
const allMethods = Array.isArray(methods) ? methods : [methods];
|
||||||
|
|
||||||
allMethods.forEach((method) => {
|
allMethods.forEach((method) => {
|
||||||
const original = object[method];
|
const original: Function = object[method];
|
||||||
|
|
||||||
object[method] = function (...args) {
|
object[method] = function (this: T, ...args: Parameters<T[K]>) {
|
||||||
return newMethod.apply(this, [original.bind(this)].concat(args));
|
return newMethod.apply(this, [original.bind(this), ...args]);
|
||||||
};
|
} as T[K];
|
||||||
|
|
||||||
Object.assign(object[method], original);
|
Object.assign(object[method], original);
|
||||||
});
|
});
|
|
@ -1,10 +1,12 @@
|
||||||
export default (compat: { [key: string]: any }, namespace: string) => {
|
export default function proxifyCompat(compat: Record<string, unknown>, namespace: string) {
|
||||||
// regex to replace common/ and NAMESPACE/ for core & core extensions
|
// regex to replace common/ and NAMESPACE/ for core & core extensions
|
||||||
|
// and remove .js, .ts and .tsx extensions
|
||||||
// e.g. admin/utils/extract --> utils/extract
|
// e.g. admin/utils/extract --> utils/extract
|
||||||
// e.g. tags/common/utils/sortTags --> tags/utils/sortTags
|
// e.g. tags/common/utils/sortTags --> tags/utils/sortTags
|
||||||
const regex = new RegExp(`(\\w+\\/)?(${namespace}|common)\\/`);
|
const regex = new RegExp(String.raw`(\w+\/)?(${namespace}|common)\/`);
|
||||||
|
const fileExt = /(\.js|\.tsx?)$/;
|
||||||
|
|
||||||
return new Proxy(compat, {
|
return new Proxy(compat, {
|
||||||
get: (obj, prop: string) => obj[prop] || obj[prop.replace(regex, '$1')],
|
get: (obj, prop: string) => obj[prop] || obj[prop.replace(regex, '$1').replace(fileExt, '')],
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user