Skip to content

Commit

Permalink
refactor: replace new decorators with old ones
Browse files Browse the repository at this point in the history
unfortunately, no bundler support TS 5.0 decorators, so we can't deploy them
  • Loading branch information
senyai committed May 8, 2024
1 parent 3622dfd commit 74c4851
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 44 deletions.
29 changes: 23 additions & 6 deletions src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,21 +140,38 @@ const enum Inline {
Repository = 1,
}

// function command(repository?: 1) {
// return (
// fn: CommandMethod,
// context: ClassMethodDecoratorContext<CommandCenter, CommandMethod> & {
// name: CommandKey;
// }
// ) => {
// if (repository) {
// fn = makeCommandWithRepository(fn);
// }
// register.push({
// id: `fossil.${context.name as CommandKey}`,
// method: fn,
// });
// return fn;
// };
// }

function command(repository?: 1) {
return (
fn: CommandMethod,
context: ClassMethodDecoratorContext<CommandCenter, CommandMethod> & {
name: CommandKey;
}
_target: any,
key: CommandKey,
descriptor: TypedPropertyDescriptor<CommandMethod>
) => {
let fn = descriptor.value!;
if (repository) {
fn = makeCommandWithRepository(fn);
}
register.push({
id: `fossil.${context.name as CommandKey}`,
id: `fossil.${key}`,
method: fn,
});
return fn;
};
}

Expand Down
153 changes: 115 additions & 38 deletions src/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,89 +6,166 @@

import { done } from './util';

