Skip to content

Commit

Permalink
docs: improve documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
pikax committed Mar 15, 2020
1 parent 0df86dc commit e9c9445
Show file tree
Hide file tree
Showing 5 changed files with 226 additions and 39 deletions.
66 changes: 50 additions & 16 deletions docs/api/core.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ export interface ArrayPaginationResult<T extends Array<any>> extends PaginationR
result: Readonly<Ref<T>>;
}

// Warning: (ae-forgotten-export) The symbol "i18nDefinition" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "i18nResult" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
// @public
export function buildI18n<T extends i18nDefinition<TMessage>, TMessage extends Record<keyof T["messages"], i18n | (() => Promise<any>)>>(definition: T): i18nResult<keyof T["messages"], T["messages"][T["locale"]]>;

// @public (undocumented)
Expand Down Expand Up @@ -49,12 +46,45 @@ export interface FormatObject {
// @public (undocumented)
export type FormatValue = RefTyped<object> | RefTyped<string> | RefTyped<number>;

// Warning: (ae-forgotten-export) The symbol "i18nMessageValue" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
// @public
export interface i18n extends Record<string, i18nMessageValue> {
}

// @public
export interface i18nDefinition<TMessage> {
fallback?: keyof TMessage;
locale: keyof TMessage;
messages: {
[K in keyof TMessage]: i18n | (() => Promise<i18n>);
};
notFoundFallback?: boolean;
resolve?: i18nResolver;
}

// @public
export type i18nLocale<T> = {
[K in keyof T]: i18nMessage<T[K]>;
};

// @public
export type i18nMessage<T> = T extends Ref<string> ? string : T extends () => Promise<infer P> ? i18nLocale<P> : T extends (...args: infer TArgs) => RefTyped<string> ? (...args: TArgs) => string : T extends object ? i18nLocale<T> : T extends Ref<infer V> ? V : T;

// @public
export type i18nMessageValue = i18nLocale<any> | RefTyped<string>;

// @public
export type i18nResolver = (i18n: i18n, path: Readonly<RefTyped<string>>, args: RefTyped<FormatObject> | Array<FormatValue> | undefined) => RefTyped<string>;

// @public
export interface i18nResult<TLocales, TMessages extends any = i18n> {
$t(path: string, args?: object | Array<object>): Readonly<Ref<string>>;
addLocale(locale: string, messages: TMessages): void;
i18n: Readonly<Ref<Readonly<TMessages>>>;
locale: Ref<TLocales>;
locales: Readonly<Ref<Readonly<Array<TLocales>>>>;
removeLocale(locale: TLocales): void;
}

// @public (undocumented)
export const isArray: (arg: any) => arg is any[];

Expand Down Expand Up @@ -179,7 +209,7 @@ export interface RetryReturnNoFactory extends RetryReturn {
exec<T>(fn: () => T): T;
}

// @public (undocumented)
// @public
export function setI18n<T extends i18nDefinition<TMessage>, TMessage extends Record<keyof T["messages"], i18n | (() => Promise<any>)>>(definition: T): i18nResult<keyof T["messages"], T["messages"][T["locale"]]>;

// @public (undocumented)
Expand Down Expand Up @@ -227,20 +257,20 @@ export function useDateNow(options?: NowOptions): {
// @public
export function useDebounce<T extends Procedure>(handler: T, wait?: number, options?: Options): T;

// @public (undocumented)
// @public
export function useFormat(format: Readonly<RefTyped<string>>, obj?: RefTyped<FormatObject>): Readonly<Ref<string>>;

// @public (undocumented)
// @public
export function useFormat(format: Readonly<RefTyped<string>>, ...args: Array<FormatValue>): Readonly<Ref<string>>;

// @public (undocumented)
export function useFormat(format: Readonly<RefTyped<string>>, obj?: RefTyped<FormatObject> | Array<FormatValue>): Readonly<Ref<string>>;

// @public (undocumented)
// @public
export function useI18n<T extends i18nDefinition<TMessage>, TMessage extends Record<keyof T["messages"], i18n | (() => Promise<any>)>>(definition: T): i18nResult<keyof T["messages"], T["messages"][T["locale"]]>;

// @public (undocumented)
export function useI18n<T = i18n>(): i18nResult<string[], T> | void;
// @public
export function useI18n<T = i18n>(): i18nResult<string[], T>;

// @public
export function useNow(options?: NowOptions & UseNowOptions): {
Expand All @@ -256,11 +286,15 @@ export interface UseNowOptions {
// @public (undocumented)
export function usePagination(options: PaginationOptions): PaginationResult;

// @public (undocumented)
export function usePath<T = any>(source: RefTyped<object>, path: RefTyped<string>, separator?: string, notFoundReturn?: UsePathNotFoundReturn): Ref<Readonly<T>>;
// @public
export function usePath<T = any, TSource = any>(source: RefTyped<TSource>, path: RefTyped<string>, separator?: string, notFoundReturn?: UsePathNotFoundReturn<TSource>): Ref<Readonly<T>>;

// @public (undocumented)
export type UsePathNotFoundReturn = (path: string, source: any, fullPath: string, originalSource: any) => any;
export type UsePathNotFoundReturn<TSource> = (
path: string,
source: any,
fullPath: string,
originalSource: TSource) => any;

// @public
export function usePerformanceNow(options?: NowOptions): {
Expand Down
19 changes: 19 additions & 0 deletions packages/core/src/format/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,30 @@ export interface FormatObject {
[id: string]: FormatValue;
}

/**
* format string based on object: [format](https://pikax.me/vue-composable/composable/format/format)
* * @example
* ```ts
* useFormat('Today is {{ day }}', { day: new Date().getDay() })
* ```
* @param format - string format
* @param obj - object to get values from
*/
export function useFormat(
format: Readonly<RefTyped<string>>,
obj?: RefTyped<FormatObject>
): Readonly<Ref<string>>;

/**
* format string based on object: [format](https://pikax.me/vue-composable/composable/format/format)
* * @example
* ```ts
* useFormat('Today is {{ 0 }}', new Date().getDay())
* ```
* @param format - string format
* @param args - array based format
*
*/
export function useFormat(
format: Readonly<RefTyped<string>>,
...args: Array<FormatValue>
Expand Down
31 changes: 25 additions & 6 deletions packages/core/src/format/path.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
import { RefTyped, unwrap, isObject, NO_OP } from "../utils";
import { computed, Ref } from "@vue/composition-api";

export type UsePathNotFoundReturn = (
export type UsePathNotFoundReturn<TSource> = (
/**
* Current path
*/
path: string,
/**
* last source found
*/
source: any,
/**
* Full path requested
*/
fullPath: string,
originalSource: any
/**
* Original source
*/
originalSource: TSource
) => any;

export function usePath<T = any>(
source: RefTyped<object>,
/**
* Retrieve object value based on string path
* @param source - Source object to retrieve path
* @param path - string path to value
* @param separator - path separator, default '.'
* @param notFoundReturn - not found handler
*/
export function usePath<T = any, TSource = any>(
source: RefTyped<TSource>,
path: RefTyped<string>,
separator: string = ".",
notFoundReturn: UsePathNotFoundReturn = NO_OP
notFoundReturn: UsePathNotFoundReturn<TSource> = NO_OP
): Ref<Readonly<T>> {
return computed(() => {
const s = unwrap(source);
Expand All @@ -25,7 +44,7 @@ export function usePath<T = any>(
}

const fragments = p.split(separator);
let c = s;
let c: Record<string, any> = s;
for (let i = 0; i < fragments.length; i++) {
let fragmentPath = fragments[i];
let index: any = -1;
Expand Down
113 changes: 98 additions & 15 deletions packages/core/src/i18n/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,36 @@ import {
} from "../utils";
import { usePath, useFormat, FormatObject, FormatValue } from "../format";

// Symbol used to inject/provide the i18n values
const I18n_ACCESS_SYMBOL: InjectionKey<i18nResult<
string[],
string
>> = /*#__PURE__*/ Symbol((__DEV__ && "I18n") || ``);

type i18nMessageValue = i18nLocale<any> | RefTyped<string>;

/**
* i18n key and message value
*/
export type i18nMessageValue = i18nLocale<any> | RefTyped<string>;

/**
* i18n interface
* * check [typescript documentation](https://pikax.me/vue-composable/composable/i18n/i18n.html#global-definition)
* * @example
* ```ts
* // types.d.ts
* declare module "@vue-composable/core" {
* interface i18n {
* hello: string;
* }
* }
* ```
*/
export interface i18n extends Record<string, i18nMessageValue> {}

type i18nMessage<T> = T extends Ref<string>
/**
* Extracts i18n configuration type to the correct output
*/
export type i18nMessage<T> = T extends Ref<string>
? string
: T extends () => Promise<infer P>
? i18nLocale<P>
Expand All @@ -37,28 +57,48 @@ type i18nMessage<T> = T extends Ref<string>
: T extends Ref<infer V>
? V
: T;

type i18nLocale<T> = {
/**
* Locale based key/value dictionary
*/
export type i18nLocale<T> = {
[K in keyof T]: i18nMessage<T[K]>;
};
type i18nResolver = (
/**
* i18n Message value resolver */
export type i18nResolver = (
i18n: i18n,
path: Readonly<RefTyped<string>>,
args: RefTyped<FormatObject> | Array<FormatValue> | undefined
) => RefTyped<string>;

interface i18nDefinition<TMessage> {
/**
* i18n definition
*/
export interface i18nDefinition<TMessage> {
/**
* Default and current locale
* If locale and fallback are different, you may need to wait until next tick to
* get the correct i18n values
*/
locale: keyof TMessage;

/**
* Fallback locale, it will be used if the current locale doesn't
* have value for the key.
* Only used if `notFoundFallback !== false`
*/
fallback?: keyof TMessage;

/**
* Object containing locale and messages for locale
*/
messages: { [K in keyof TMessage]: i18n | (() => Promise<i18n>) };

/**
* Resolves the translation for i18n
* @param i18n i18n messages
* @param path desired path
* @param args arguments
* @param i18n - i18n messages
* @param path - desired path
* @param args - arguments
*/
resolve?: i18nResolver;

Expand All @@ -69,30 +109,69 @@ interface i18nDefinition<TMessage> {
notFoundFallback?: boolean;
}

interface i18nResult<TLocales, TMessages extends any = i18n> {
/**
* i18n Object
*/
export interface i18nResult<TLocales, TMessages extends any = i18n> {
/**
* Current locale
* You can assign a new locale
*/
locale: Ref<TLocales>;

locales: Ref<Array<TLocales>>;
/**
* @readonly List of available locales
*/
locales: Readonly<Ref<Readonly<Array<TLocales>>>>;

/**
* @readonly Object based locale messages
*/
i18n: Readonly<Ref<Readonly<TMessages>>>;

/**
* Function based message locale with support to format and arguments
* Inspired by [vue-i18n](https://github.com/kazupon/vue-i18n)
* @param path - Current message path
* @param args - Argument passed to format value
*/
$t(path: string, args?: object | Array<object>): Readonly<Ref<string>>;

/**
* Adds a new locale to the locale array, it also overrides existing locale
* @param locale - Locale key
* @param messages - Object based messages
*/
addLocale(locale: string, messages: TMessages): void;
/**
* Removes locale from the locale list
* @param locale - Locale key
*/
removeLocale(locale: TLocales): void;
}

/**
* Calls setI18n
* @param definition - Locale definition
*/
export function useI18n<
T extends i18nDefinition<TMessage>,
TMessage extends Record<keyof T["messages"], i18n | (() => Promise<any>)>
>(definition: T): i18nResult<keyof T["messages"], T["messages"][T["locale"]]>;
export function useI18n<T = i18n>(): i18nResult<string[], T> | void;
/**
* Inject i18n
*/
export function useI18n<T = i18n>(): i18nResult<string[], T>;
export function useI18n(definition?: any): any {
if (definition) {
return buildI18n(definition);
return setI18n(definition);
} else return inject(I18n_ACCESS_SYMBOL);
}

/**
* Builds i18n object based on the definition
* @param definition - i18n definition
*/
export function buildI18n<
T extends i18nDefinition<TMessage>,
TMessage extends Record<keyof T["messages"], i18n | (() => Promise<any>)>
Expand Down Expand Up @@ -150,7 +229,7 @@ export function buildI18n<
fallback.value = {};
}

watch(
watch(
[locale, fallback],
async ([l, fb]: [keyof TMessage, i18n | undefined]) => {
if (l === definition.fallback && shouldFallback) {
Expand Down Expand Up @@ -213,6 +292,10 @@ export function buildI18n<
};
}

/**
* Build and provide i18n definition
* @param definition - I18N definition
*/
export function setI18n<
T extends i18nDefinition<TMessage>,
TMessage extends Record<keyof T["messages"], i18n | (() => Promise<any>)>
Expand Down

0 comments on commit e9c9445

Please sign in to comment.