Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf(t): improve TypeScript compilation speed (for adapters) #15

Merged
merged 2 commits into from
Dec 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
191 changes: 96 additions & 95 deletions packages/t/source/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import type {
} from "@wluwd/t-utils";
import type { Get, Simplify, ValueOf } from "type-fest";

type ConcatKeys<
export type ConcatKeys<
Previous extends string,
New extends string,
> = Previous extends "" ? New : `${Previous}.${New}`;

type PathsToBranches<
export type PathsToBranches<
Branch extends Record<string, unknown>,
KeysFound extends string = "",
> = Simplify<
Expand All @@ -27,25 +27,25 @@ type PathsToBranches<
> &
string;

type AnyFunction = (...args: any) => any;
export type AnyFunction = (...args: any) => any;

interface Factory<
export interface Factory<
Fn extends AnyFunction = AnyFunction,
Name extends string | undefined = string,
> {
factory: Fn;
name: Name;
}

interface Fn<
export interface Fn<
Fn extends AnyFunction = AnyFunction,
Name extends string | undefined = string,
> {
fn: Fn;
name: Name;
}

type LocaleSetter<AllowedLocales extends string = string> = (
export type LocaleSetter<AllowedLocales extends string = string> = (
locale: AllowedLocales,
) => void;

Expand Down Expand Up @@ -94,14 +94,14 @@ export interface CreateTranslationsFactoryOptions<
};
}

type AnyTranslator = (translation: string, data: any) => string;
export type AnyTranslator = (translation: string, data: any) => string;

type LocaleGetter<
export type LocaleGetter<
Locale extends string,
SignalLike extends boolean,
> = () => SignalLike extends true ? () => Locale : Locale;

type TranslationsPicker<
export type TranslationsPicker<
Translations extends AnyTranslations,
SignalLike extends boolean,
> = <Prefix extends PathsToBranches<Translations>>(
Expand All @@ -110,33 +110,33 @@ type TranslationsPicker<
? () => Get<Translations, Prefix>
: Get<Translations, Prefix>;

type TranslationsPickerAsync<Translations extends AnyTranslations> = <
export type TranslationsPickerAsync<Translations extends AnyTranslations> = <
Prefix extends PathsToBranches<Translations>,
>(
prefix: Prefix,
) => Promise<Get<Translations, Prefix>>;

type LocaleGetterHookBuilder<
export type LocaleGetterHookBuilder<
Options extends Fn<LocaleGetter<string, boolean>, string>,
> = {
[key in Options["name"]]: Options["fn"];
};

type LocaleGetterFunctionBuilder<
export type LocaleGetterFunctionBuilder<
Options extends Fn<LocaleGetter<string, false>, string> | undefined,
> = Options extends object
? {
[key in Options["name"]]: Options["fn"];
}
: object;

type TranslationsGetterHookBuilder<
export type TranslationsGetterHookBuilder<
Options extends Fn<TranslationsPicker<AnyTranslations, boolean>, string>,
> = {
[key in Options["name"]]: Options["fn"];
};

type TranslationsGetterFunctionBuilder<
export type TranslationsGetterFunctionBuilder<
Options extends
| Fn<TranslationsPickerAsync<AnyTranslations>, string>
| undefined,
Expand All @@ -146,7 +146,7 @@ type TranslationsGetterFunctionBuilder<
}
: object;

type CreateTranslationsInstance<
export type CreateTranslationsInstance<
Locale extends string,
Translations extends AnyTranslations,
Options extends {
Expand All @@ -169,7 +169,7 @@ type CreateTranslationsInstance<
t: Options["translator"];
};

type WithLazyInit<
export type WithLazyInit<
Lazy extends boolean,
Locale extends string,
Input extends object,
Expand All @@ -179,14 +179,75 @@ type WithLazyInit<
} & Input
: Input;

