/// import { ReadStream } from 'fs'; import { Stream, Readable } from 'stream'; /** * The content id identifies content objects in storage. The PHP implementation of H5P * uses integers for this, we try to use strings. This might change in the future, if it * turns out that the H5P editor client doesn't work with string ids. */ export declare type ContentId = string; /** * Permissions give rights to users to do certain actions with a piece of content. */ export declare enum Permission { Delete = 0, Download = 1, Edit = 2, Embed = 3, List = 4, View = 5 } /** * A response that is sent back to an AJAX call. */ export interface IAjaxResponse { /** * The actual payload. Only to be filled in if the request was successful. */ data?: any; /** * Better description of the error and possibly also which action to take. Only to be filled out if success is false. */ details?: string; /** * An machine readable error code that the client should be able to interpret. Only to be filled out if success is false. */ errorCode?: string; /** * The HTTP status code of the request. (e.g. 200 or 404) */ httpStatusCode?: number; /** * The localized error message. Only to be filled out if success is false. */ message?: string; /** * True if the request was successful, false if something went wrong (errorCode and message should be filled in then). */ success: boolean; } /** * Assets are files required by a library to work. These include JavaScript, CSS files and translations. */ export interface IAssets { scripts: string[]; styles: string[]; translations: object; } /** * Represents the information needed to identify an installed library. This information is also called * ubername when it's represented as a string like this: H5P.Example-1.0 * Even though H5P libraries generally also have a patch version (1.0.0), the patch version is not * needed to identify an installed library as there can only be one installed patch version of a library * at a time. (However, It is possible to install the same library in different major or minor versions. * That's why the machine name is not enough to identify it.) */ export interface ILibraryName { /** * The name used to identify the library (e.g. H5P.Example) */ machineName: string; /** * The major version of the library (e.g. 1) */ majorVersion: number; /** * The minor version of the library (e.g. 0) */ minorVersion: number; } export interface IFullLibraryName extends ILibraryName { patchVersion: number; } export interface ILibraryInstallResult { newVersion?: IFullLibraryName; oldVersion?: IFullLibraryName; type: 'new' | 'patch' | 'none'; } /** * This is an author inside content metadata. */ export interface IContentAuthor { name?: string; role?: string; } /** * This is a change inside content metadata. */ export interface IContentChange { author?: string; date?: string; log?: string; } /** * This is the structure of the object received by the editor client when saving content. * It is also used when creating h5p.json files for .h5p packages. */ export interface IContentMetadata { author?: string; authorComments?: string; authors?: IContentAuthor[]; changes?: IContentChange[]; contentType?: string; dynamicDependencies?: ILibraryName[]; editorDependencies?: ILibraryName[]; embedTypes: ('iframe' | 'div')[]; h?: string; language: string; license?: string; licenseExtras?: string; licenseVersion?: string; mainLibrary: string; metaDescription?: string; metaKeywords?: string; /** * A flat list of all dependencies required for the content to be displayed. * Note that this list is a flat representation of the full dependency tree * that is created by looking up all dependencies of the main library. */ preloadedDependencies: ILibraryName[]; source?: string; title: string; w?: string; yearsFrom?: string; yearsTo?: string; } /** * The integration object is used to pass information to the H5P JavaScript * client running in the browser about certain settings and values of the * server. */ export interface IIntegration { ajax: { /** * The Ajax endpoint called when the user state has changed * Example: /h5p-ajax/content-user-data/:contentId/:dataType/:subContentId?token=XYZ * You can use these placeholders: * :contentId * :dataType * :subContentId * The H5P client will replace them with the actual values. */ contentUserData: string; /** * An Ajax endpoint called when the user has finished the content. * Example: /h5p-ajax/set-finished.json?token=XYZ * Only called when postUserStatistics is set to true. */ setFinished: string; }; ajaxPath: string; /** * The base URL, e.g. https://example.org */ baseUrl?: string; /** * The key must be of the form "cid-XXX", where XXX is the id of the content */ contents?: { [key: string]: { /** * Can be used to override the URL used for getting content files. * It must be a URL to which the actual filenames can be appended. * Do not end it with a slash! * If it is a relative URL it will be appended to the hostname that * is in use (this is done in the H5P client). * If it is an absolute URL it will be used directly. */ contentUrl?: string; contentUserData?: { /** * The state as a serialized JSON object. */ state: string; }[]; displayOptions: { copy: boolean; copyright: boolean; embed: boolean; export: boolean; frame: boolean; icon: boolean; }; /** * The full embed code ( with absolute URLs). * Example: " */ embedCode?: string; /** * The download URL (absolute URL). */ exportUrl?: string; fullScreen: '0' | '1'; jsonContent: string; /** * The ubername with whitespace as separator. */ library: string; mainId?: string; metadata?: { defaultLanguage: string; license: string; title: string; }; /** * The parameters. */ params?: any; /** * A script html tag which can be included alongside the embed code * to make the iframe size to the available width. Use absolute URLs. * Example: */ resizeCode?: string; /** * A complete list of scripts required to display the content. * Includes core scripts and content type specific scripts. */ scripts?: string[]; /** * A complete list of styles required to display the content. * Includes core scripts and content type specific styles. */ styles?: string[]; /** * The absolute URL to the current content. */ url?: string; }; }; /** * The files in this list are references when creating iframes. */ core?: { /** * A list of JavaScript files that make up the H5P core */ scripts?: string[]; /** * A list of CSS styles that make up the H5P core. */ styles?: string[]; }; /** * Can be null. */ crossorigin?: any; /** * Can be null. */ crossoriginCacheBuster?: any; /** * We pass certain configuration values to the client with the editor * integration object. Note that the way to pass these values to the client * is NOT standardized and in the PHP implementation it is not the same in * the Drupal, Moodle and WordPress clients. For our NodeJS version * we've decided to put the values into the integration object. The page * created by the editor renderer has to extract these values and put * them into the corresponding properties of the H5PEditor object! * See /src/renderers/default.ts how this can be done! */ editor?: ILumiEditorIntegration; fullscreenDisabled?: 0 | 1; hubIsEnabled: boolean; /** * The localization strings. The namespace can for example be 'H5P'. */ l10n: { [namespace: string]: any; }; /** * Can be null. The server can customize library behavior by setting the * library config for certain machine names, as the H5P client allows it to * be called by executing H5P.getLibraryConfig(machineName). This means that * libraries can retrieve configuration values from the server that way. */ libraryConfig?: { [machineName: string]: any; }; /** * The URL at which the core **JavaScript** files are stored. */ libraryUrl?: string; /** * The cache buster appended to JavaScript and CSS files. * Example: ?q8idru */ pluginCacheBuster?: string; /** * If set the URL specified in ajax.setFinished is called when the user is * finished with a content object. */ postUserStatistics: boolean; reportingIsEnabled?: boolean; /** * Set to false to disable saving user state. */ saveFreq: number | boolean; /** * Used when generating xAPI statements. */ siteUrl?: string; /** * The URL at which files can be accessed. Combined with the baseUrl by the * client. * Example. /h5p */ url: string; /** * Used to override the auto-generated library URL (libraries means "content * types" here). If this is unset, the H5P client will assume '/libraries'. * Note that the URL is NOT appended to the url or baseUrl property! */ urlLibraries?: string; user: { /** * Usage unknown. */ canToggleViewOthersH5PContents?: 0 | 1; id?: any; mail: string; name: string; }; } /** * The editor integration object is used to pass information to the page that * is created by the renderer. Note that this object is NOT standard H5P * behavior but specific to our NodeJS implementation. * The editor view created by the renderer has to copy these values into the * H5PEditor object! This is the responsibility of the implementation and NOT * done by the H5P client automatically! */ export interface ILumiEditorIntegration extends IEditorIntegration { baseUrl?: string; contentId?: string; contentRelUrl?: string; editorRelUrl?: string; relativeUrl?: string; } /** * This is the H5P standard editor integration interface. */ export interface IEditorIntegration { ajaxPath: string; apiVersion: { majorVersion: number; minorVersion: number; }; assets: { css: string[]; js: string[]; }; basePath?: string; copyrightSemantics?: any; fileIcon?: { height: number; path: string; width: number; }; /** * The path at which **temporary** files can be retrieved from. */ filesPath: string; language?: string; libraryUrl: string; metadataSemantics?: any; nodeVersionId: ContentId; wysiwygButtons?: string[]; } /** * This describes the Path of JavaScript and CSS files in a library.json file. * This single property interface exists because the library.json file expects * this format. */ export interface IPath { path: string; } /** * This describes the creation time and the size of a file */ export interface IFileStats { birthtime: Date; size: number; } /** * This is the structure of "data transfer objects" that are passed back to the * JavaScript client. It is used to return a lot of information about library * metadata, required files, translations etc. * * It does not exactly follow the structure library.json: it also includes other * properties, which aren't present in the library.json file (they are added * dynamically) and some properties are missing or named differently. */ export interface ILibraryDetailedDataForClient { /** * URLs of CSS files required for the editor. */ css: string[]; /** * Exact usage unknown. Can be null. */ defaultLanguage: string; /** * URLs of JavaScript files required for the editor. */ javascript: string[]; /** * Exact usage unknown. Can be null. */ language: any; /** * The languages available for the content type (e.g. en, de, fr, etc.) */ languages: string[]; /** * The machine name of the library. (e.g. H5P.Example) */ name: string; /** * The semantics object describing the structure of content of this type. */ semantics: ISemanticsEntry[]; /** * The human-readable title of the library. */ title: string; /** * Used translation strings for the various libraries. */ translations: any; /** * The URL of the JavaScript file that performs content upgrades. * Can be null. */ upgradesScript: string; /** * The version of the library. */ version: { major: number; minor: number; }; } /** * This is the structure of "data transfer objects" that are passed back to the * Javascript client. It is used when giving a rough overview of installed libraries. */ export interface ILibraryOverviewForClient { majorVersion: number; metadataSettings: any; minorVersion: number; name: string; restricted: boolean; runnable: boolean | 0 | 1; title: string; tutorialUrl: string; /** * The name of the library in the format "H5P.Library-1.0" */ uberName: string; } /** * This specifies the structure of user objects. It must be implemented by * implementations. */ export interface IUser { /** * If true, the user can create content of content types that are set to "restricted". */ canCreateRestricted: boolean; /** * If true, the user can install content types from the hub that are set the "recommended" * by the Hub. */ canInstallRecommended: boolean; /** * If true, the user can generally install and update libraries. This includes Hub * content types that aren't set to "recommended" or uploading custom packages. */ canUpdateAndInstallLibraries: boolean; /** * An internal id used to check if user objects are identical. */ id: string; /** * The full name of the user. */ name: string; /** * Specifies type of user. Possible values other than 'local' are unknown as of this time. */ type: 'local' | string; } /** * Implementations need to implement the IContentStorage interface and pass it to the constructor of * H5PEditor. * It is used to persist content data (semantic data, images, videos etc.) permanently. * See the FileContentStorage sample implementation in the examples directory for more details. */ export interface IContentStorage { /** * Creates a content object in the repository. Content files (like images) are added to it later * with addFile(...). * Throws an error if something went wrong. In this case the calling method will remove all traces of * the content and all changes are reverted. * @param metadata The content metadata of the content (= h5p.json) * @param content the content object (= content/content.json) * @param user The user who owns this object. * @param contentId (optional) The content id to use * @returns The newly assigned content id */ addContent(metadata: IContentMetadata, content: any, user: IUser, contentId?: ContentId): Promise; /** * Adds a content file to an existing content object. The content object has to be created with addContent(...) first. * @param contentId The id of the content to add the file to * @param filename The filename; can be a path including subdirectories (e.g. 'images/xyz.png') * @param readStream A readable stream that contains the data * @param user (optional) The user who owns this object */ addFile(contentId: ContentId, filename: string, readStream: Stream, user?: IUser): Promise; /** * Checks if a piece of content exists in storage. * @param contentId the content id to check * @returns true if the piece of content exists */ contentExists(contentId: ContentId): Promise; /** * Deletes a content object and all its dependent files from the repository. * Throws errors if something goes wrong. * @param id The content id to delete. * @param user The user who wants to delete the content */ deleteContent(contentId: ContentId, user?: IUser): Promise; /** * Deletes a file from a content object. * @param contentId the content object the file is attached to * @param filename the file to delete; can be a path including subdirectories (e.g. 'images/xyz.png') */ deleteFile(contentId: ContentId, filename: string, user?: IUser): Promise; /** * Checks if a file exists. * @param contentId The id of the content to add the file to * @param filename the filename of the file to get; can be a path including subdirectories (e.g. 'images/xyz.png') * @returns true if the file exists */ fileExists(contentId: ContentId, filename: string): Promise; /** * Returns information about a content file (e.g. image or video) inside a piece of content. * @param id the id of the content object that the file is attached to * @param filename the filename of the file to get information about * @param user the user who wants to retrieve the content file * @returns */ getFileStats(contentId: ContentId, file: string, user: IUser): Promise; /** * Returns a readable stream of a content file (e.g. image or video) inside a piece of content * @param id the id of the content object that the file is attached to * @param filename the filename of the file to get; can be a path including subdirectories (e.g. 'images/xyz.png') * @param user the user who wants to retrieve the content file * @param rangeStart (optional) the position in bytes at which the stream should start * @param rangeEnd (optional) the position in bytes at which the stream should end * @returns the stream (that can be used to send the file to the user) */ getFileStream(contentId: ContentId, file: string, user: IUser, rangeStart?: number, rangeEnd?: number): Promise; /** * Returns the content metadata (=h5p.json) for a content id * @param contentId the content id for which to retrieve the metadata * @param user (optional) the user who wants to access the metadata. If undefined, access must be granted. * @returns the metadata */ getMetadata(contentId: ContentId, user?: IUser): Promise; /** * Returns the content object (=content.json) for a content id * @param contentId the content id for which to retrieve the metadata * @param user (optional) the user who wants to access the metadata. If undefined, access must be granted. * @returns the content object */ getParameters(contentId: ContentId, user?: IUser): Promise; /** * Calculates how often a library is in use. * @param library the library for which to calculate usage. * @returns asDependency: how often the library is used as subcontent in * content; asMainLibrary: how often the library is used as a main library */ getUsage(library: ILibraryName): Promise<{ asDependency: number; asMainLibrary: number; }>; /** * Returns an array of permissions that the user has on the piece of content * @param contentId the content id to check * @param user the user who wants to access the piece of content * @returns the permissions the user has for this content (e.g. download it, delete it etc.) */ getUserPermissions(contentId: ContentId, user: IUser): Promise; /** * Lists the content objects in the system (if no user is specified) or owned by the user. * @param user (optional) the user who owns the content * @returns a list of contentIds */ listContent(user?: IUser): Promise; /** * Gets the filenames of files added to the content with addFile(...) (e.g. images, videos or other files) * @param contentId the piece of content * @param user the user who wants to access the piece of content * @returns a list of files that are used in the piece of content, e.g. ['images/image1.png', 'videos/video2.mp4', 'file.xyz'] */ listFiles(contentId: ContentId, user: IUser): Promise; /** * Removes invalid characters from filenames and enforces other filename * rules required by the storage implementation (e.g. filename length * restrictions). * Note: file names will be appended with a 9 character long unique id, * so you must make sure to shorten long filenames accordingly! * If you do not implement this method, there will be no sanitization! * @param filename the filename to sanitize; this can be a relative path * (e.g. "images/image1.png") * @returns the clean filename */ sanitizeFilename?(filename: string): string; } /** * Implementations need to implement the ILibraryStorage interface and pass it to H5PEditor. * It is used to persist library information and files permanently. * Note that the library metadata and semantics are accessed regularly, so caching them is a good idea. * The library files will also be accessed frequently, so it makes sense to keep them in memory and not * access a hard disk every time they are downloaded. * See the FileLibraryStorage sample implementation in the examples directory for more details. */ export interface ILibraryStorage { /** * Adds a library file to a library. The library metadata must have been installed with addLibrary(...) first. * Throws an error if something unexpected happens. In this case the method calling addFile(...) will clean * up the partly installed library. * @param library The library that is being installed * @param filename Filename of the file to add, relative to the library root * @param stream The stream containing the file content * @returns true if successful */ addFile(library: ILibraryName, filename: string, readStream: Stream): Promise; /** * Adds the metadata of the library to the repository and assigns a new id to the installed library. * This dea is used later when the library must be referenced somewhere. * Throws errors if something goes wrong. * @param libraryMetadata The library metadata object (= content of library.json) * @param restricted True if the library can only be used be users allowed to install restricted libraries. * @returns The newly created library object to use when adding library files with addFile(...) */ addLibrary(libraryData: ILibraryMetadata, restricted: boolean): Promise; /** * Removes all files of a library. Doesn't delete the library metadata. (Used when updating libraries.) * @param library the library whose files should be deleted */ clearFiles(library: ILibraryName): Promise; /** * Removes the library and all its files from the repository. * Throws errors if something went wrong. * @param library The library to remove. */ deleteLibrary(library: ILibraryName): Promise; /** * Check if the library contains a file. * @param library The library to check * @param filename * @returns true if file exists in library, false otherwise */ fileExists(library: ILibraryName, filename: string): Promise; /** * Counts how often libraries are listed in the dependencies of other * libraries and returns a list of the number. * * Note: Implementations should not count circular dependencies that are * caused by editorDependencies. Example: H5P.InteractiveVideo has * H5PEditor.InteractiveVideo in its editor dependencies. * H5PEditor.Interactive video has H5P.InteractiveVideo in its preloaded * dependencies. In this case H5P.InteractiveVideo should get a dependency * count of 0 and H5PEditor.InteractiveVideo should have 1. That way it is * still possible to delete the library from storage. * * @returns an object with ubernames as key. * Example: * { * 'H5P.Example': 10 * } * This means that H5P.Example is used by 10 other libraries. */ getAllDependentsCount(): Promise<{ [ubername: string]: number; }>; /** * Returns the number of libraries that depend on this (single) library. * @param library the library to check * @returns the number of libraries that depend on this library. */ getDependentsCount(library: ILibraryName): Promise; /** * Returns a information about a library file. * Throws an exception if the file does not exist. * @param library library * @param filename the relative path inside the library * @returns the file stats */ getFileStats(library: ILibraryName, file: string): Promise; /** * Returns a readable stream of a library file's contents. * Throws an exception if the file does not exist. * @param library library * @param filename the relative path inside the library * @returns a readable stream of the file's contents */ getFileStream(library: ILibraryName, file: string): Promise; /** * Returns all installed libraries or the installed libraries that have the machine names in the arguments. * @param machineNames (optional) only return libraries that have these machine names * @returns the libraries installed */ getInstalledLibraryNames(...machineNames: string[]): Promise; /** * Gets a list of installed language files for the library. * @param library The library to get the languages for * @returns The list of JSON files in the language folder (without the extension .json) */ getLanguages(library: ILibraryName): Promise; /** * Gets the information about an installed library * @param library the library * @returns the metadata and information about the locally installed library */ getLibrary(library: ILibraryName): Promise; /** * Checks if a library is installed. * @param library the library to check * @returns true if the library is installed */ isInstalled(library: ILibraryName): Promise; /** * Checks if the library has been installed. * @param name the library name * @returns true if the library has been installed */ libraryExists(name: ILibraryName): Promise; /** * Returns a list of library addons that are installed in the system. * Addons are libraries that have the property 'addTo' in their metadata. * ILibraryStorage implementation CAN but NEED NOT implement the method. * If it is not implemented, addons won't be available in the system. */ listAddons?(): Promise; /** * Gets a list of all library files that exist for this library. * @param library * @returns all files that exist for the library */ listFiles(library: ILibraryName): Promise; /** * Updates the additional metadata properties that is added to the * stored libraries. This metadata can be used to customize behavior like * restricting libraries to specific users. * * Implementations should avoid updating the metadata if the additional * metadata if nothing has changed. * @param library the library for which the metadata should be updated * @param additionalMetadata the metadata to update * @returns true if the additionalMetadata object contained real changes * and if they were successfully saved; false if there were not changes. * Throws an error if saving was not possible. */ updateAdditionalMetadata(library: ILibraryName, additionalMetadata: Partial): Promise; /** * Updates the library metadata. This is necessary when updating to a new patch version. * After this clearFiles(...) is called by the LibraryManager to remove all old files. * The next step is to add the patched files with addFile(...). * @param libraryMetadata the new library metadata * @returns The updated library object */ updateLibrary(libraryMetadata: ILibraryMetadata): Promise; } /** * This is the actual "content itself", meaning the object contained in content.json. It is * created by the JavaScript editor client and played out by the JavaScript player. Its structure * can vary depending on the semantics associated with the main library of the content. */ export declare type ContentParameters = any; /** * This is an entry in the semantics of a library. The semantics define who content parameters * must look like. * * Note: Attributes can only be used by specific semantic types. See https://h5p.org/semantics * for a full reference. */ export interface ISemanticsEntry { /** * A common field is set for all instances of the library at once. * In the editor, all common fields are displayed in a group at the bottom. * Use this for localization / translations. */ common?: boolean; /** * (for number) the number of allowed decimals */ decimals?: number; /** * The default value of the field. */ default?: string; /** * An explanation text below the widget shown in the editor */ description?: string; /** * (for text with html widget) what the html widget inserts when pressing enter */ enterMode?: 'p' | 'div'; /** * (for list) The name for a single entity in a list. */ entity?: string; /** * (for group) Group is expanded by default */ expanded?: boolean; /** * Further attributes allowed in the params. */ extraAttributes?: string[]; /** * (in lists only) defines a single field type in the list */ field?: ISemanticsEntry; /** * (in groups only) a list of field definitions */ fields?: ISemanticsEntry[]; /** * The font choices the user has in the HTML editor widget. If set to true, * the editor will display the default choices and the style will be allowed * by the sanitization filter. All other styles will be removed. * * You an also specify lists of allowed CSS values with a label. These are * currently ignored in the server-side CSS style filter, though. */ font?: { background?: boolean | { css: string; default?: boolean; label: string; }[]; color?: boolean | { css: string; default?: boolean; label: string; }[]; family?: boolean | { css: string; default?: boolean; label: string; }[]; height?: boolean | { css: string; default?: boolean; label: string; }[]; size?: boolean | { css: string; default?: boolean; label: string; }[]; spacing?: boolean | { css: string; default?: boolean; label: string; }[]; }; /** * More important fields have a more prominent style in the editor. */ importance?: 'low' | 'medium' | 'high'; /** * A help text that can be collapsed. */ important?: { description: string; example: string; }; /** * (for group) unknown */ isSubContent?: boolean; /** * The text displayed in the editor for the entry. (localizable) */ label?: string; /** * (for number) the maximum number allowed * (for list) the maximum number of elements */ max?: number | string; /** * (for text) the maximum number of characters of the text */ maxLength?: number; /** * (for number) the minimum number allowed * (for list) the minimum number of elements */ min?: number | string; /** * The internal name (e.g. for referencing it in code) */ name: string; /** * Optional fields don't have to be filled in. */ optional?: boolean; /** * (for select) the options to choose from * (for library) a list of library ubernames (whitespaces instead * of hyphens as separators) */ options?: any[]; /** * The text displayed in a text box if the user has entered nothing so far. */ placeholder?: string; /** * (for text) the regexp pattern the text must match */ regexp?: { modifiers: string; pattern: string; }; /** * (for number) the allowed steps */ steps?: number; /** * (for library) an id identifying subcontent, set by the editor; Must be * formatted like this: * /^\{?[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\}?$/ */ subContentId?: string; /** * (for text) list of allowed html tags. */ tags?: string[]; /** * The object type of this entry. */ type: 'file' | 'text' | 'number' | 'boolean' | 'group' | 'list' | 'select' | 'library' | 'image' | 'video' | 'audio'; /** * Name of the widget to use in the editor. */ widget?: string; } /** * This is metadata of a library that is not part of the H5P specification. The * data can be used to customize behaviour of h5p-nodejs-library. */ export interface IAdditionalLibraryMetadata { /** * If set to true, the library can only be used be users who have this special * privilege. */ restricted: boolean; } /** * Objects of this interface represent installed libraries that have an id. */ export interface IInstalledLibrary extends ILibraryMetadata, IAdditionalLibraryMetadata { /** * Compares libraries by giving precedence to title, then major version, then minor version * @param otherLibrary */ compare(otherLibrary: IInstalledLibrary): number; /** * Compares libraries by giving precedence to major version, then minor version, then if present patch version. * @param otherLibrary * @returns a negative value: if this library is older than the other library * a positive value: if this library is newer than the other library * zero: if both libraries are the same (or if it can't be determined, because the patch version is missing in the other library) */ compareVersions(otherLibrary: ILibraryName & { patchVersion?: number; }): number; } /** * This interface represents the structure of library.json files. */ export interface ILibraryMetadata extends IFullLibraryName { /** * Addons can be added to other content types by */ addTo?: { content?: { types?: { text?: { /** * If any string property in the parameters matches the regex, * the addon will be activated for the content. */ regex?: string; }; }[]; }; /** * Contains cases in which the library should be added to the editor. * * This is an extension to the H5P library metadata structure made by * h5p-nodejs-library. That way addons can specify to which editors * they should be added in general. The PHP implementation hard-codes * this list into the server, which we want to avoid here. */ editor?: { /** * A list of machine names in which the addon should be added. */ machineNames: string[]; }; /** * Contains cases in which the library should be added to the player. * * This is an extension to the H5P library metadata structure made by * h5p-nodejs-library. That way addons can specify to which editors * they should be added in general. The PHP implementation hard-codes * this list into the server, which we want to avoid here. */ player?: { /** * A list of machine names in which the addon should be added. */ machineNames: string[]; }; }; author?: string; /** * The core API required to run the library. */ coreApi?: { majorVersion: number; minorVersion: number; }; description?: string; dropLibraryCss?: { machineName: string; }[]; dynamicDependencies?: ILibraryName[]; editorDependencies?: ILibraryName[]; embedTypes?: ('iframe' | 'div')[]; fullscreen?: 0 | 1; h?: number; license?: string; metadataSettings?: { disable: 0 | 1; disableExtraTitleField: 0 | 1; }; preloadedCss?: IPath[]; preloadedDependencies?: ILibraryName[]; preloadedJs?: IPath[]; runnable: boolean | 0 | 1; title: string; w?: number; } /** * Persists any arbitrarily nested objects to some kind storage. * Used to store settings and temporary data that needs to be retrieved later. */ export interface IKeyValueStorage { /** * Loads a value from the storage * @param key The key whose value should be returned. * @returns the value or undefined */ load(key: string): Promise; /** * Save a value to the storage. * @param key The key for which the value should be stored. * @param value The value to store. */ save(key: string, value: any): Promise; } /** * This is the data sent to the H5P Hub when the local installation (site) registers itself there. */ export interface IRegistrationData { /** * The core API version that the site supports (e.g. 1.24). Unknown if the hub only reports back content * types that work for this core version. */ core_api_version: string; /** * Purpose unknown. */ disabled: 0 | 1; /** * The version of the H5P PHP library. As we only imitate the PHP library, this doesn't really apply here. * Probably used for statistical purposes. It makes sense to use the version of the core client JS files here. */ h5p_version: string; /** * An integer that identifies the site. You can for example use a crc32 hash of the local installation path. * The purpose of the id is unknown. */ local_id: string; /** * The name of the H5P implementation. */ platform_name: string; /** * The version of the H5P implementation. */ platform_version: string; /** * Tells the H5P Hub in what network the installation operates. Probably used for statistical * purposes. */ type: 'local' | 'network' | 'internet'; /** * The unique id that is used to re-identify this site at the Hub later. * Can be '' when the site is doing the registration for the first time. * Later it should be the value that is received back from the H5P Hub. */ uuid: string; } /** * This is the usage statistics sent to the H5P Hub, when the option is enabled. * NOTE: Not implemented yet. */ export interface IUsageStatistics { /** * Statistical information about every installed library. The key is the library uber name * with a whitespace instead of a hyphen as separator between machine name and * major version (e.g. H5P.Example 1.0). */ libraries: { [key: string]: ILibraryUsageStatistics; }; /** * The number of active authors */ num_authors: number; } /** * Used to send statistical information about the usage of the library to the H5P Hub. * NOTE: This functionality is not implemented yet. */ export interface ILibraryUsageStatistics { /** * The number of content objects created for this library */ content: number; /** * The number of 'created' events from the log. (Can probably be different from 'content' * as content objects can also be deleted again.) */ created: number; /** * The number of 'createdUpload' events from the log */ createdUpload: number; /** * The number of 'deleted' events from the log */ deleted: number; /** * The number of 'loaded' events (= views?) from log. */ loaded: number; /** * Used patch version */ patch: number; /** * The number of 'resultViews' events from log */ resultViews: number; /** * The number of 'shortcode insert' events from log (Unclear what this is) */ shortcodeInserts: number; } /** * This resolver loads data about a local library. */ export declare type ILibraryLoader = (machineName: string, majorVersion: number, minorVersion: number) => IInstalledLibrary; export interface IH5PConfig { /** * URL prefix for all AJAX requests */ ajaxUrl: string; /** * The prefix that is added to all URLs. */ baseUrl: string; /** * Base path for content files (e.g. images). Used in the player and in * the editor. */ contentFilesUrl: string; /** * Base path for content files (e.g. images) IN THE PLAYER. It MUST direct * to a URL at which the content files for THE CONTENT BEING DISPLAYED must * be accessible. This means it must include the contentId of the object! * You can insert the contentId using the placeholder {{contentId}}. * * Example: * http://127.0.0.1:9000/s3bucket/${contentId}` * * You can use this URL to load content files from a different server, e.g. * S3 storage. Note that this only work for the player and not the editor. */ contentFilesUrlPlayerOverride: string; /** * Time after which the content type cache is considered to be outdated in milliseconds. * User-configurable. */ contentTypeCacheRefreshInterval: number; /** * A list of file extensions allowed for content files. * Contains file extensions (without .) separated by whitespaces. */ contentWhitelist: string; /** * This is the version of the H5P Core (JS + CSS) that is used by this implementation. * It is sent to the H5P Hub when registering there. * Not user-configurable and should not be changed by custom implementations. */ coreApiVersion: { major: number; minor: number; }; /** * Path to the H5P core files directory. */ coreUrl: string; /** * If true, the fullscreen button will not be shown to the user. */ disableFullscreen: boolean; /** * Path to the downloadable H5P packages. */ downloadUrl: string; /** * You can specify which addons should be added to which library here. */ editorAddons?: { /** * The property name is the machine mame to which to add addons. * The string array contains the machine names of addons that should * be added. */ [machineName: string]: string[]; }; /** * Path to editor "core files" */ editorLibraryUrl: string; /** * If set to true, the content types that require a Learning Record Store to make sense are * offered as a choice when the user creates new content. * User-configurable. */ enableLrsContentTypes: boolean; /** * The maximum character count of paths of content files allowed when * exporting h5p packages. If files would be longer, paths are shortened. */ exportMaxContentPathLength: number; /** * Unclear. Taken over from PHP implementation and sent to the H5P Hub when registering the site. * User-configurable. */ fetchingDisabled: 0 | 1; /** * This is the version of the PHP implementation that the NodeJS implementation imitates. * Can be anything like 1.22.1 * It is sent to the H5P Hub when registering there. * Not user-configurable and should not be changed by custom implementations. */ h5pVersion: string; /** * The URL called to fetch information about the content types available at the H5P Hub. * User-configurable. */ hubContentTypesEndpoint: string; /** * The URL called to register the running instance at the H5P Hub. * User-configurable. */ hubRegistrationEndpoint: string; /** * The URL of the library files (=content types). */ librariesUrl: string; /** * (optional) You can set server-wide custom settings for some libraries * by setting the values here. As far as we know, this is currently only * supported by H5P.MathDisplay. See https://h5p.org/mathematical-expressions * for more information. */ libraryConfig?: { [machineName: string]: any; }; /** * A list of file extensions allowed for library files. (File extensions without . and * separated by whitespaces.) * (All extensions allowed for content files are also automatically allowed for libraries). */ libraryWhitelist: string; /** * The list of content types that are enabled when enableLrsContentTypes is set to true. * Not user-configurable. */ lrsContentTypes: string[]; /** * The maximum allowed file size of content and library files (in bytes). */ maxFileSize: number; /** * The maximum allowed file size of all content and library files in an uploaded h5p package (in bytes). */ maxTotalSize: number; /** * The Url at which the parameters of a piece of content can be retrieved */ paramsUrl: string; /** * This is the name of the H5P implementation sent to the H5P for statistical reasons. * Not user-configurable but should be overridden by custom custom implementations. */ platformName: string; /** * This is the version of the H5P implementation sent to the H5P when registering the site. * Not user-configurable but should be overridden by custom custom implementations. */ platformVersion: string; /** * You can specify which addons should be added to which library in the player here. */ playerAddons?: { /** * The property name is the machine mame to which to add addons. * The string array contains the machine names of addons that should * be added. */ [machineName: string]: string[]; }; /** * The Url at which content can be displayed. */ playUrl: string; /** * If true, the instance will send usage statistics to the H5P Hub whenever it looks for new content types or updates. * User-configurable. */ sendUsageStatistics: boolean; /** * Indicates on what kind of network the site is running. Can be "local", "network" or "internet". * TODO: This value should not be user-configurable, but has to be determined by the system on startup. * (If possible.) */ siteType: 'local' | 'network' | 'internet'; temporaryFileLifetime: number; /** * The URL path of temporary file storage (used for image, video etc. uploads of * unsaved content). */ temporaryFilesUrl: string; uuid: string; /** * Loads all changeable settings from storage. (Should be called when the system initializes.) */ load(): Promise; /** * Saves all changeable settings to storage. (Should be called when a setting was changed.) */ save(): Promise; } /** * Describes as file that is stored temporarily (for uploads of unsaved content) */ export interface ITemporaryFile { /** * Indicates when the temporary file should be deleted. */ expiresAt: Date; /** * The name by which the file can be identified; can be a path including subdirectories (e.g. 'images/xyz.png') */ filename: string; /** * The user who is allowed to access the file */ ownedByUserId: string; } /** * Stores files uploaded by the user in temporary storage. Note that filenames can be paths like * 'images/xyz.png'! */ export interface ITemporaryFileStorage { /** * Deletes the file from temporary storage (e.g. because it has expired) * @param filename the filename; can be a path including subdirectories (e.g. 'images/xyz.png') * @param userId the user id * @returns true if deletion was successful */ deleteFile(filename: string, userId: string): Promise; /** * Checks if a file exists in temporary storage. * @param filename the filename to check; can be a path including subdirectories (e.g. 'images/xyz.png') * @param user the user for who to check * @returns true if file already exists */ fileExists(filename: string, user: IUser): Promise; /** * Returns a information about a temporary file. * Throws an exception if the file does not exist. * @param filename the relative path inside the library * @param user the user who wants to access the file * @returns the file stats */ getFileStats(filename: string, user: IUser): Promise; /** * Returns the contents of a file. * Must check for access permissions and throw an H5PError if a file is not accessible. * @param filename the filename; can be a path including subdirectories (e.g. 'images/xyz.png') * @param user the user who accesses the file * @param rangeStart (optional) the position in bytes at which the stream should start * @param rangeEnd (optional) the position in bytes at which the stream should end * @returns the stream containing the file's content */ getFileStream(filename: string, user: IUser, rangeStart?: number, rangeEnd?: number): Promise; /** * Returns a list of files in temporary storage for the specified user. * If the user is undefined or null, lists all files in temporary storage. * @param user (optional) Only list files for the user. If left out, will list all temporary files. * @returns a list of information about the files */ listFiles(user?: IUser): Promise; /** * Removes invalid characters from filenames and enforces other filename * rules required by the storage implementation (e.g. filename length * restrictions). * @param filename the filename to sanitize * @returns the clean filename */ sanitizeFilename?(filename: string): string; /** * Stores a file. Only the user who stores the file is allowed to access it later. * @param filename the filename by which the file will be identified later; can be a path including subdirectories (e.g. 'images/xyz.png') * @param dataStream the stream containing the file's data * @param user the user who is allowed to access the file * @param expirationTime when the file ought to be deleted * @returns an object containing information about the stored file; undefined if failed */ saveFile(filename: string, dataStream: ReadStream, user: IUser, expirationTime: Date): Promise; } /** * This function returns the (relative) URL at which a file inside a library * can be accessed. It is used when URLs of library files must be inserted * (hard-coded) into data structures. The implementation must do this file -> * URL resolution, as it decides where the files can be accessed. */ export declare type ILibraryFileUrlResolver = (library: ILibraryName, filename: string) => string; /** * This objects carries information about content types that the user can select * from the H5P Hub. The optional properties don't have to be set if a content type * is only installed locally. */ export interface IHubContentType { categories?: string[]; createdAt?: number; description: string; example?: string; h5pMajorVersion?: number; h5pMinorVersion?: number; icon: string; isRecommended?: boolean; keywords?: string[]; license?: any; machineName: string; majorVersion: number; minorVersion: number; owner: string; patchVersion: number; popularity?: number; screenshots?: any; summary?: string; title: string; tutorial?: string; updatedAt?: number; } /** * Carries information about the local installation status of a content type. */ export interface IHubContentTypeWithLocalInfo extends IHubContentType { canInstall: boolean; installed: boolean; isUpToDate: boolean; localMajorVersion: number; localMinorVersion: number; localPatchVersion: number; restricted: boolean; } /** * Information about the H5P Hub */ export interface IHubInfo { apiVersion: { major: number; minor: number; }; details: Array<{ code: string; message: string; }>; libraries: IHubContentTypeWithLocalInfo[]; outdated: boolean; recentlyUsed: any[]; user: string; } export interface IPlayerModel { contentId: ContentParameters; dependencies: ILibraryName[]; downloadPath: string; embedTypes: ('iframe' | 'div')[]; integration: IIntegration; scripts: string[]; styles: string[]; translations: any; user: IUser; } export interface IEditorModel { integration: IIntegration; scripts: string[]; styles: string[]; urlGenerator: IUrlGenerator; } export interface IUrlGenerator { coreFile(file: string): string; downloadPackage(contentId: ContentId): string; editorLibraryFile(file: string): string; editorLibraryFiles(): string; libraryFile(library: ILibraryName, file: string): string; parameters(): string; play(): string; temporaryFiles(): string; } /** * The translation function is called to retrieve translation for keys. * @param key the key for which a translation should be returned; Note that his * is not the English string, but a identifier that can also be prefixed with a * namespace (we follow the convention of the npm package i18next here). * Examples: * - namespace1:key1 * - anothernamespace:a-somewhat-longer-key * @param language the language code to translate to (ISO 639-1) * @returns the translated string */ export declare type ITranslationFunction = (key: string, language: string) => string; export interface ILibraryAdministrationOverviewItem { canBeDeleted: boolean; canBeUpdated: boolean; dependentsCount: number; instancesAsDependencyCount: number; instancesCount: number; isAddon: boolean; machineName: string; majorVersion: number; minorVersion: number; patchVersion: number; restricted: boolean; runnable: boolean; title: string; }