@omnicajs/vue-remote
Version:
Proxy renderer for Vue.js based on @remote-ui
331 lines (286 loc) • 9.57 kB
text/typescript
import type {
Id,
SerializedComment,
SerializedComponent,
SerializedFragment,
SerializedText,
KIND_ROOT,
} from '@/dom/common/tree'
import type {
SchemaType,
TypeOf,
PropertiesOf,
MethodsOf,
ChildrenOf,
UnknownType,
} from '@/dom/remote/schema'
import type {
IfAllKeysOptional,
Unknown,
UnknownMethods,
} from '~types/scaffolding'
import {
KIND_COMMENT,
KIND_COMPONENT,
KIND_FRAGMENT,
KIND_TEXT,
} from '@/dom/common/tree'
export interface RemoteNode {
readonly id: Id;
}
export interface RemoteRoot<
Supports extends SchemaType<string, Unknown, UnknownMethods, UnknownType> = SchemaType<string, Unknown, UnknownMethods, UnknownType>
> extends RemoteNode {
readonly kind: typeof KIND_ROOT
readonly options: RemoteRootOptions<Supports>
readonly children: ReadonlyArray<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<Supports, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
>
append (
...children: Array<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<Supports, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| string
>
): void | Promise<void>;
insertBefore (
child:
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<Supports, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>,
before?:
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<Supports, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| null,
): void | Promise<void>;
replace (
...children: Array<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<Supports, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| string
>
): void | Promise<void>;
removeChild (
child:
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<Supports, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
): void | Promise<void>;
createComment (text?: string): RemoteComment<RemoteRoot<Supports>>;
createComponent<Type extends Supports>(
type: Type | RemoteComponentDescriptor<Type>,
...rest: IfAllKeysOptional<
PropertiesOf<Type>,
| [(PropertiesOf<Type> | null)?, ...Array<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| string
>]
| [(PropertiesOf<Type> | null)?, Array<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| string
>?],
| [PropertiesOf<Type>, ...Array<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| string
>]
| [PropertiesOf<Type>, Array<
| RemoteComment<RemoteRoot<Supports>>
| RemoteComponent<ChildrenOf<Supports>, RemoteRoot<Supports>>
| RemoteText<RemoteRoot<Supports>>
| string
>?]
>
): RemoteComponent<Type, RemoteRoot<Supports>>;
createFragment (): RemoteFragment<RemoteRoot<Supports>>;
createText (text?: string): RemoteText<RemoteRoot<Supports>>;
mount (): Promise<void>;
}
export interface RemoteRootOptions<
Supports extends RemoteComponentOption = RemoteComponentOption
> {
readonly strict?: boolean;
readonly components?: ReadonlyArray<Supports>;
}
export interface RemoteComment<Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
readonly kind: typeof KIND_COMMENT;
readonly root: Root;
readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly text: string;
update (text: string): void | Promise<void>;
remove (): void | Promise<void>;
serialize (): SerializedComment;
print (): string;
}
export type RemoteComponentOption<
Type extends SupportedBy<RemoteRoot> = SupportedBy<RemoteRoot>
> = Type | RemoteComponentDescriptor<Type>
export type SchemaOf<D> = D extends RemoteComponentDescriptor<infer S1>
? S1
: D extends RemoteComponentOption<infer S2>
? S2
: never
export interface RemoteComponentDescriptor<
Type extends SupportedBy<RemoteRoot>
> {
type: Type;
hasProperty (name: string | keyof PropertiesOf<Type>): name is keyof PropertiesOf<Type>;
hasMethod (name: string | keyof MethodsOf<Type>): name is keyof MethodsOf<Type>;
supports (name: string): boolean;
}
export type SupportedBy<Root> = Root extends RemoteRoot<infer S>
? S
: never
export interface RemoteComponent<
Type extends SupportedBy<RemoteRoot>,
Root extends RemoteRoot = RemoteRoot,
> extends RemoteNode {
readonly kind: typeof KIND_COMPONENT;
readonly type: TypeOf<Type>;
readonly root: Root;
readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly properties: PropertiesOf<Type>;
readonly children: ReadonlyArray<
| RemoteComment<Root>
| RemoteComponent<ChildrenOf<Type>, Root>
| RemoteText<Root>
>;
invoke (method: string, ...payload: unknown[]): Promise<unknown>;
updateProperties (properties: Partial<PropertiesOf<Type>>): void | Promise<void>;
append (...children: Array<
| RemoteComment<Root>
| RemoteComponent<ChildrenOf<Type>, Root>
| RemoteText<Root>
| string
>): void | Promise<void>;
insertBefore (
child:
| RemoteComment<Root>
| RemoteComponent<ChildrenOf<Type>, Root>
| RemoteText<Root>,
before?:
| RemoteComment<Root>
| RemoteComponent<ChildrenOf<Type>, Root>
| RemoteText<Root>
| null
): void | Promise<void>;
replace (...children: Array<
| RemoteComment<Root>
| RemoteComponent<ChildrenOf<Type>, Root>
| RemoteText<Root>
| string
>): void | Promise<void>;
removeChild (
child:
| RemoteComment<Root>
| RemoteComponent<ChildrenOf<Type>, Root>
| RemoteText<Root>
): void | Promise<void>;
remove (): void | Promise<void>;
serialize (): SerializedComponent<PropertiesOf<Type>>;
print (): string;
}
export interface RemoteFragment<Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
readonly kind: typeof KIND_FRAGMENT;
readonly root: Root;
readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly children: ReadonlyArray<
| RemoteComment<Root>
| RemoteComponent<SupportedBy<Root>, Root>
| RemoteText<Root>
>;
append (
...children: Array<
| RemoteComment<Root>
| RemoteComponent<SupportedBy<Root>, Root>
| RemoteText<Root>
| string
>
): void | Promise<void>;
insertBefore(
child:
| RemoteComment<Root>
| RemoteComponent<SupportedBy<Root>, Root>
| RemoteText<Root>,
before?:
| RemoteComment<Root>
| RemoteComponent<SupportedBy<Root>, Root>
| RemoteText<Root>
| null,
): void | Promise<void>;
replace (
...children: Array<
| RemoteComment<Root>
| RemoteComponent<SupportedBy<Root>, Root>
| RemoteText<Root>
| string
>
): void | Promise<void>;
removeChild (
child:
| RemoteComment<Root>
| RemoteComponent<SupportedBy<Root>, Root>
| RemoteText<Root>,
): void | Promise<void>;
serialize (): SerializedFragment;
}
export interface RemoteText<Root extends RemoteRoot = RemoteRoot> extends RemoteNode {
readonly kind: typeof KIND_TEXT;
readonly root: Root;
readonly progenitor: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly parent: RemoteComponent<SupportedBy<Root>, Root> | Root | null;
readonly text: string;
update (text: string): void | Promise<void>;
serialize (): SerializedText;
remove (): void | Promise<void>;
print (): string;
}
export type UnknownComponent = RemoteComponent<UnknownType>
export type UnknownChild = RemoteComment | RemoteComponent<UnknownType> | RemoteText
export type UnknownNode = UnknownChild | RemoteFragment
export type UnknownParent =
| RemoteRoot
| RemoteComponent<SchemaType<string, Unknown, UnknownMethods, UnknownType>>
| RemoteFragment
export function isRemoteComment<
Root extends RemoteRoot = RemoteRoot,
>(value: unknown): value is RemoteComment<Root> {
return value != null && (value as RemoteComment<Root>).kind === KIND_COMMENT
}
export function isRemoteComponent<
Type extends UnknownType = UnknownType,
Root extends RemoteRoot = RemoteRoot,
>(value: unknown): value is RemoteComponent<Type, Root> {
return value != null && (value as RemoteComponent<Type, Root>).kind === KIND_COMPONENT
}
export function isRemoteFragment<
Root extends RemoteRoot = RemoteRoot,
>(value: unknown): value is RemoteFragment<Root> {
return value != null && (value as RemoteFragment<Root>).kind === KIND_FRAGMENT
}
export function isRemoteText<
Root extends RemoteRoot = RemoteRoot,
>(value: unknown): value is RemoteText<Root> {
return value != null && (value as RemoteText<Root>).kind === KIND_TEXT
}
export const normalizeChild = (
child: UnknownChild | string,
root: RemoteRoot
): UnknownChild => typeof child === 'string' ? root.createText(child) : child
export const normalizeChildren = (
children: Array<UnknownChild | string>,
root: RemoteRoot
) => children.map((child) => normalizeChild(child, root))