export const createTranslationsFactory =
<
SignalLike extends boolean,
LocaleGetterHookName extends string,
TranslationsGetterHookName extends string,
LocaleGetterFunctionName extends string | undefined = undefined,
TranslationsGetterFunctionName extends string | undefined = undefined,
>({
export type CreateTranslationsFactory = <
SignalLike extends boolean,
LocaleGetterHookName extends string,
TranslationsGetterHookName extends string,
LocaleGetterFunctionName extends string | undefined = undefined,
TranslationsGetterFunctionName extends string | undefined = undefined,
>(
options: CreateTranslationsFactoryOptions<
SignalLike,
LocaleGetterFunctionName,
LocaleGetterHookName,
TranslationsGetterFunctionName,
TranslationsGetterHookName
>,
) => <
Loaders extends Record<string, LazyLoader>,
Locale extends keyof Loaders & string,
Translations extends Awaited<ReturnType<ValueOf<Loaders>>>,
Translator extends AnyTranslator,
Lazy extends boolean = false,
>(
translationLoaders: Loaders,
options: {
cache?: Partial<Record<Locale, Translations>>;
localeFrom: LocaleNegotiators<keyof Loaders & string>;
translator: Translator;
},
lazy?: Lazy,
) => Simplify<
WithLazyInit<
Lazy,
Locale,
CreateTranslationsInstance<
Locale,
Translations,
{
locale: {
function: LocaleGetterFunctionName extends undefined
? undefined
: {
fn: LocaleGetter<Locale, false>;
name: LocaleGetterFunctionName;
};
hook: {
fn: LocaleGetter<Locale, SignalLike>;
name: LocaleGetterHookName;
};
setter: LocaleSetter<Locale>;
};
translations: {
function: TranslationsGetterFunctionName extends undefined
? undefined
: {
fn: TranslationsPickerAsync<Translations>;
name: TranslationsGetterFunctionName;
};
hook: {
fn: TranslationsPicker<Translations, SignalLike>;
name: TranslationsGetterHookName;
};
};
translator: Translator;
}
>
>
>;

export const createTranslationsFactory: CreateTranslationsFactory =
({
locale: {
fn: localeFn,
hook: { factory: localeHookFactory, name: localeHookName },
Expand All @@ -197,87 +258,27 @@ export const createTranslationsFactory =
fn: translationsFn,
hook: { factory: translationsHookFactory, name: translationsHookName },
},
}: CreateTranslationsFactoryOptions<
SignalLike,
LocaleGetterFunctionName,
LocaleGetterHookName,
TranslationsGetterFunctionName,
TranslationsGetterHookName
>) =>
<
Loaders extends Record<string, LazyLoader>,
Locale extends keyof Loaders & string,
Translations extends Awaited<ReturnType<ValueOf<Loaders>>>,
Translator extends AnyTranslator,
Lazy extends boolean = false,
>(
translationLoaders: Loaders,
{
cache: initialCache,
localeFrom: negotiators,
translator,
}: {
cache?: Partial<Record<Locale, Translations>>;
localeFrom: LocaleNegotiators<keyof Loaders & string>;
translator: Translator;
},
lazy?: Lazy,
): Simplify<
WithLazyInit<
Lazy,
Locale,
CreateTranslationsInstance<
Locale,
Translations,
{
locale: {
function: LocaleGetterFunctionName extends undefined
? undefined
: {
fn: LocaleGetter<Locale, false>;
name: LocaleGetterFunctionName;
};
hook: {
fn: LocaleGetter<Locale, SignalLike>;
name: LocaleGetterHookName;
};
setter: LocaleSetter<Locale>;
};
translations: {
function: TranslationsGetterFunctionName extends undefined
? undefined
: {
fn: TranslationsPickerAsync<Translations>;
name: TranslationsGetterFunctionName;
};
hook: {
fn: TranslationsPicker<Translations, SignalLike>;
name: TranslationsGetterHookName;
};
};
translator: Translator;
}
>
>
> => {
const initTranslator = (initNegotiators?: LocaleNegotiators<Locale>) => {
for (const [locale, loader] of Object.entries(translationLoaders) as [
Locale,
LazyLoader,
][]) {
}) =>
(
translationLoaders,
{ cache: initialCache, localeFrom: negotiators, translator },
lazy,
) => {
const initTranslator = (initNegotiators?: LocaleNegotiators<string>) => {
for (const [locale, loader] of Object.entries(translationLoaders)) {
loaders.set(locale, loader);
}

if (initialCache) {
for (const [locale, translations] of Object.entries(initialCache) as [
Locale,
Translations,
string,
AnyTranslations,
][]) {
globalCache.set(locale, translations);
}
}

const availableLocales = Object.keys(translationLoaders) as Locale[];
const availableLocales = Object.keys(translationLoaders);

const activeNegotiators =
initNegotiators !== undefined ? initNegotiators : negotiators;
Expand Down