export function memoize<Return extends {}>(
target: (this: Record<string, Return>) => Return,
context: ClassGetterDecoratorContext
// export function memoize<Return extends {}>(
// target: (this: Record<string, Return>) => Return,
// context: ClassGetterDecoratorContext
// ) {
// const memoizeKey = `$memoize$${context.name as string}`;
// return function (this: Record<string, Return>): Return {
// if (!this[memoizeKey]) {
// this[memoizeKey] = target.apply(this);
// }
// return this[memoizeKey];
// };
// }
export function memoize<Return>(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
const memoizeKey = `$memoize$${context.name as string}`;
return function (this: Record<string, Return>): Return {
const memoizeKey = `$memoize$${key}`;
const fn = descriptor.get!;
descriptor.get = function (this: Record<string, Return>): Return {
if (!this[memoizeKey]) {
this[memoizeKey] = target.apply(this);
this[memoizeKey] = fn.apply(this);
}
return this[memoizeKey];
};
}

/**
* Decorator to not allow multiple async calls
*/
export function throttle<Args extends any[], T>(
target: (
this: Record<string, Promise<T> | undefined>,
...args: Args
) => Promise<T>,
context: ClassMethodDecoratorContext
) {
const currentKey = `$thr$c$${String(context.name)}`; // $throttle$current$
const nextKey = `$thr$n$${String(context.name)}`; // $throttle$next$
// export function throttle<Args extends any[], T>(
// target: (
// this: Record<string, Promise<T> | undefined>,
// ...args: Args
// ) => Promise<T>,
// context: ClassMethodDecoratorContext
// ) {
// const currentKey = `$thr$c$${String(context.name)}`; // $throttle$current$
// const nextKey = `$thr$n$${String(context.name)}`; // $throttle$next$

// const trigger = function (
// this: Record<string, Promise<T> | undefined>,
// ...args: Args
// ): Promise<T> {
// if (this[nextKey]) {
// return this[nextKey]!;
// }

// if (this[currentKey]) {
// this[nextKey] = done(this[currentKey]!).then(() => {
// this[nextKey] = undefined;
// return trigger.apply(this, args);
// });

// return this[nextKey]!;
// }

// this[currentKey] = target.apply(this, args);

// const clear = () => (this[currentKey] = undefined);
// done(this[currentKey]!).then(clear, clear);

const trigger = function (
this: Record<string, Promise<T> | undefined>,
...args: Args
): Promise<T> {
// return this[currentKey]!;
// };

// return trigger;
// }
export function throttle(
target: any,
key: string,
descriptor: PropertyDescriptor
): void {
const currentKey = `$thr$c$${key}`; // $throttle$current$
const nextKey = `$thr$n$${key}`; // $throttle$next$
const fn = descriptor.value!;

descriptor.value = function (
this: Record<string, Promise<any> | undefined>,
...args: any
): Promise<any> {
if (this[nextKey]) {
return this[nextKey]!;
}

if (this[currentKey]) {
this[nextKey] = done(this[currentKey]!).then(() => {
this[nextKey] = undefined;
return trigger.apply(this, args);
return fn.apply(this, args);
});

return this[nextKey]!;
}

this[currentKey] = target.apply(this, args);
this[currentKey] = fn.apply(this, args);

const clear = () => (this[currentKey] = undefined);
done(this[currentKey]!).then(clear, clear);

return this[currentKey]!;
};

return trigger;
}

// Make sure asynchronous functions are called one after another.
type ThisPromise = Record<string, Promise<any>>;
// type ThisPromise = Record<string, Promise<any>>;

export function sequentialize<Args extends any[]>(
target: (this: ThisPromise, ...args: Args) => Promise<any>,
context: ClassMethodDecoratorContext
// export function sequentialize<Args extends any[]>(
// target: (this: ThisPromise, ...args: Args) => Promise<any>,
// context: ClassMethodDecoratorContext
// ) {
// const currentKey = `$s11e$${context.name as string}`; // sequentialize

// return function (this: ThisPromise, ...args: Args): Promise<any> {
// const currentPromise =
// (this[currentKey] as Promise<any>) || Promise.resolve(null);
// const run = async () => await target.apply(this, args);
// this[currentKey] = currentPromise.then(run, run);
// return this[currentKey];
// };
// }

export function sequentialize(
target: any,
key: string,
descriptor: PropertyDescriptor
) {
const currentKey = `$s11e$${context.name as string}`; // sequentialize
const currentKey = `$s11e$${key}`; // sequentialize
const fn = descriptor.value!;

return function (this: ThisPromise, ...args: Args): Promise<any> {
descriptor.value = function (this: any, ...args: any): Promise<any> {
const currentPromise =
(this[currentKey] as Promise<any>) || Promise.resolve(null);
const run = async () => await target.apply(this, args);
const run = async () => await fn.apply(this, args);
this[currentKey] = currentPromise.then(run, run);
return this[currentKey];
};
}

type ThisTimer = Record<string, ReturnType<typeof setTimeout>>;
// type ThisTimer = Record<string, ReturnType<typeof setTimeout>>;

// export function debounce(delay: number) {
// return function <Args extends any[]>(
// target: (this: ThisTimer, ...args: Args) => void,
// context: ClassMemberDecoratorContext
// ) {
// const timerKey = `$d6e$${String(context.name)}`; // debounce

// return function (this: ThisTimer, ...args: Args): void {
// clearTimeout(this[timerKey]);
// this[timerKey] = setTimeout(() => target.apply(this, args), delay);
// };
// };
// }
export function debounce(delay: number) {
return function <Args extends any[]>(
target: (this: ThisTimer, ...args: Args) => void,
context: ClassMemberDecoratorContext
) {
const timerKey = `$d6e$${String(context.name)}`; // debounce
return function (target: any, key: string, descriptor: PropertyDescriptor) {
const timerKey = `$d6e$${key}`; // debounce
const fn = descriptor.value!;

return function (this: ThisTimer, ...args: Args): void {
descriptor.value = function (this: any, ...args: any): void {
clearTimeout(this[timerKey]);
this[timerKey] = setTimeout(() => target.apply(this, args), delay);
this[timerKey] = setTimeout(() => fn.apply(this, args), delay);
};
};
}
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"removeComments": true,
"sourceMap": true,
"strictNullChecks": true,
"experimentalDecorators": true,
},
"include": [
"src/**/*",
Expand Down

0 comments on commit 74c4851

Please sign in to comment.