World・読み取り
ローカルモデルの生成、取得、購読と操作可否。
生成と取得
World.create は新規作成、World.open は同じIDの復元。本人と保存先を明示します。接続・公開は行いません。
TypeScript · シグネチャ
connect(options: {
identity: Identity;
access: RelayAccess | (() => Promise<RelayAccess>);
} & ({ discovery: string; endpoints?: never } | {
endpoints: readonly string[]; discovery?: never;
})): Promise<Connection>;
World.create(options: {
identity: Identity;
name: string;
source?: WorldData;
storage?: Storage;
blobs?: Storage;
}): Promise<World>;
World.open(source: WorldData | Storage, options: {
identity: Identity;
storage?: Storage;
blobs?: Storage;
}): Promise<World>;World
read / watch は同期。watch は登録時に初回通知します。close の前に利用中のSessionから退出します。
TypeScript · シグネチャ
interface World {
readonly id: string;
readonly subject: string;
readonly scopes: Scopes;
readonly scenes: Scenes;
readonly definitions: Definitions;
readonly objects: Objects;
readonly assets: Assets;
readonly chat: Chat;
readonly invitations: WorldInvitations;
readonly keepers: Keepers;
read(): DeepReadonly<ModelInfo>;
read<K extends Collection>(query: ReadQuery<K>): ReadPage<Records[K]>;
watch(listener: (info: DeepReadonly<ModelInfo>) => void, options?: WatchOptions): () => void;
watch<K extends Collection>(query: ReadQuery<K>, listener: (page: ReadPage<Records[K]>) => void, options?: WatchOptions): () => void;
availability(operation: DeepReadonly<WorldOperation>): Availability;
rename(name: string): Promise<ChangeResult>;
close(): Promise<void>;
}read / watch
limit は既定100・最大500。next を同じ条件の cursor に渡します。取得済みで閲覧可能なデータだけが対象です。related は参照先のレコードで、ファイル実体は含みません。
TypeScript · シグネチャ
interface DeepReadonlyArray<T> extends ReadonlyArray<DeepReadonly<T>> {}
type DeepReadonly<T> = T extends readonly unknown[]
? number extends T['length'] ? DeepReadonlyArray<T[number]> : { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T extends object ? { readonly [K in keyof T]: DeepReadonly<T[K]> } : T;
interface ModelInfo {
name: string;
owner: string;
revision: number;
rootScope: string;
rootScene: string;
writable: boolean;
complete: boolean;
}
interface Records {
scopes: Scope;
scenes: Scene;
definitions: Definition;
objects: WorldObject;
assets: Asset;
messages: Message;
keepers: KeeperRecord;
invitations: InvitationRecord;
}
type Collection = keyof Records;
interface Bounds {
left: number;
top: number;
right: number;
bottom: number;
}
type ReadQuery<K extends Collection = Collection> = K extends Collection
? {
from: K;
id?: string;
limit?: number;
cursor?: string;
} & (K extends 'objects'
? { scope?: string; scene?: string; bounds?: Bounds }
: K extends 'scenes' | 'definitions' | 'assets' | 'messages'
? { scope?: string }
: {})
: never;
interface RelatedRecords {
readonly scopes: Readonly<Record<string, DeepReadonly<Scope>>>;
readonly scenes: Readonly<Record<string, DeepReadonly<Scene>>>;
readonly definitions: Readonly<Record<string, DeepReadonly<Definition>>>;
readonly assets: Readonly<Record<string, DeepReadonly<Asset>>>;
}
interface ReadPage<T> {
readonly items: readonly DeepReadonly<T>[];
readonly related: RelatedRecords;
readonly total: number;
readonly next: string | null;
readonly revision: number;
}操作可否
allowed と reason で現在の可否を判別します。成功を予約するものではなく、実行時のエラー処理も必要です。
TypeScript · シグネチャ
type WorldOperation =
| { operation: 'rename' | 'scopes.create' | 'save' | 'export' | 'merge' | 'close' }
| { operation: 'scopes.remove' | 'scenes.configure' | 'scenes.remove'
| 'objects.move' | 'objects.edit' | 'objects.remove'
| 'assets.read' | 'assets.remove' | 'chat.remove' | 'invitations.revoke'; id: string }
| { operation: 'scenes.create' | 'assets.import' | 'chat.send'; scope: string }
| { operation: 'definitions.set'; scope: string; id?: string }
| { operation: 'objects.place'; definition: string; placement: Placement }
| { operation: 'invitations.create'; actions: WorldGrant['actions'] }
| { operation: 'keepers.appoint'; subject: string };
type Availability =
| { allowed: true; reason: null }
| { allowed: false; reason:
'closed' | 'missing' | 'forbidden' | 'connecting'
| 'writer-absent' | 'incomplete' | 'in-use' };
const moving = world.availability({ operation: 'objects.move', id: objectId });
const placing = world.availability({ operation: 'objects.place', definition: definitionId, placement });編集結果
変更結果は revision と accepted(local / shared)。新規作成は id も返します。
TypeScript · シグネチャ
interface ChangeResult {
revision: number;
accepted: 'local' | 'shared';
}
type Created = ChangeResult & { id: string };