observablehq-file-attachments
Version:
Library to handle ObservableHQ's file attachments more flexibly, and to support virtualizing them.
188 lines • 6.63 kB
TypeScript
/**
* The various types used in the system.
*
* @module types
*/
import { AFile } from './AFile';
import { AFileSystem } from './AFileSystem';
import { CACHED_METADATA, DIRECTORY, FILE, METADATA, TAGS } from './symbols';
/**
* Options for requestion data from a [[VFile]]/
*/
export interface DataOptions {
/**
* For TSV and CSV, whether to return the rows as an array.
*/
array?: boolean;
/**
* For TSV and CSV, whether to attempt to convert the values to e.g. numbers
*/
typed?: boolean;
/**
* Whether data should be interconverted between text and binary based on utf8, rather than utf16.
*/
utf8?: boolean;
}
/**
* Objects that JSON.parse can produce.
*/
export declare type JsonObject = {
[k: string]: JsonObject;
} | string | number | null | Array<JsonObject>;
/**
* The known metadata types. Additional keys may be used, without typing.
*/
export declare type Metadata = {
name: string;
url?: string;
contentType?: string;
length?: number;
modificationDate?: Date;
eTag?: string;
} & {
[k in Exclude<string, 'modificationDate'>]: any | undefined;
};
/**
* The properties we add to track metadata.
*/
interface MetadataProps {
[CACHED_METADATA]?: Metadata;
[METADATA]?: Metadata;
}
/**
* The common portion of the ObservableHQ](https://observablehq.com)-supplied
* [FileAttachment](https://observablehq.com/@observablehq/file-attachments)
* interface.
*/
interface FileAttachmentBase {
json(opts?: DataOptions): Promise<JsonObject>;
blob(opts?: DataOptions): Promise<Blob>;
text(opts?: DataOptions): Promise<string>;
arrayBuffer(opts?: DataOptions): Promise<ArrayBuffer>;
csv(opts?: DataOptions): Promise<any>;
tsv(opts?: DataOptions): Promise<any>;
url(): Promise<string>;
name: string;
}
/**
* The ObservableHQ](https://observablehq.com)-supplied
* [FileAttachment](https://observablehq.com/@observablehq/file-attachments).
*/
export interface FileAttachment extends FileAttachmentBase, MetadataProps {
['content-type']?: string;
}
/**
* The interface for the [FileAttachment](https://observablehq.com/@observablehq/file-attachments)
* analogs we supply. These differ in that [[IAFile.url]] returns a `Promise<string>` rather
* than a `string`.
*/
export interface IAFile extends FileAttachmentBase, MetadataProps {
}
/**
* The methods of an interface that return a `Promise`.
*/
declare type AsyncMethodsOf<I, T extends keyof I = keyof I> = T extends string ? I[T] extends (...args: any) => Promise<any> ? T : never : never;
/**
* Split out the methods of [[IAFile]] that are async.
*/
declare type IAFileMethods = AsyncMethodsOf<IAFile>;
/**
* Split out everything in [[IAFile]] that is not an async method.
*/
declare type IAFileOther = Exclude<keyof IAFile, IAFileMethods>;
/**
* Extract the wrapped type from a promise.
*/
declare type UnwrapPromise<T> = T extends Promise<infer P> ? P : T;
/**
* Add another allowed return type to an async function.
*/
declare type AddReturnType<T extends (...args: any[]) => any, R> = (...args: Parameters<T>) => Promise<R | UnwrapPromise<ReturnType<T>>>;
/**
* The async methods of [[AFileAwait]] should return the same values as [[IAFile]] except each `Promise` can also
* resolve to `undefined`.
*/
export declare type IAFileAwait = {
[k in IAFileMethods]: AddReturnType<IAFile[k], undefined>;
} & {
[k in IAFileOther]: IAFile[k];
};
/**
* Version numbers/tags (labels) for files.
*/
export declare type Version = 'latest' | 'earliest' | string | number;
/**
* Version, including the special version '*'.
*/
export declare type DeleteVersion = Version | '*';
export interface Tags {
[k: string]: VFile;
}
/**
* File entries are either a [ObservableHQ](https://observablehq.com)-supplied
* [FileAttachment](https://observablehq.com/@observablehq/file-attachments), or an [[AFile]]
*/
export declare type VFile = AFile | FileAttachment;
/**
* An array of file versions. The array can be sparse if versions are
* deleted. File version indexes start at 1, but the arrays start at 0.
*
* So the tree:
* ```javascript
* const tree: Tree = {
* myFile: [file1, file2]
* };
* ```
* provides 2 versions of `/myFile`. Version 1 is _file1_ and version 2 is _file2_.
*/
export interface Files extends Array<VFile> {
[TAGS]?: Tags;
[METADATA]?: Metadata;
}
/**
* A directory tree, denoting the hierarchy of files. Javascript `Object`s are the directories.
* * Entries in the directory are named by keys.
* * If the value of an entry is another Javascript `Object`, it is a subdirectory.
* * If the value of an entry is an `Array`, it is a list of file versions. See [[Files]]
*/
export declare type Tree = {
/**
* Special symbol entry [[FILE]] provides a function that dynamically adds files on demand.
*/
[FILE]?: FileHandler;
/**
* Special symbol entry [[DIRECTORY]] provides a function that dynamically adds subdirectories on demand.
*/
[DIRECTORY]?: DirectoryHandler;
/**
* Regular entries
*/
[k: string]: Tree | Files;
};
/**
* A value, or a `Promise` of a value, where either synchronous or async code may be used.
* @typeParam T the wrapped type
*/
export declare type PromiseOr<T> = T | Promise<T>;
/**
* A handler to dynamically add files. It is called when a file is not found, and can add that file or more.
*
* The handler implementation will typically return an array of a single [[AFile]] instance (or zero if no file should be added).
*
* Advanced usages can return multiple versions in the array, or use {@link setVersion | setVersion()} to tag entries in the
* array.
*/
export declare type FileHandler = (filesystem: AFileSystem, path: string, name: string, version: Version, rest: string[], tree: Tree) => PromiseOr<Files>;
/**
* A handler to dynamically add subdirectories. It is called when a directory is not found, and can create
* a subdirectory heirarchy on demand. A [[DirectoryHandler]] that adds itself to the returned tree as a
* [[DIRECTORY]] handler can create an infinite on-demand hierarchy.
*/
export declare type DirectoryHandler = (filesystem: AFileSystem, path: string, name: string, rest: string[], tree: Tree) => PromiseOr<Tree>;
export interface Regenerable {
updateCount: number;
updated(v: this): void;
errored(e: Error): void;
}
export {};
//# sourceMappingURL=types.d.ts.map