// Generated by dts-bundle-generator v7.2.0 export interface SemaphoreOptions { /** * The maximum number of concurrent locks. */ concurrency: number; /** * The maximum time to wait for a lock to become available. */ timeout?: number; } declare class Semaphore { private _running; private concurrency; private timeout?; private queue; constructor({ concurrency, timeout }: SemaphoreOptions); get remaining(): number; get running(): number; acquire(): Promise<() => void>; run(fn: () => T | Promise): Promise; } declare const phpEventStdinTransfer: unique symbol; export type PHPEventWithStdinTransfer = { type: string; stdin: ReadableStream; [phpEventStdinTransfer]: true; }; /** * Emitted when a sendmail null transport receives the first stdin bytes from * `mail()`, `popen()`, `proc_open()`, or any other spawn of a `sendmail` binary. */ export interface PHPSendmailSpawnedEvent extends PHPEventWithStdinTransfer { type: "sendmail.spawned"; } export declare function phpVar(value: unknown): string; export declare function phpVars>(vars: T): Record; declare const proxyMarker: unique symbol; declare const createEndpoint: unique symbol; declare const releaseProxy: unique symbol; /** * Interface of values that were marked to be proxied with `comlink.proxy()`. * Can also be implemented by classes. */ export interface ProxyMarked { [proxyMarker]: true; } /** * Takes a type and wraps it in a Promise, if it not already is one. * This is to avoid `Promise>`. * * This is the inverse of `Unpromisify`. */ export type Promisify = T extends Promise ? T : Promise; /** * Takes a type that may be Promise and unwraps the Promise type. * If `P` is not a Promise, it returns `P`. * * This is the inverse of `Promisify`. */ export type Unpromisify

= P extends Promise ? T : P; /** * Takes the raw type of a remote property and returns the type that is visible to the local thread * on the proxy. * * Note: This needs to be its own type alias, otherwise it will not distribute over unions. * See https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types */ export type RemoteProperty = T extends Function | ProxyMarked ? Remote : Promisify; /** * Takes the raw type of a property as a remote thread would see it through a proxy (e.g. when * passed in as a function argument) and returns the type that the local thread has to supply. * * This is the inverse of `RemoteProperty`. * * Note: This needs to be its own type alias, otherwise it will not distribute over unions. See * https://www.typescriptlang.org/docs/handbook/advanced-types.html#distributive-conditional-types */ export type LocalProperty = T extends Function | ProxyMarked ? Local : Unpromisify; /** * Proxies `T` if it is a `ProxyMarked`, clones it otherwise (as handled by structured cloning and * transfer handlers). */ export type ProxyOrClone = T extends ProxyMarked ? Remote : T; /** * Inverse of `ProxyOrClone`. */ export type UnproxyOrClone = T extends RemoteObject ? Local : T; /** * Takes the raw type of a remote object in the other thread and returns the type as it is visible * to the local thread when proxied with `Comlink.proxy()`. * * This does not handle call signatures, which is handled by the more general `Remote` type. * * @template T The raw type of a remote object as seen in the other thread. */ export type RemoteObject = { [P in keyof T]: RemoteProperty; }; /** * Takes the type of an object as a remote thread would see it through a proxy (e.g. when passed in * as a function argument) and returns the type that the local thread has to supply. * * This does not handle call signatures, which is handled by the more general `Local` type. * * This is the inverse of `RemoteObject`. * * @template T The type of a proxied object. */ export type LocalObject = { [P in keyof T]: LocalProperty; }; /** * Additional special comlink methods available on each proxy returned by `Comlink.wrap()`. */ export interface ProxyMethods { [createEndpoint]: () => Promise; [releaseProxy]: () => void; } /** * Takes the raw type of a remote object, function or class in the other thread and returns the * type as it is visible to the local thread from the proxy return value of `Comlink.wrap()` or * `Comlink.proxy()`. */ export type Remote = RemoteObject & (T extends (...args: infer TArguments) => infer TReturn ? (...args: { [I in keyof TArguments]: UnproxyOrClone; }) => Promisify>> : unknown) & (T extends { new (...args: infer TArguments): infer TInstance; } ? { new (...args: { [I in keyof TArguments]: UnproxyOrClone; }): Promisify>; } : unknown) & ProxyMethods; /** * Expresses that a type can be either a sync or async. */ export type MaybePromise = Promise | T; /** * Takes the raw type of a remote object, function or class as a remote thread would see it through * a proxy (e.g. when passed in as a function argument) and returns the type the local thread has * to supply. * * This is the inverse of `Remote`. It takes a `Remote` and returns its original input `T`. */ export type Local = Omit, keyof ProxyMethods> & (T extends (...args: infer TArguments) => infer TReturn ? (...args: { [I in keyof TArguments]: ProxyOrClone; }) => MaybePromise>> : unknown) & (T extends { new (...args: infer TArguments): infer TInstance; } ? { new (...args: { [I in keyof TArguments]: ProxyOrClone; }): MaybePromise>>; } : unknown); /** * Converts an object type to a promisified version where: * - Methods return `Promise>` (no double-wrapping) * - Properties become `Promise>` */ export type Promisified = { [K in keyof T]: T[K] extends (...args: infer A) => infer R ? (...args: A) => Promise> : Promise>; }; /** * The type returned by `createObjectPoolProxy`. All method calls and * property accesses are wrapped in promises because acquiring a free * pool instance is inherently async. * * Dispose/asyncDispose symbols are omitted because the pool proxy * forwards calls to a single random instance — disposing one * instance out of the pool is never the intended behavior. Pool * lifecycle should be managed by the code that created the pool. */ export type Pooled = Omit, typeof Symbol.dispose | typeof Symbol.asyncDispose>; declare class EmscriptenDownloadMonitor extends EventTarget { #private; expectAssets(assets: Record): void; monitorFetch(fetchPromise: Promise): Promise; } /** * Options for customizing the progress tracker. */ export interface ProgressTrackerOptions { /** The weight of the progress, a number between 0 and 1. */ weight?: number; /** The caption to display during progress, a string. */ caption?: string; /** The time in milliseconds to fill the progress, a number. */ fillTime?: number; } /** * Custom event providing information about a loading process. */ export type LoadingEvent = CustomEvent<{ /** The number representing how much was loaded. */ loaded: number; /** The number representing how much needs to loaded in total. */ total: number; }>; /** * Custom event providing progress details. */ export type ProgressTrackerEvent = CustomEvent; export interface ProgressDetails { /** The progress percentage as a number between 0 and 100. */ progress: number; /** The caption to display during progress, a string. */ caption: string; } /** * ProgressObserver A function that receives progress updates. * * @param progress The progress percentage as a number between 0 and 100. */ export type ProgressObserver = (progress: number) => void; /** * Listener A function for handling specific event types. * * @param event The event of type T. */ export type Listener = (event: T) => void; export type TSCompatibleListener = EventListenerOrEventListenerObject | null | Listener; export interface ProgressReceiver { setProgress(details: ProgressDetails): any; setLoaded(): any; } declare class ProgressTracker extends EventTarget { private _selfWeight; private _selfDone; private _selfProgress; private _selfCaption; private _weight; private _progressObserver?; private _loadingListener?; private _isFilling; private _fillTime; private _fillInterval?; private _subTrackers; constructor({ weight, caption, fillTime, }?: ProgressTrackerOptions); /** * Creates a new sub-tracker with a specific weight. * * The weight determines what percentage of the overall progress * the sub-tracker represents. For example, if the main tracker is * monitoring a process that has two stages, and the first stage * is expected to take twice as long as the second stage, you could * create the first sub-tracker with a weight of 0.67 and the second * sub-tracker with a weight of 0.33. * * The caption is an optional string that describes the current stage * of the operation. If provided, it will be used as the progress caption * for the sub-tracker. If not provided, the main tracker will look for * the next sub-tracker with a non-empty caption and use that as the progress * caption instead. * * Returns the newly-created sub-tracker. * * @throws {Error} If the weight of the new stage would cause the total weight of all stages to exceed 1. * * @param weight The weight of the new stage, as a decimal value between 0 and 1. * @param caption The caption for the new stage, which will be used as the progress caption for the sub-tracker. * * @example * ```ts * const tracker = new ProgressTracker(); * const subTracker1 = tracker.stage(0.67, 'Slow stage'); * const subTracker2 = tracker.stage(0.33, 'Fast stage'); * * subTracker2.set(50); * subTracker1.set(75); * subTracker2.set(100); * subTracker1.set(100); * ``` */ stage(weight?: number, caption?: string): ProgressTracker; /** * Fills the progress bar slowly over time, simulating progress. * * The progress bar is filled in a 100 steps, and each step, the progress * is increased by 1. If `stopBeforeFinishing` is true, the progress bar * will stop filling when it reaches 99% so that you can call `finish()` * explicitly. * * If the progress bar is filling or already filled, this method does nothing. * * @example * ```ts * const progress = new ProgressTracker({ caption: 'Processing...' }); * progress.fillSlowly(); * ``` * * @param options Optional options. */ fillSlowly({ stopBeforeFinishing }?: { stopBeforeFinishing?: boolean | undefined; }): void; set(value: number): void; finish(): void; get caption(): string; setCaption(caption: string): void; get done(): boolean; get progress(): number; get weight(): number; get observer(): ProgressObserver; get loadingListener(): Listener; pipe(receiver: ProgressReceiver): void; addEventListener(type: string, listener: TSCompatibleListener): void; removeEventListener(type: string, listener: TSCompatibleListener): void; private notifyProgress; private notifyDone; } /** * Other WebAssembly declarations, for compatibility with older versions of * Typescript */ export declare namespace Emscripten { export interface RootFS extends Emscripten.FileSystemInstance { filesystems: Record; } export interface FileSystemType { mount(mount: FS.Mount): FS.FSNode; syncfs(mount: FS.Mount, populate: () => unknown, done: (err?: number | null) => unknown): void; } export type EnvironmentType = "WEB" | "NODE" | "SHELL" | "WORKER"; export type JSType = "number" | "string" | "array" | "boolean"; export type TypeCompatibleWithC = number | string | any[] | boolean; export type CIntType = "i8" | "i16" | "i32" | "i64"; export type CFloatType = "float" | "double"; export type CPointerType = "i8*" | "i16*" | "i32*" | "i64*" | "float*" | "double*" | "*"; export type CType = CIntType | CFloatType | CPointerType; export interface CCallOpts { async?: boolean | undefined; } type NamespaceToInstance = { [K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : never; }; export type FileSystemInstance = NamespaceToInstance & { mkdirTree(path: string): void; lookupPath(path: string, opts?: any): FS.Lookup; }; export interface EmscriptenModule { print(str: string): void; printErr(str: string): void; arguments: string[]; environment: Emscripten.EnvironmentType; preInit: Array<{ (): void; }>; preRun: Array<{ (): void; }>; postRun: Array<{ (): void; }>; onAbort: { (what: any): void; }; onRuntimeInitialized: { (): void; }; preinitializedWebGLContext: WebGLRenderingContext; noInitialRun: boolean; noExitRuntime: boolean; logReadFiles: boolean; filePackagePrefixURL: string; wasmBinary: ArrayBuffer; destroy(object: object): void; getPreloadedPackage(remotePackageName: string, remotePackageSize: number): ArrayBuffer; instantiateWasm(imports: WebAssembly.Imports, successCallback: (module: WebAssembly.Instance) => void): WebAssembly.Exports | undefined; locateFile(url: string, scriptDirectory: string): string; onCustomMessage(event: MessageEvent): void; HEAP: Int32Array; IHEAP: Int32Array; FHEAP: Float64Array; HEAP8: Int8Array; HEAP16: Int16Array; HEAP32: Int32Array; HEAPU8: Uint8Array; HEAPU16: Uint16Array; HEAPU32: Uint32Array; HEAPF32: Float32Array; HEAPF64: Float64Array; HEAP64: BigInt64Array; HEAPU64: BigUint64Array; TOTAL_STACK: number; TOTAL_MEMORY: number; FAST_MEMORY: number; addOnPreRun(cb: () => any): void; addOnInit(cb: () => any): void; addOnPreMain(cb: () => any): void; addOnExit(cb: () => any): void; addOnPostRun(cb: () => any): void; preloadedImages: any; preloadedAudios: any; _malloc(size: number): number; _free(ptr: number): void; } /** * A factory function is generated when setting the `MODULARIZE` build option * to `1` in your Emscripten build. It return a Promise that resolves to an * initialized, ready-to-call `EmscriptenModule` instance. * * By default, the factory function will be named `Module`. It's recommended * to use the `EXPORT_ES6` option, in which the factory function will be the * default export. If used without `EXPORT_ES6`, the factory function will be * a global variable. You can rename the variable using the `EXPORT_NAME` * build option. It's left to you to export any global variables as needed in * your application's types. * @param moduleOverrides Default properties for the initialized module. */ export type EmscriptenModuleFactory = (moduleOverrides?: Partial) => Promise; export namespace FS { interface Lookup { path: string; node: FSNode; } interface Analyze { isRoot: boolean; exists: boolean; error: Error; name: string; path: Lookup["path"]; object: Lookup["node"]; parentExists: boolean; parentPath: Lookup["path"]; parentObject: Lookup["node"]; } interface Mount { type: Emscripten.FileSystemType; opts: Record; mountpoint: string; mounts: Mount[]; root: FSNode; } class FSStream { constructor(); object: FSNode; readonly isRead: boolean; readonly isWrite: boolean; readonly isAppend: boolean; flags: number; position: number; } class FSNode { parent: FSNode; mount: Mount; mounted?: Mount; id: number; name: string; mode: number; rdev: number; readMode: number; writeMode: number; constructor(parent: FSNode, name: string, mode: number, rdev: number); read: boolean; write: boolean; readonly isFolder: boolean; readonly isDevice: boolean; readonly isSharedFS?: boolean; } interface ErrnoError extends Error { name: "ErronoError"; errno: number; code: string; } function lookupPath(path: string, opts: any): Lookup; function getPath(node: FSNode): string; function analyzePath(path: string, dontResolveLastLink?: boolean): Analyze; function isFile(mode: number): boolean; function isDir(mode: number): boolean; function isLink(mode: number): boolean; function isChrdev(mode: number): boolean; function isBlkdev(mode: number): boolean; function isFIFO(mode: number): boolean; function isSocket(mode: number): boolean; function major(dev: number): number; function minor(dev: number): number; function makedev(ma: number, mi: number): number; function registerDevice(dev: number, ops: any): void; function syncfs(populate: boolean, callback: (e: any) => any): void; function syncfs(callback: (e: any) => any, populate?: boolean): void; function mount(type: Emscripten.FileSystemType, opts: any, mountpoint: string): any; function unmount(mountpoint: string): void; function mkdir(path: string, mode?: number): any; function mkdev(path: string, mode?: number, dev?: number): any; function symlink(oldpath: string, newpath: string): any; function rename(old_path: string, new_path: string): void; function rmdir(path: string): void; function readdir(path: string): any; function unlink(path: string): void; function readlink(path: string): string; function stat(path: string, dontFollow?: boolean): any; function lstat(path: string): any; function chmod(path: string, mode: number, dontFollow?: boolean): void; function lchmod(path: string, mode: number): void; function fchmod(fd: number, mode: number): void; function chown(path: string, uid: number, gid: number, dontFollow?: boolean): void; function lchown(path: string, uid: number, gid: number): void; function fchown(fd: number, uid: number, gid: number): void; function truncate(path: string, len: number): void; function ftruncate(fd: number, len: number): void; function utime(path: string, atime: number, mtime: number): void; function open(path: string, flags: string, mode?: number, fd_start?: number, fd_end?: number): FSStream; function close(stream: FSStream): void; function llseek(stream: FSStream, offset: number, whence: number): any; function read(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number): number; function write(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position?: number, canOwn?: boolean): number; function allocate(stream: FSStream, offset: number, length: number): void; function mmap(stream: FSStream, buffer: ArrayBufferView, offset: number, length: number, position: number, prot: number, flags: number): any; function ioctl(stream: FSStream, cmd: any, arg: any): any; function readFile(path: string, opts: { encoding: "binary"; flags?: string | undefined; }): Uint8Array; function readFile(path: string, opts: { encoding: "utf8"; flags?: string | undefined; }): string; function readFile(path: string, opts?: { flags?: string | undefined; }): Uint8Array; function writeFile(path: string, data: string | ArrayBufferView, opts?: { flags?: string | undefined; }): void; function cwd(): string; function chdir(path: string): void; function init(input: null | (() => number | null), output: null | ((c: number) => any), error: null | ((c: number) => any)): void; function createLazyFile(parent: string | FSNode, name: string, url: string, canRead: boolean, canWrite: boolean): FSNode; function createPreloadedFile(parent: string | FSNode, name: string, url: string, canRead: boolean, canWrite: boolean, onload?: () => void, onerror?: () => void, dontCreateFile?: boolean, canOwn?: boolean): void; function createDataFile(parent: string | FSNode, name: string, data: ArrayBufferView, canRead: boolean, canWrite: boolean, canOwn: boolean): FSNode; } export const MEMFS: Emscripten.FileSystemType; export const NODEFS: Emscripten.FileSystemType; export const IDBFS: Emscripten.FileSystemType; export const PROXYFS: Emscripten.FileSystemType; type StringToType = R extends Emscripten.JSType ? { number: number; string: string; array: number[] | string[] | boolean[] | Uint8Array | Int8Array; boolean: boolean; null: null; }[R] : never; type ArgsToType> = Extract<{ [P in keyof T]: StringToType; }, any[]>; type ReturnToType = R extends null ? null : StringToType>; export function cwrap | [ ], R extends Emscripten.JSType | null>(ident: string, returnType: R, argTypes: I, opts?: Emscripten.CCallOpts): (...arg: ArgsToType) => ReturnToType; export function ccall | [ ], R extends Emscripten.JSType | null>(ident: string, returnType: R, argTypes: I, args: ArgsToType, opts?: Emscripten.CCallOpts): ReturnToType; export function setValue(ptr: number, value: any, type: Emscripten.CType, noSafe?: boolean): void; export function getValue(ptr: number, type: Emscripten.CType, noSafe?: boolean): number; export function allocate(slab: number[] | ArrayBufferView | number, types: Emscripten.CType | Emscripten.CType[], allocator: number, ptr?: number): number; export function stackAlloc(size: number): number; export function stackSave(): number; export function stackRestore(ptr: number): void; export function UTF8ToString(ptr: number, maxBytesToRead?: number): string; export function stringToUTF8(str: string, outPtr: number, maxBytesToRead?: number): void; export function lengthBytesUTF8(str: string): number; export function allocateUTF8(str: string): number; export function allocateUTF8OnStack(str: string): number; export function UTF16ToString(ptr: number): string; export function stringToUTF16(str: string, outPtr: number, maxBytesToRead?: number): void; export function lengthBytesUTF16(str: string): number; export function UTF32ToString(ptr: number): string; export function stringToUTF32(str: string, outPtr: number, maxBytesToRead?: number): void; export function lengthBytesUTF32(str: string): number; export function intArrayFromString(stringy: string, dontAddNull?: boolean, length?: number): number[]; export function intArrayToString(array: number[]): string; export function writeStringToMemory(str: string, buffer: number, dontAddNull: boolean): void; export function writeArrayToMemory(array: number[], buffer: number): void; export function writeAsciiToMemory(str: string, buffer: number, dontAddNull: boolean): void; export function addRunDependency(id: any): void; export function removeRunDependency(id: any): void; export function addFunction(func: (...args: any[]) => any, signature?: string): number; export function removeFunction(funcPtr: number): void; export const ALLOC_NORMAL: number; export const ALLOC_STACK: number; export const ALLOC_STATIC: number; export const ALLOC_DYNAMIC: number; export const ALLOC_NONE: number; export {}; } export interface RmDirOptions { /** * If true, recursively removes the directory and all its contents. * Default: true. */ recursive?: boolean; } export interface ListFilesOptions { /** * If true, prepend given folder path to all file names. * Default: false. */ prependPath: boolean; } export type RuntimeType = "NODE" | "WEB" | "WORKER"; export type PHPRuntimeId = number; export interface PHPResponseData { /** * Response headers. */ readonly headers: Record; /** * Response body. Contains the output from `echo`, * `print`, inline HTML etc. */ readonly bytes: Uint8Array; /** * Stderr contents, if any. */ readonly errors: string; /** * The exit code of the script. `0` is a success, while * `1` and `2` indicate an error. */ readonly exitCode: number; /** * Response HTTP status code, e.g. 200. */ readonly httpStatusCode: number; } declare class StreamedPHPResponse { #private; /** * Response body. Contains the output from `echo`, * `print`, inline HTML etc. */ readonly stdout: ReadableStream; /** * Stderr contents, if any. */ readonly stderr: ReadableStream; /** * The exit code of the script. `0` is a success, anything * else is an error. */ readonly exitCode: Promise; private cachedParsedHeaders; private cachedStdoutBytes; private cachedStderrText; constructor(headers: ReadableStream, stdout: ReadableStream, stderr: ReadableStream, exitCode: Promise); /** * Creates a StreamedPHPResponse from a buffered PHPResponse. * Useful for unifying response handling when both types may be returned. */ static fromPHPResponse(response: PHPResponse): StreamedPHPResponse; /** * Creates a StreamedPHPResponse for a given HTTP status code. * Shorthand for `StreamedPHPResponse.fromPHPResponse(PHPResponse.forHttpCode(...))`. */ static forHttpCode(httpStatusCode: number, text?: string): StreamedPHPResponse; /** * Returns the raw headers stream for serialization purposes. * For parsed headers, use the `headers` property instead. */ getHeadersStream(): ReadableStream; /** * True if the response is successful (HTTP status code 200-399), * false otherwise. */ ok(): Promise; /** * Resolves when the response has finished processing – either successfully or not. */ get finished(): Promise; /** * Resolves once HTTP headers are available. */ get headers(): Promise>; /** * Resolves once HTTP status code is available. */ get httpStatusCode(): Promise; /** * Exposes the stdout bytes as they're produced by the PHP instance */ get stdoutText(): Promise; /** * Exposes the stdout bytes as they're produced by the PHP instance */ get stdoutBytes(): Promise; /** * Exposes the stderr bytes as they're produced by the PHP instance */ get stderrText(): Promise; private getParsedHeaders; } /** * PHP response. Body is an `ArrayBuffer` because it can * contain binary data. * * This type is used in Comlink.transferHandlers.set('PHPResponse', \{ ... \}) * so be sure to update that if you change this type. */ export declare class PHPResponse implements PHPResponseData { /** @inheritDoc */ readonly headers: Record; /** @inheritDoc */ readonly bytes: Uint8Array; /** @inheritDoc */ readonly errors: string; /** @inheritDoc */ readonly exitCode: number; /** @inheritDoc */ readonly httpStatusCode: number; constructor(httpStatusCode: number, headers: Record, body: Uint8Array, errors?: string, exitCode?: number); static forHttpCode(httpStatusCode: number, text?: string): PHPResponse; static fromRawData(data: PHPResponseData): PHPResponse; static fromStreamedResponse(streamedResponse: StreamedPHPResponse): Promise; /** * True if the response is successful (HTTP status code 200-399), * false otherwise. */ ok(): boolean; toRawData(): PHPResponseData; /** * Response body as JSON. */ get json(): any; /** * Response body as text. */ get text(): string; } /** * Result of acquiring a PHP instance. * The `reap` function should be called when done with the instance. */ export interface AcquiredPHP { php: PHP; /** * Release the PHP instance back to the pool (for multi-instance managers) * or mark it as idle (for single-instance managers). */ reap: () => void; } /** * Minimal interface for managing PHP instances. * * This interface allows PHPRequestHandler to work with different * instance management strategies: * - PHPProcessManager: Multiple PHP instances with concurrency control * - SinglePHPInstanceManager: Single PHP instance for CLI contexts */ export interface PHPInstanceManager extends AsyncDisposable { /** * Get the primary PHP instance. * This instance is persistent and never killed. */ getPrimaryPhp(): Promise; /** * Acquire a PHP instance for processing a request. * * @returns An acquired PHP instance with a reap function. */ acquirePHPInstance(): Promise; } export type PHPFactoryOptions = { isPrimary: boolean; }; export type RewriteRule = { match: RegExp; replacement: string; }; export type FileNotFoundToResponse = { type: "response"; response: PHPResponse; }; export type FileNotFoundToInternalRedirect = { type: "internal-redirect"; uri: string; }; export type FileNotFoundTo404 = { type: "404"; }; export type FileNotFoundAction = FileNotFoundToResponse | FileNotFoundToInternalRedirect | FileNotFoundTo404; export type FileNotFoundGetActionCallback = (relativePath: string) => FileNotFoundAction; /** * Interface for cookie storage implementations. * This allows different cookie handling strategies to be used with the PHP request handler. */ export interface CookieStore { /** * Processes and stores cookies from response headers * @param headers Response headers containing Set-Cookie directives */ rememberCookiesFromResponseHeaders(headers: Record): void; /** * Gets the cookie header string for the next request * @returns Formatted cookie header string */ getCookieRequestHeader(): string; } /** * Maps a URL path prefix to an absolute filesystem path. * Similar to Nginx's `alias` directive or Apache's `Alias` directive. * * @example * ```ts * // Requests to /phpmyadmin/* will be served from /tools/phpmyadmin/* * { urlPrefix: '/phpmyadmin', fsPath: '/tools/phpmyadmin' } * ``` */ export type PathAlias = { /** * The URL path prefix to match (e.g., '/phpmyadmin'). */ urlPrefix: string; /** * The absolute filesystem path to serve files from. */ fsPath: string; }; export interface BaseConfiguration { /** * The directory in the PHP filesystem where the server will look * for the files to serve. Default: `/var/www`. */ documentRoot?: string; /** * Request Handler URL. Used to populate $_SERVER details like HTTP_HOST. */ absoluteUrl?: string; /** * Rewrite rules */ rewriteRules?: RewriteRule[]; /** * Path aliases that map URL prefixes to filesystem paths outside * the document root. Similar to Nginx's `alias` directive. * * @example * ```ts * pathAliases: [ * { urlPrefix: '/phpmyadmin', fsPath: '/tools/phpmyadmin' } * ] * ``` */ pathAliases?: PathAlias[]; /** * A callback that decides how to handle a file-not-found condition for a * given request URI. */ getFileNotFoundAction?: FileNotFoundGetActionCallback; } export type PHPRequestHandlerFactoryArgs = PHPFactoryOptions & { requestHandler: PHPRequestHandler; }; export type PHPRequestHandlerConfiguration = BaseConfiguration & { cookieStore?: CookieStore | false; /** * Provide a single PHP instance directly. * PHPRequestHandler will create a SinglePHPInstanceManager internally. * This is the simplest option for CLI contexts with a single PHP instance. */ php?: PHP; /** * Provide a factory function to create PHP instances. * PHPRequestHandler will create a PHPProcessManager internally. */ phpFactory?: (requestHandler: PHPRequestHandlerFactoryArgs) => Promise; /** * The maximum number of PHP instances that can exist at * the same time. Only used when phpFactory is provided. */ maxPhpInstances?: number; }; /** * Handles HTTP requests using PHP runtime as a backend. * * @public * @example Use PHPRequestHandler implicitly with a new PHP instance: * ```js * import { PHP } from '@php-wasm/web'; * * const php = await PHP.load( '7.4', { * requestHandler: { * // PHP FS path to serve the files from: * documentRoot: '/www', * * // Used to populate $_SERVER['SERVER_NAME'] etc.: * absoluteUrl: 'http://127.0.0.1' * } * } ); * * php.mkdirTree('/www'); * php.writeFile('/www/index.php', '; /** * Converts a path to an absolute URL based at the PHPRequestHandler * root. * * @param path The server path to convert to an absolute URL. * @returns The absolute URL. */ pathToInternalUrl(path: string): string; /** * Converts an absolute URL based at the PHPRequestHandler to a relative path * without the server pathname and scope. * * @param internalUrl An absolute URL based at the PHPRequestHandler root. * @returns The relative path. */ internalUrlToPath(internalUrl: string): string; /** * The absolute URL of this PHPRequestHandler instance. */ get absoluteUrl(): string; /** * The directory in the PHP filesystem where the server will look * for the files to serve. Default: `/var/www`. */ get documentRoot(): string; /** * Serves the request – either by serving a static file, or by * dispatching it to the PHP runtime. * * The request() method mode behaves like a web server and only works if * the PHP was initialized with a `requestHandler` option (which the online * version of WordPress Playground does by default). * * In the request mode, you pass an object containing the request information * (method, headers, body, etc.) and the path to the PHP file to run: * * ```ts * const php = PHP.load('7.4', { * requestHandler: { * documentRoot: "/www" * } * }) * php.writeFile("/www/index.php", `; /** * Serves the request with streaming support – returns a StreamedPHPResponse * that allows processing the response body incrementally without buffering * the entire response in memory. * * This is useful for large file downloads (>2GB) that would otherwise * exceed JavaScript's Uint8Array size limits. * * @param request - PHP Request data. * @returns A StreamedPHPResponse. */ requestStreamed(request: PHPRequest): Promise; /** * Computes the essential $_SERVER entries for a request. * * php_wasm.c sets some defaults, assuming it runs as a CLI script. * This function overrides them with the values correct in the request * context. * * @TODO: Consolidate the $_SERVER setting logic into a single place instead * of splitting it between the C SAPI and the TypeScript code. The PHP * class has a `.cli()` method that could take care of the CLI-specific * $_SERVER values. * * Path and URL-related $_SERVER entries are theoretically documented * at https://www.php.net/manual/en/reserved.variables.server.php, * but that page is not very helpful in practice. Here are tables derived * by interacting with PHP servers: * * ## PHP Dev Server * * Setup: * – `/home/adam/subdir/script.php` file contains `` * – `php -S 127.0.0.1:8041` running in `/home/adam` directory * – A request is sent to `http://127.0.0.1:8041/subdir/script.php/b.php/c.php` * * Results: * * $_SERVER['REQUEST_URI'] | `/subdir/script.php/b.php/c.php` * $_SERVER['SCRIPT_NAME'] | `/subdir/script.php` * $_SERVER['SCRIPT_FILENAME']| `/home/adam/subdir/script.php` * $_SERVER['PATH_INFO'] | `/b.php/c.php` * $_SERVER['PHP_SELF'] | `/subdir/script.php/b.php/c.php` * * ## Apache – rewriting rules * * Setup: * – `/var/www/html/subdir/script.php` file contains `` * – Apache is listening on port 8041 * – The document root is `/var/www/html` * – A request is sent to `http://127.0.0.1:8041/api/v1/user/123` * * .htaccess file: * * ```apache * RewriteEngine On * RewriteRule ^api/v1/user/([0-9]+)$ /subdir/script.php?endpoint=user&id=$1 [L,QSA] * ``` * * Results: * * ``` * $_SERVER['REQUEST_URI'] | /api/v1/user/123 * $_SERVER['SCRIPT_NAME'] | /subdir/script.php * $_SERVER['SCRIPT_FILENAME'] | /var/www/html/subdir/script.php * $_SERVER['PATH_INFO'] | (key not set) * $_SERVER['PHP_SELF'] | /subdir/script.php * $_SERVER['QUERY_STRING'] | endpoint=user&id=123 * $_SERVER['REDIRECT_STATUS'] | 200 * $_SERVER['REDIRECT_URL'] | /api/v1/user/123 * $_SERVER['REDIRECT_QUERY_STRING'] | endpoint=user&id=123 * === $_GET Variables === * $_GET['endpoint'] | user * $_GET['id'] | 123 * ``` * * ## Apache – vanilla request * * Setup: * – The same as above. * – A request sent http://localhost:8041/subdir/script.php?param=value * * Results: * * ``` * $_SERVER['REQUEST_URI'] | /subdir/script.php?param=value * $_SERVER['SCRIPT_NAME'] | /subdir/script.php * $_SERVER['SCRIPT_FILENAME'] | /var/www/html/subdir/script.php * $_SERVER['PATH_INFO'] | (key not set) * $_SERVER['PHP_SELF'] | /subdir/script.php * $_SERVER['REDIRECT_URL'] | (key not set) * $_SERVER['REDIRECT_STATUS'] | (key not set) * $_SERVER['QUERY_STRING'] | param=value * $_SERVER['REQUEST_METHOD'] | GET * $_SERVER['DOCUMENT_ROOT'] | /var/www/html * * === $_GET Variables === * $_GET['param'] | value * ``` */ private prepare_$_SERVER_superglobal; [Symbol.asyncDispose](): Promise; } declare const __private__dont__use: unique symbol; export type UnmountFunction = (() => Promise) | (() => any); export type MountHandler = (php: PHP, FS: Emscripten.RootFS, vfsMountPoint: string) => UnmountFunction | Promise; declare class PHP implements Disposable { #private; protected [__private__dont__use]: any; requestHandler?: PHPRequestHandler; /** * An exclusive lock that prevent multiple requests from running at * the same time. */ semaphore: Semaphore; /** * Initializes a PHP runtime. * * @internal * @param PHPRuntime - Optional. PHP Runtime ID as initialized by loadPHPRuntime. * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized. */ constructor(PHPRuntimeId?: PHPRuntimeId); /** * Adds an event listener for a PHP event. * @param eventType - The type of event to listen for. * @param listener - The listener function to be called when the event is triggered. */ addEventListener(eventType: PHPEvent["type"] | "*", listener: PHPEventListener): void; /** * Removes an event listener for a PHP event. * @param eventType - The type of event to remove the listener from. * @param listener - The listener function to be removed. */ removeEventListener(eventType: PHPEvent["type"] | "*", listener: PHPEventListener): void; dispatchEvent(event: Event): void; /** * Listens to message sent by the PHP code. * * To dispatch messages, call: * * post_message_to_js(string $data) * * Arguments: * $data (string) – Data to pass to JavaScript. * * @example * * ```ts * const php = await PHP.load('8.0'); * * php.onMessage( * // The data is always passed as a string * function (data: string) { * // Let's decode and log the data: * console.log(JSON.parse(data)); * } * ); * * // Now that we have a listener in place, let's * // dispatch a message: * await php.run({ * code: ` '15', * 'post_title' => 'This is a blog post!' * ]) * )); * `, * }); * ``` * * @param listener Callback function to handle the message. */ onMessage(listener: MessageListener): () => Promise; setSpawnHandler(handler: SpawnHandler | string): Promise; /** * Overrides spawning of a specific binary, e.g. `sendmail`. The override * applies to any argv[0] whose basename matches `command` and takes * precedence over the handler installed via setSpawnHandler(). */ setCommandSpawnHandler(command: string, handler: SpawnHandler): void; /** @deprecated Use PHPRequestHandler instead. */ get absoluteUrl(): string; /** @deprecated Use PHPRequestHandler instead. */ get documentRoot(): string; /** @deprecated Use PHPRequestHandler instead. */ pathToInternalUrl(path: string): string; /** @deprecated Use PHPRequestHandler instead. */ internalUrlToPath(internalUrl: string): string; initializeRuntime(runtimeId: PHPRuntimeId): void; /** @inheritDoc */ setSapiName(newName: string): Promise; /** * Changes the current working directory in the PHP filesystem. * This is the directory that will be used as the base for relative paths. * For example, if the current working directory is `/root/php`, and the * path is `data`, the absolute path will be `/root/php/data`. * * @param path - The new working directory. */ chdir(path: string): void; /** * Gets the current working directory in the PHP filesystem. * * @returns The current working directory. */ cwd(): any; /** * Changes the permissions of a file or directory. * @param path - The path to the file or directory. * @param mode - The new permissions. */ chmod(path: string, mode: number): void; /** * Do not use. Use new PHPRequestHandler() instead. * @deprecated */ request(request: PHPRequest): Promise; /** * Runs PHP code. * * This low-level method directly interacts with the WebAssembly * PHP interpreter. * * Every time you call run(), it prepares the PHP * environment and: * * * Resets the internal PHP state * * Populates superglobals ($_SERVER, $_GET, etc.) * * Handles file uploads * * Populates input streams (stdin, argv, etc.) * * Sets the current working directory * * You can use run() in two primary modes: * * ### Code snippet mode * * In this mode, you pass a string containing PHP code to run. * * ```ts * const result = await php.run({ * code: `; /** * Runs PHP code and returns a StreamedPHPResponse object that can be used to * process the output incrementally. * * This low-level method directly interacts with the WebAssembly * PHP interpreter and provides streaming capabilities for processing * PHP output as it becomes available. * * Every time you call stream(), it prepares the PHP * environment and: * * * Resets the internal PHP state * * Populates superglobals ($_SERVER, $_GET, etc.) * * Handles file uploads * * Populates input streams (stdin, argv, etc.) * * Sets the current working directory * * You can use stream() in two primary modes: * * ### Code snippet mode * * In this mode, you pass a string containing PHP code to run. * * ```ts * const streamedResponse = await php.stream({ * code: `; /** * Defines a constant in the PHP runtime. * @param key - The name of the constant. * @param value - The value of the constant. */ defineConstant(key: string, value: string | boolean | number | null): void; /** * Recursively creates a directory with the given path in the PHP filesystem. * For example, if the path is `/root/php/data`, and `/root` already exists, * it will create the directories `/root/php` and `/root/php/data`. * * @param path - The directory path to create. */ mkdir(path: string): void; /** * @deprecated Use mkdir instead. */ mkdirTree(path: string): void; /** * Reads a file from the PHP filesystem and returns it as a string. * * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist. * @param path - The file path to read. * @returns The file contents. */ readFileAsText(path: string): string; /** * Reads a file from the PHP filesystem and returns it as an array buffer. * * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist. * @param path - The file path to read. * @returns The file contents. */ readFileAsBuffer(path: string): Uint8Array; /** * Overwrites data in a file in the PHP filesystem. * Creates a new file if one doesn't exist yet. * * @param path - The file path to write to. * @param data - The data to write to the file. */ writeFile(path: string, data: string | Uint8Array | Buffer): void; /** * Removes a file from the PHP filesystem. * * @throws {@link @php-wasm/universal:ErrnoError} – If the file doesn't exist. * @param path - The file path to remove. */ unlink(path: string): void; /** * Moves a file or directory in the PHP filesystem to a * new location. * * @param fromPath The path to rename. * @param toPath The new path. */ mv(fromPath: string, toPath: string): void; /** * Copies a file or directory in the PHP filesystem to a * new location. * * @param fromPath The source path. * @param toPath The target path. */ cp(fromPath: string, toPath: string): void; /** * Removes a directory from the PHP filesystem. * * @param path The directory path to remove. * @param options Options for the removal. */ rmdir(path: string, options?: RmDirOptions): void; /** * Lists the files and directories in the given directory. * * @param path - The directory path to list. * @param options - Options for the listing. * @returns The list of files and directories in the given directory. */ listFiles(path: string, options?: ListFilesOptions): string[]; /** * Checks if a directory exists in the PHP filesystem. * * @param path – The path to check. * @returns True if the path is a directory, false otherwise. */ isDir(path: string): boolean; /** * Checks if a file exists in the PHP filesystem. * * @param path – The path to check. * @returns True if the path is a file, false otherwise. */ isFile(path: string): boolean; /** * Creates a symlink in the PHP filesystem. * @param target * @param path */ symlink(target: string, path: string): any; /** * Checks if a path is a symlink in the PHP filesystem. * * @param path * @returns True if the path is a symlink, false otherwise. */ isSymlink(path: string): boolean; /** * Reads the target of a symlink in the PHP filesystem. * * @param path * @returns The target of the symlink. */ readlink(path: string): string; /** * Resolves the real path of a file in the PHP filesystem. * @param path * @returns The real path of the file. */ realpath(path: string): string; /** * Checks if a file (or a directory) exists in the PHP filesystem. * * @param path - The file path to check. * @returns True if the file exists, false otherwise. */ fileExists(path: string): boolean; /** * Enables inline PHP runtime rotation after a certain number of requests * or an internal crash. */ enableRuntimeRotation(options: { recreateRuntime: () => Promise | number; maxRequests?: number; }): void; private rotateRuntime; /** * Hot-swaps the PHP runtime for a new one without * interrupting the operations of this PHP instance. * * @param runtime */ hotSwapPHPRuntime(runtime: number): Promise; /** * Mounts a filesystem to a given path in the PHP filesystem. * * The returned unmount function removes the mount from runtime-rotation * tracking on success or ordinary failure. `MountStillActiveError` leaves it * tracked because the handler guarantees the mount remains live and retryable. * * @param virtualFSPath - Where to mount it in the PHP virtual filesystem. * @param mountHandler - The mount handler to use. * @return Unmount function to unmount the filesystem. */ mount(virtualFSPath: string, mountHandler: MountHandler): Promise; /** * Starts a PHP CLI session with given arguments. * * This method can only be used when PHP was compiled with the CLI SAPI * and it cannot be used in conjunction with `run()`. * * Once this method finishes running, the PHP instance is no * longer usable and should be discarded. This is because PHP * internally cleans up all the resources and calls exit(). * * @param argv - The arguments to pass to the CLI. * @returns The exit code of the CLI session. */ cli(argv: string[], options?: { env?: Record; cwd?: string; }): Promise; /** * Runs an arbitrary CLI command using the spawn handler associated * with this PHP instance. * * @param argv * @param options * @returns StreamedPHPResponse. */ private subProcess; setSkipShebang(shouldSkip: boolean): void; exit(code?: number): void; [Symbol.dispose](): void; } export type LimitedPHPApi = Pick & { documentRoot: PHP["documentRoot"]; absoluteUrl: PHP["absoluteUrl"]; addEventListener: PHP["addEventListener"] | ((event: string, listener: (event: any) => any) => void); removeEventListener: PHP["removeEventListener"] | ((event: string, listener: (event: any) => any) => void); }; export type PHPWorkerEvent = PHPEvent | { type: string; }; export type PHPWorkerEventListener = (event: PHPWorkerEvent) => void; declare class PHPWorker implements LimitedPHPApi, AsyncDisposable { #private; /** @inheritDoc @php-wasm/universal!RequestHandler.absoluteUrl */ absoluteUrl: string; /** @inheritDoc @php-wasm/universal!RequestHandler.documentRoot */ documentRoot: string; private chroot; onMessageListeners: MessageListener[]; /** @inheritDoc */ constructor(requestHandler?: PHPRequestHandler, monitor?: EmscriptenDownloadMonitor); __internal_setRequestHandler(requestHandler: PHPRequestHandler): void; /** * @internal * @deprecated * Do not use this method directly in the code consuming * the web API. It will change or even be removed without * a warning. */ protected __internal_getPHP(): PHP | undefined; /** * @internal * @deprecated * Do not use this method directly in the code consuming * the web API. It will change or even be removed without * a warning. */ protected __internal_getRequestHandler(): PHPRequestHandler; setPrimaryPHP(php: PHP): Promise; /** @inheritDoc @php-wasm/universal!PHPRequestHandler.pathToInternalUrl */ pathToInternalUrl(path: string): string; /** @inheritDoc @php-wasm/universal!PHPRequestHandler.internalUrlToPath */ internalUrlToPath(internalUrl: string): string; /** * The onDownloadProgress event listener. */ onDownloadProgress(callback: (progress: CustomEvent) => void): Promise; /** @inheritDoc @php-wasm/universal!PHP.mv */ mv(fromPath: string, toPath: string): Promise; /** @inheritDoc @php-wasm/universal!PHP.cp */ cp(fromPath: string, toPath: string): Promise; /** @inheritDoc @php-wasm/universal!PHP.rmdir */ rmdir(path: string, options?: RmDirOptions): Promise; /** @inheritDoc @php-wasm/universal!PHPRequestHandler.request */ request(request: PHPRequest): Promise; /** * Handles a request with streaming support for large responses. * Returns a StreamedPHPResponse that allows processing the response * body incrementally without buffering the entire response in memory. * * This is useful for large file downloads (>2GB) that would otherwise * exceed JavaScript's Uint8Array size limits. * * @param request - PHP Request data. */ requestStreamed(request: PHPRequest): Promise; /** @inheritDoc @php-wasm/universal!/PHP.run */ run(request: PHPRunOptions): Promise; /** * Starts a PHP request and returns its output streams before PHP exits. * * A pooled PHP instance remains checked out until `response.finished` * settles. If the request fails before returning a response, the instance * is released immediately. A non-zero PHP exit is exposed through * `response.exitCode` instead of making this method reject. * * @param request - PHP code or script path, request metadata, and environment. * @returns A streamed response whose output can be consumed incrementally. * @throws When a PHP instance cannot be acquired or the request cannot start. */ runStream(request: PHPRunOptions): Promise; /** @inheritDoc @php-wasm/universal!/PHP.cli */ cli(argv: string[], options?: { env?: Record; }): Promise; /** @inheritDoc @php-wasm/universal!/PHP.chdir */ chdir(path: string): void; /** @inheritDoc @php-wasm/universal!/PHP.chdir */ cwd(): string; /** * @returns A PHP instance with a consistent chroot. */ private acquirePHPInstance; /** @inheritDoc @php-wasm/universal!/PHP.setSapiName */ setSapiName(newName: string): void; /** @inheritDoc @php-wasm/universal!/PHP.mkdir */ mkdir(path: string): void; /** @inheritDoc @php-wasm/universal!/PHP.mkdirTree */ mkdirTree(path: string): void; /** @inheritDoc @php-wasm/universal!/PHP.readFileAsText */ readFileAsText(path: string): string; /** @inheritDoc @php-wasm/universal!/PHP.readFileAsBuffer */ readFileAsBuffer(path: string): Uint8Array; /** @inheritDoc @php-wasm/universal!/PHP.writeFile */ writeFile(path: string, data: string | Uint8Array): void; /** @inheritDoc @php-wasm/universal!/PHP.unlink */ unlink(path: string): void; /** @inheritDoc @php-wasm/universal!/PHP.listFiles */ listFiles(path: string, options?: ListFilesOptions): string[]; /** @inheritDoc @php-wasm/universal!/PHP.isDir */ isDir(path: string): boolean; /** @inheritDoc @php-wasm/universal!/PHP.isFile */ isFile(path: string): boolean; /** @inheritDoc @php-wasm/universal!/PHP.fileExists */ fileExists(path: string): boolean; /** @inheritDoc @php-wasm/universal!/PHP.onMessage */ onMessage(listener: MessageListener): () => Promise; /** @inheritDoc @php-wasm/universal!/PHP.defineConstant */ defineConstant(key: string, value: string | boolean | number | null): void; /** @inheritDoc @php-wasm/universal!/PHP.addEventListener */ addEventListener(eventType: PHPWorkerEvent["type"], listener: PHPWorkerEventListener): void; /** * Removes an event listener for a PHP event. * @param eventType - The type of event to remove the listener from. * @param listener - The listener function to be removed. */ removeEventListener(eventType: PHPWorkerEvent["type"], listener: PHPWorkerEventListener): void; protected dispatchEvent(event: EventType): void; protected registerWorkerListeners(php: PHP): void; [Symbol.asyncDispose](): Promise; protected getRequestHandler(required?: true): PHPRequestHandler; protected getRequestHandler(required: false): PHPRequestHandler | undefined; } /** * Represents an event related to the PHP request. */ export interface PHPRequestEndEvent { type: "request.end"; } /** * Represents an error event related to the PHP request. */ export interface PHPRequestErrorEvent { type: "request.error"; error: Error; source?: "request" | "php-wasm"; } /** * Represents a PHP runtime initialization event. */ export interface PHPRuntimeInitializedEvent { type: "runtime.initialized"; } /** * Emitted before the exit() method of the PHP Emscripten runtime is called. */ export interface PHPRuntimeBeforeExitEvent { type: "runtime.beforeExit"; } /** * Emitted when a filesystem write operation occurs (writeFile, mkdir, rmdir, mv, cp, unlink). * This event is used to trigger journal flushing for persistent storage. */ export interface PHPFilesystemWriteEvent { type: "filesystem.write"; } /** * Represents an event related to the PHP instance. * This is intentionally not an extension of CustomEvent * to make it isomorphic between different JavaScript runtimes. */ export type PHPEvent = PHPRequestEndEvent | PHPRequestErrorEvent | PHPRuntimeInitializedEvent | PHPRuntimeBeforeExitEvent | PHPFilesystemWriteEvent | PHPSendmailSpawnedEvent; /** * A callback function that handles PHP events. */ export type PHPEventListener = (event: PHPEvent) => void; export type UniversalPHP = LimitedPHPApi | Remote | Pooled; export type MessageListener = (data: string) => Promise | string | void; export interface EventEmitter { on(event: string, listener: (...args: any[]) => void): this; off(event: string, listener: (...args: any[]) => void): this; emit(event: string, ...args: any[]): boolean; } export type ChildProcess = EventEmitter & { stdout: EventEmitter; stderr: EventEmitter; stdin: EventEmitter & { write: (data: Uint8Array, encoding: string, cb: (err: Error | null) => void) => void; end: () => void; }; }; export type SpawnHandler = (command: string, args: string[]) => ChildProcess; export type HTTPMethod = "GET" | "POST" | "HEAD" | "OPTIONS" | "PATCH" | "PUT" | "DELETE"; export type PHPRequestHeaders = Record; export interface PHPRequest { /** * Request method. Default: `GET`. */ method?: HTTPMethod; /** * Request path or absolute URL. */ url: string; /** * Request headers. */ headers?: PHPRequestHeaders; /** * Request body. * If an object is given, the request will be encoded as multipart * and sent with a `multipart/form-data` header. */ body?: string | Uint8Array | Record; } export interface PHPRunOptions { /** * Request path following the domain:port part – * after any URL rewriting rules (e.g. apache .htaccess) * have been applied. */ relativeUri?: string; /** * Path of the .php file to execute. */ scriptPath?: string; /** * Request protocol. */ protocol?: string; /** * Request method. Default: `GET`. */ method?: HTTPMethod; /** * Request headers. */ headers?: PHPRequestHeaders; /** * Request body. */ body?: string | Uint8Array; /** * Environment variables to set for this run. */ env?: Record; /** * $_SERVER entries to set for this run. */ $_SERVER?: Record; /** * The code snippet to eval instead of a php file. */ code?: string; } /** * Output of the PHP.wasm runtime. */ export interface PHPOutput { /** Exit code of the PHP process. 0 means success, 1 and 2 mean error. */ exitCode: number; /** Stdout data */ stdout: ArrayBuffer; /** Stderr lines */ stderr: string[]; } /** * Rewrites the php.ini file with the given entries. * * @param php The PHP instance. * @param entries The entries to write to the php.ini file. */ export declare function setPhpIniEntries(php: UniversalPHP, entries: Record): Promise; /** * Emscripten's filesystem-related Exception. * * @see https://emscripten.org/docs/api_reference/Filesystem-API.html * @see https://github.com/emscripten-core/emscripten/blob/main/system/lib/libc/musl/arch/emscripten/bits/errno.h * @see https://github.com/emscripten-core/emscripten/blob/38eedc630f17094b3202fd48ac0c2c585dbea31e/system/include/wasi/api.h#L336 */ export declare class ErrnoError extends Error { constructor(errno: number, message?: string, options?: any); node?: any; errno: number; } export declare const PHPNextVersion = "next"; export type PHPNextVersion = typeof PHPNextVersion; export declare const SupportedPHPVersions: readonly [ "8.5", "8.4", "8.3", "8.2", "8.1", "8.0", "7.4" ]; export declare const LatestSupportedPHPVersion: "8.5"; export declare const SupportedPHPVersionsList: string[]; export type SupportedPHPVersion = (typeof SupportedPHPVersions)[number]; declare const LegacyPHPVersions: readonly [ "5.2" ]; export type LegacyPHPVersion = (typeof LegacyPHPVersions)[number]; export type AllPHPVersion = PHPNextVersion | SupportedPHPVersion | LegacyPHPVersion; export interface FileTree extends Record { } /** * The php.ini directive used to load the extension. Use `extension` for * regular PHP extensions and `zend_extension` for Zend extensions like Xdebug. */ export type PHPExtensionIniDirective = "extension" | "zend_extension"; export type PHPExtensionLoadDirective = PHPExtensionIniDirective | false; /** * Extension artifact manifest. Lets callers publish a matrix of `.so` files * and lets `resolvePHPExtension()` select the artifact matching the current * PHP version. External extension artifacts are JSPI-only. */ export interface PHPExtensionManifest { name: string; version?: string; mode?: "php-extension"; /** * The first directive of the generated startup `.ini` file. Defaults to * `extension`; use `zend_extension` for Zend extensions like Xdebug. * Use `false` to stage the `.so` without registering it in php.ini. */ loadWithIniDirective?: PHPExtensionLoadDirective; /** Additional `key=value` lines for the generated startup `.ini` file. */ iniEntries?: Record; /** Environment variables added before the extension is loaded. */ env?: Record; /** * VFS directory where PHP.wasm writes the extension `.so` file and its * per-extension ini file. Defaults to `PHP_EXTENSIONS_DIR`. */ extensionDir?: string; artifacts: Array<{ /** PHP major/minor version, e.g. `8.4`. */ phpVersion: string; /** Relative to the manifest URL/base URL, or an absolute URL. */ sourcePath: string; /** URL-backed files needed only by this artifact. */ extraFiles?: PHPExtensionManifestExtraFiles; }>; /** URL-backed files shared by every artifact in this manifest. */ extraFiles?: PHPExtensionManifestExtraFiles; } export interface PHPExtensionManifestExtraFiles { /** * Absolute VFS path where files and directories are written. When a * manifest declares both top-level and per-artifact `extraFiles`, the * first declared `targetPath` wins. Defaults to * `/-assets`. */ vfsRoot?: string; nodes?: Array<{ /** Joined with the group's `vfsRoot` to form the final VFS path. */ vfsPath: string; /** Defaults to "file". Only file nodes need a `sourcePath`. */ type?: "file" | "directory"; /** Relative to the manifest URL/base URL, or an absolute URL. */ sourcePath?: string; }>; } /** * Source for a PHP extension `.so`. Use `format: 'so'` when the caller has * bytes, `format: 'url'` for a direct artifact URL, and `format: 'manifest'` * when PHP.wasm should select the right artifact from a manifest. */ export type PHPExtensionSource = { format: "so"; name?: string; bytes: Uint8Array | ArrayBuffer; } | { format: "url"; name?: string; url: string | URL; } | { format: "manifest"; /** * In `@php-wasm/universal`, must be an absolute URL. `@php-wasm/node` * also accepts filesystem paths and `file:` URLs. */ manifestUrl: string | URL; } | { format: "manifest"; manifest: PHPExtensionManifest; /** Base URL for resolving relative artifact paths. */ baseUrl?: string | URL; }; export interface ResolvedInstallOptions { /** PHP major/minor version the active runtime is initializing for. */ phpVersion: string; source: PHPExtensionSource; /** Overrides the name inferred from `source`. */ name?: string; /** * The first directive of the generated startup `.ini` file. Regular * extensions need `extension=...`; Zend extensions like Xdebug need * `zend_extension=...`. */ loadWithIniDirective?: PHPExtensionLoadDirective; /** Additional `key=value` lines for the generated startup `.ini` file. */ iniEntries?: Record; /** * Sidecar files to write into the PHP VFS before the extension is loaded. * Use this for data files or dependency assets the extension expects at * runtime. */ extraFiles?: ResolvedExtraFiles; /** Environment variables added before the extension is loaded. */ env?: Record; /** * VFS directory where PHP.wasm writes the extension `.so` file and its * per-extension ini file. Defaults to `PHP_EXTENSIONS_DIR`. */ extensionDir?: string; /** * Fetch implementation used for URL and manifest sources. Runtimes may * provide environment-specific defaults; for example, `@php-wasm/node` * adds local file support. */ fetch?: typeof fetch; } /** * Sidecar files to stage next to an extension. Use this for data files or * native-library assets the extension expects at runtime. All paths are * absolute VFS paths. */ export interface ResolvedExtraFiles { /** Absolute VFS paths to create as empty directories. */ directories?: string[]; /** Map of absolute VFS paths to file contents. */ files: Record; } export type WithAPIState = { /** * Resolves to true when the remote API is ready for * Comlink communication, but not necessarily fully initialized yet. */ isConnected: () => Promise; /** * Resolves to true when the remote API is declares it's * fully loaded and ready to be used. */ isReady: () => Promise; }; export type RemoteAPI = Remote & ProxyMethods & WithAPIState; declare class StreamedFile extends File { readonly filesize: number | undefined; private readableStream; static fromArrayBuffer(arrayBuffer: Uint8Array, name: string, options?: { type?: string; filesize?: number; }): StreamedFile; /** * Creates a new StreamedFile instance. * * @param readableStream The readable stream containing the file data. * @param name The name of the file. * @param options An object containing options such as the MIME type and file size. */ constructor(readableStream: ReadableStream, name: string, options?: { type?: string; filesize?: number; }); /** * Overrides the slice() method of the File class. * * @returns A Blob representing a portion of the file. */ slice(): Blob; /** * Returns the readable stream associated with the file. * * @returns The readable stream. */ stream(): ReadableStream; /** * Loads the file data into memory and then returns it as a string. * * @returns File data as text. */ text(): Promise; /** * Loads the file data into memory and then returns it as an ArrayBuffer. * * @returns File data as an ArrayBuffer. */ arrayBuffer(): Promise; } export declare class BlueprintFilesystemRequiredError extends Error { constructor(message?: string); } /** * Error thrown when a resource could not be downloaded from a URL. */ export declare class ResourceDownloadError extends Error { readonly url: string; constructor(message: string, url: string, options?: ErrorOptions); } export declare const ResourceTypes: readonly [ "vfs", "literal", "wordpress.org/themes", "wordpress.org/plugins", "url", "git:directory", "bundled", "zip" ]; export type VFSReference = { /** Identifies the file resource as Virtual File System (VFS) */ resource: "vfs"; /** The path to the file in the VFS */ path: string; }; export type LiteralReference = { /** Identifies the file resource as a literal file */ resource: "literal"; /** The name of the file */ name: string; /** The contents of the file */ contents: string | Uint8Array; }; export type CoreThemeReference = { /** Identifies the file resource as a WordPress Core theme */ resource: "wordpress.org/themes"; /** The slug of the WordPress Core theme */ slug: string; }; export type CorePluginReference = { /** Identifies the file resource as a WordPress Core plugin */ resource: "wordpress.org/plugins"; /** The slug of the WordPress Core plugin */ slug: string; }; export type UrlReference = { /** Identifies the file resource as a URL */ resource: "url"; /** The URL of the file */ url: string; /** Optional caption for displaying a progress message */ caption?: string; }; export type GitDirectoryRefType = "branch" | "tag" | "commit" | "refname"; export type GitDirectoryReference = { /** Identifies the file resource as a git directory */ resource: "git:directory"; /** The URL of the git repository */ url: string; /** The ref (branch, tag, or commit) of the git repository */ ref: string; /** Explicit hint about the ref type (branch, tag, commit, refname) */ refType?: GitDirectoryRefType; /** The path to the directory in the git repository. Defaults to the repo root. */ path?: string; /** When true, include a `.git` directory with Git metadata (experimental). */ ".git"?: boolean; }; export interface Directory { files: FileTree; name: string; } export type DirectoryLiteralReference = Directory & { /** Identifies the file resource as a git directory */ resource: "literal:directory"; }; export type BundledReference = { /** Identifies the file resource as a Blueprint file */ resource: "bundled"; /** The path to the file in the Blueprint */ path: string; }; export type ZipWrapperReference = { /** Identifies the resource as a ZIP wrapper */ resource: "zip"; /** The inner resource to wrap in a ZIP file */ inner: FileReference | DirectoryReference; /** Optional filename for the ZIP (defaults to inner resource name + .zip) */ name?: string; }; export type FileReference = VFSReference | LiteralReference | CoreThemeReference | CorePluginReference | UrlReference | BundledReference | ZipWrapperReference; export type DirectoryReference = GitDirectoryReference | DirectoryLiteralReference; export declare abstract class Resource { /** Optional progress tracker to monitor progress */ protected _progress?: ProgressTracker; get progress(): ProgressTracker | undefined; set progress(value: ProgressTracker | undefined); /** A Promise that resolves to the file contents */ protected promise?: Promise; protected playground?: UniversalPHP; setPlayground(playground: UniversalPHP): void; abstract resolve(): Promise; /** The name of the referenced file */ abstract get name(): string; /** Whether this Resource is loaded asynchronously */ get isAsync(): boolean; /** * Creates a new Resource based on the given file reference * * @param ref The file reference to create the Resource for * @param options Additional options for the Resource * @returns A new Resource instance */ static create(ref: FileReference | DirectoryReference, { semaphore, progress, corsProxy, streamBundledFile, gitAdditionalHeadersCallback, }: { /** Optional semaphore to limit concurrent downloads */ semaphore?: Semaphore; progress?: ProgressTracker; corsProxy?: string; streamBundledFile?: StreamBundledFile; gitAdditionalHeadersCallback?: (url: string) => Record; }): Resource; } export declare abstract class ResourceDecorator extends Resource { protected resource: Resource; constructor(resource: Resource); /** @inheritDoc */ get progress(): ProgressTracker | undefined; /** @inheritDoc */ set progress(value: ProgressTracker | undefined); /** @inheritDoc */ abstract resolve(): Promise; /** @inheritDoc */ get name(): string; /** @inheritDoc */ get isAsync(): boolean; /** @inheritDoc */ setPlayground(playground: UniversalPHP): void; } /** * A `Resource` that represents a file in the VFS (virtual file system) of the * playground. */ export declare class VFSResource extends Resource { private resource; /** * Creates a new instance of `VFSResource`. * @param playground The playground client. * @param resource The VFS reference. * @param progress The progress tracker. */ constructor(resource: VFSReference, _progress?: ProgressTracker); /** @inheritDoc */ resolve(): Promise; /** @inheritDoc */ get name(): string; } /** * A `Resource` that represents a literal file. */ export declare class LiteralResource extends Resource { private resource; /** * Creates a new instance of `LiteralResource`. * @param resource The literal reference. * @param progress The progress tracker. */ constructor(resource: LiteralReference, _progress?: ProgressTracker); /** @inheritDoc */ resolve(): Promise; /** @inheritDoc */ get name(): string; } /** * A base class for `Resource`s that require fetching data from a remote URL. */ export declare abstract class FetchResource extends Resource { private corsProxy?; /** * Creates a new instance of `FetchResource`. * @param progress The progress tracker. */ constructor(_progress?: ProgressTracker, corsProxy?: string); /** @inheritDoc */ resolve(): Promise; /** * Gets the URL to fetch the data from. * @returns The URL. */ protected abstract getURL(): string; /** * Gets the caption for the progress tracker. * @returns The caption. */ protected get caption(): string; /** @inheritDoc */ get name(): string; /** @inheritDoc */ get isAsync(): boolean; } /** * A `Resource` that represents a file available from a URL. */ export declare class UrlResource extends FetchResource { private resource; private options?; /** * Creates a new instance of `UrlResource`. * @param resource The URL reference. * @param progress The progress tracker. */ constructor(resource: UrlReference, progress?: ProgressTracker, options?: { corsProxy?: string; }); /** @inheritDoc */ getURL(): string; /** @inheritDoc */ protected get caption(): string; } /** * A `Resource` that represents a WordPress core theme. */ export declare class CoreThemeResource extends FetchResource { private resource; constructor(resource: CoreThemeReference, progress?: ProgressTracker); get name(): string; getURL(): string; } /** * A resource that fetches a WordPress plugin from wordpress.org. */ export declare class CorePluginResource extends FetchResource { private resource; constructor(resource: CorePluginReference, progress?: ProgressTracker); /** @inheritDoc */ get name(): string; /** @inheritDoc */ getURL(): string; } /** * A decorator for a resource that adds caching functionality. */ export declare class CachedResource extends ResourceDecorator { protected promise?: Promise; /** @inheritDoc */ resolve(): Promise; } /** * A decorator for a resource that adds concurrency control functionality * through a semaphore. */ export declare class SemaphoreResource extends ResourceDecorator { private readonly semaphore; constructor(resource: Resource, semaphore: Semaphore); /** @inheritDoc */ resolve(): Promise; } /** * @inheritDoc activatePlugin * @example * * * { * "step": "activatePlugin", * "pluginName": "Gutenberg", * "pluginPath": "/wordpress/wp-content/plugins/gutenberg" * } * */ export interface ActivatePluginStep { step: "activatePlugin"; /** * Path to the plugin directory as absolute path * (/wordpress/wp-content/plugins/plugin-name); or the plugin entry file * relative to the plugins directory (plugin-name/plugin-name.php). */ pluginPath: string; /** Optional. Plugin name to display in the progress bar. */ pluginName?: string; } /** * Activates a WordPress plugin (if it's installed). * * @param playground The playground client. */ export declare const activatePlugin: StepHandler; /** * Changes the site URL of the WordPress installation. * * @inheritDoc defineSiteUrl */ export interface DefineSiteUrlStep { step: "defineSiteUrl"; /** The URL */ siteUrl: string; } /** * Sets [`WP_HOME`](https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#blog-address-url) and [`WP_SITEURL`](https://developer.wordpress.org/advanced-administration/wordpress/wp-config/#wp-siteurl) constants for the WordPress installation. * * Using this step on playground.wordpress.net is moot. * It is useful when building a custom Playground-based tool, like [`wp-now`](https://www.npmjs.com/package/@wp-now/wp-now), * or deploying Playground on a custom domain. * * @param playground The playground client. * @param siteUrl */ export declare const defineSiteUrl: StepHandler; export interface InstallAssetOptions { /** * The zip file to install. */ zipFile: File; /** * Target path to extract the main folder. * @example * * * const targetPath = `${await playground.documentRoot}/wp-content/plugins`; * */ targetPath: string; /** * Target folder name to install the asset into. */ targetFolderName?: string; /** * What to do if the asset already exists. */ ifAlreadyInstalled?: "overwrite" | "skip" | "error"; } /** * @inheritDoc installPlugin * @hasRunnableExample * @needsLogin * @landingPage /wp-admin/plugins.php * @example * * * { * "step": "installPlugin", * "pluginData": { * "resource": "wordpress.org/plugins", * "slug": "gutenberg" * }, * "options": { * "activate": true * } * } * * * @example * * * { * "step": "installPlugin", * "pluginData": { * "resource": "git:directory", * "url": "https://github.com/wordpress/wordpress-playground.git", * "ref": "HEAD", * "path": "wp-content/plugins/hello-dolly" * }, * "options": { * "activate": true * } * } * */ export interface InstallPluginStep extends Pick { /** * The step identifier. */ step: "installPlugin"; /** * The plugin files to install. It can be a plugin zip file, a single PHP * file, or a directory containing all the plugin files at its root. */ pluginData: FileResource | DirectoryResource; /** * @deprecated. Use 'pluginData' instead. */ pluginZipFile?: FileResource; /** * Optional installation options. */ options?: InstallPluginOptions; } export interface InstallPluginOptions { /** * Whether to activate the plugin after installing it. */ activate?: boolean; /** * Parameters to expose to the plugin during its activation hook. */ activationOptions?: Record; /** * Whether installation/activation failures should abort the Blueprint. */ onError?: "skip-plugin" | "throw"; /** * The name of the folder to install the plugin to. Defaults to guessing from pluginData */ targetFolderName?: string; /** * Human-readable plugin name for progress captions and skip warnings. */ humanReadableName?: string; } /** * Installs a WordPress plugin in the Playground. * * @param playground The playground client. * @param pluginData The plugin zip file. * @param options Optional. Set `activate` to false if you don't want to activate the plugin. */ export declare const installPlugin: StepHandler>; /** * @inheritDoc installTheme * @hasRunnableExample * @needsLogin * @example * * * { * "step": "installTheme", * "themeData": { * "resource": "wordpress.org/themes", * "slug": "pendant" * }, * "options": { * "activate": true, * "importStarterContent": true * } * } * */ export interface InstallThemeStep extends Pick { /** * The step identifier. */ step: "installTheme"; /** * The theme files to install. It can be either a theme zip file, or a * directory containing all the theme files at its root. */ themeData: FileResource | DirectoryResource; /** * @deprecated. Use 'themeData' instead. */ themeZipFile?: FileResource; /** * Optional installation options. */ options?: InstallThemeOptions; } export interface InstallThemeOptions { /** * Whether to activate the theme after installing it. */ activate?: boolean; /** * Whether to import the theme's starter content after installing it. */ importStarterContent?: boolean; /** * Whether installation, activation, or starter-content failures should * abort the Blueprint. */ onError?: "skip-theme" | "throw"; /** * The name of the folder to install the theme to. Defaults to guessing from themeData */ targetFolderName?: string; /** * Human-readable theme name for the progress caption and skip warning. */ humanReadableName?: string; } /** * Installs a WordPress theme in the Playground. * * @param playground The playground client. * @param themeZipFile The theme zip file. * @param options Optional. Set `activate` to false if you don't want to activate the theme. */ export declare const installTheme: StepHandler>; /** * @inheritDoc login * @hasRunnableExample * @example * * * { * "step": "login", * "username": "admin" * } * */ export type LoginStep = { step: "login"; /** * The user to log in as. Defaults to 'admin'. */ username?: string; /** * @deprecated The password field is deprecated and will be removed in a future version. * Only the username field is required for user authentication. */ password?: string; }; /** * Logs in to Playground. * Under the hood, this function sets the `PLAYGROUND_AUTO_LOGIN_AS_USER` constant. * The `0-auto-login.php` mu-plugin uses that constant to log in the user on the first load. * This step depends on the `@wp-playground/wordpress` package because * the plugin is located in and loaded automatically by the `@wp-playground/wordpress` package. */ export declare const login: StepHandler; /** * @private */ export interface RunWpInstallationWizardStep { step: "runWpInstallationWizard"; options: WordPressInstallationOptions; } export interface WordPressInstallationOptions { adminUsername?: string; adminPassword?: string; } /** * Installs WordPress * * @param playground The playground client. * @param options Installation options. */ export declare const runWpInstallationWizard: StepHandler; /** * @inheritDoc setSiteOptions * @hasRunnableExample * * @example * * * { * "step": "setSiteOptions", * "options": { * "blogname": "My Blog", * "blogdescription": "A great blog" * } * } * */ export type SetSiteOptionsStep = { /** The name of the step. Must be "setSiteOptions". */ step: "setSiteOptions"; /** The options to set on the site. */ options: Record; }; /** * Sets site options. This is equivalent to calling [`update_option`](https://developer.wordpress.org/reference/functions/update_option/) for each * option in the [`options`](https://developer.wordpress.org/apis/options/#available-options-by-category) object. */ export declare const setSiteOptions: StepHandler; /** * @inheritDoc updateUserMeta * @hasRunnableExample * * @example * * * { * "step": "updateUserMeta", * "meta": { * "first_name": "John", * "last_name": "Doe" * }, * "userId": 1 * } * */ export interface UpdateUserMetaStep { step: "updateUserMeta"; /** An object of user meta values to set, e.g. { "first_name": "John" } */ meta: Record; /** User ID */ userId: number; } /** * Updates user meta. This is equivalent to calling [`update_user_meta`](https://developer.wordpress.org/reference/functions/update_user_meta/) for each * meta value in the `meta` object. */ export declare const updateUserMeta: StepHandler; /** * @inheritDoc rm * @hasRunnableExample * @landingPage /index.php * @example * * * { * "step": "rm", * "path": "/wordpress/index.php" * } * */ export interface RmStep { step: "rm"; /** The path to remove */ path: string; } /** * Removes a file at the specified path. */ export declare const rm: StepHandler; /** * @inheritDoc cp * @hasRunnableExample * @landingPage /index2.php * @example * * * { * "step": "cp", * "fromPath": "/wordpress/index.php", * "toPath": "/wordpress/index2.php" * } * */ export interface CpStep { step: "cp"; /** Source path */ fromPath: string; /** Target path */ toPath: string; } /** * Copies a file from one path to another. */ export declare const cp: StepHandler; /** * @inheritDoc rmdir * @hasRunnableExample * @landingPage /wp-admin/ * @example * * * { * "step": "rmdir", * "path": "/wordpress/wp-admin" * } * */ export interface RmdirStep { step: "rmdir"; /** The path to remove */ path: string; } /** * Removes a directory at the specified path. */ export declare const rmdir: StepHandler; /** * @inheritDoc runSql * @hasRunnableExample * @example * * * { * "step": "runSql", * "sql": { * "resource": "literal", * "name": "schema.sql", * "contents": "DELETE FROM wp_posts" * } * } * */ export interface RunSqlStep { /** * The step identifier. */ step: "runSql"; /** * The SQL to run. Each non-empty line must contain a valid SQL query. */ sql: ResourceType; } /** * Run one or more SQL queries. * * This step uses WP_MySQL_Naive_Query_Stream to parse and execute SQL queries using * streaming semantics. It supports multiline queries, comments, and queries * separated by semicolons. Each query is executed using `$wpdb`. This step assumes * a presence of the `sqlite-database-integration` plugin that ships the required * query tokenizer classes. */ export declare const runSql: StepHandler>; /** * @inheritDoc mkdir * @hasRunnableExample * @example * * * { * "step": "mkdir", * "path": "/wordpress/my-new-folder" * } * */ export interface MkdirStep { step: "mkdir"; /** The path of the directory you want to create */ path: string; } /** * Creates a directory at the specified path. */ export declare const mkdir: StepHandler; /** * @inheritDoc mv * @hasRunnableExample * @landingPage /index2.php * @example * * * { * "step": "mv", * "fromPath": "/wordpress/index.php", * "toPath": "/wordpress/index2.php" * } * */ export interface MvStep { step: "mv"; /** Source path */ fromPath: string; /** Target path */ toPath: string; } /** * Moves a file or directory from one path to another. */ export declare const mv: StepHandler; /** * @inheritDoc runPHP * @hasRunnableExample * @example * * * { * "step": "runPHP", * "code": " 'wp-load.php required for WP functionality', 'post_status' => 'publish')); ?>" * } * */ export interface RunPHPStep { /** The step identifier. */ step: "runPHP"; /** The PHP code to run. */ code: string | { /** * This property is ignored during Blueprint v1 execution but exists * so the same runPHP step structure can be used for Blueprints v1 and v2. */ filename: string; content: string; }; } /** * Runs PHP code. * When running WordPress functions, the `code` key must first load [`wp-load.php`](https://github.com/WordPress/WordPress/blob/master/wp-load.php) and start with `">; /** * @inheritDoc runPHP * @hasRunnableExample * @example * * * { * "step": "runPHPWithOptions", * "options": { * "code": "", * "body": "Site Name Modified by runPHPWithOptions" * } * } * */ export interface RunPHPWithOptionsStep { step: "runPHPWithOptions"; /** * Run options (See * /wordpress-playground/api/universal/interface/PHPRunOptions/)) */ options: PHPRunOptions; } /** * Runs PHP code with the given options. */ export declare const runPHPWithOptions: StepHandler; /** * @private * @inheritDoc request * @needsLogin * @hasRunnableExample * @example * * * { * "step": "request", * "request": { * "method": "POST", * "url": "/wp-admin/admin-ajax.php", * "formData": { * "action": "my_action", * "foo": "bar" * } * } * } * */ export interface RequestStep { step: "request"; /** * Request details (See * /wordpress-playground/api/universal/interface/PHPRequest) */ request: PHPRequest; } /** * Sends a HTTP request to Playground. */ export declare const request: StepHandler>; /** * @inheritDoc writeFile * @hasRunnableExample * @landingPage /test.php * @example * * * { * "step": "writeFile", * "path": "/wordpress/test.php", * "data": "" * } * */ export interface WriteFileStep { step: "writeFile"; /** The path of the file to write to */ path: string; /** The data to write */ data: FileResource | string | Uint8Array; } /** * Writes data to a file at the specified path. */ export declare const writeFile: StepHandler>; /** * @inheritDoc writeFiles * @hasRunnableExample * @landingPage /test.php * @example * * * { * "step": "writeFiles", * "writeToPath": "/wordpress/wp-content/plugins/my-plugin", * "filesTree": { * "name": "my-plugin", * "files": { * "index.php": "Hello World!'; ?>", * "public": { * "style.css": "a { color: red; }" * } * } * } * } * */ export interface WriteFilesStep { step: "writeFiles"; /** The path of the file to write to */ writeToPath: string; /** * The 'filesTree' defines the directory structure, supporting 'literal:directory' or * 'git:directory' types. The 'name' represents the root directory, while 'files' is an object * where keys are file paths, and values contain either file content as a string or nested objects * for subdirectories. */ filesTree: DirectoryResource; } /** * Writes multiple files to a specified directory in the Playground * filesystem. * ``` * my-plugin/ * ├── index.php * └── public/ * └── style.css * ``` */ export declare const writeFiles: StepHandler>; /** * @inheritDoc defineWpConfigConsts * @hasRunnableExample * @example * * * { * "step": "defineWpConfigConsts", * "consts": { * "WP_DEBUG": true * } * } * */ export interface DefineWpConfigConstsStep { step: "defineWpConfigConsts"; /** The constants to define */ consts: Record; /** * The method of defining the constants in wp-config.php. Possible values are: * * - rewrite-wp-config: Default. Rewrites the wp-config.php file to * explicitly call define() with the requested * name and value. This method alters the file * on the disk, but it doesn't conflict with * existing define() calls in wp-config.php. * * - define-before-run: Defines the constant before running the requested * script. It doesn't alter any files on the disk, but * constants defined this way may conflict with existing * define() calls in wp-config.php. */ method?: "rewrite-wp-config" | "define-before-run"; /** * @deprecated This option is noop and will be removed in a future version. * This option is only kept in here to avoid breaking Blueprint schema validation * for existing apps using this option. */ virtualize?: boolean; } /** * Defines constants in a [`wp-config.php`](https://developer.wordpress.org/advanced-administration/wordpress/wp-config/) file. * * This step can be called multiple times, and the constants will be merged. * * @param playground The playground client. * @param wpConfigConst */ export declare const defineWpConfigConsts: StepHandler; /** * @inheritDoc activateTheme * @example * * * { * "step": "activateTheme", * "themeFolderName": "storefront" * } * */ export interface ActivateThemeStep { step: "activateTheme"; /** * The name of the theme folder inside wp-content/themes/ */ themeFolderName: string; } /** * Activates a WordPress theme (if it's installed). * * @param playground The playground client. * @param themeFolderName The theme folder name. */ export declare const activateTheme: StepHandler; /** * @inheritDoc unzip * @example * * * { * "step": "unzip", * "zipFile": { * "resource": "vfs", * "path": "/wordpress/data.zip" * }, * "extractToPath": "/wordpress" * } * */ export interface UnzipStep { step: "unzip"; /** The zip file to extract */ zipFile?: ResourceType; /** * The path of the zip file to extract * @deprecated Use zipFile instead. */ zipPath?: string; /** The path to extract the zip file to */ extractToPath: string; } /** * Unzip a zip file. * * @param playground Playground client. * @param zipPath The zip file to unzip. * @param extractTo The directory to extract the zip file to. */ export declare const unzip: StepHandler>; /** * @inheritDoc importWordPressFiles * @example * * * { * "step": "importWordPressFiles", * "wordPressFilesZip": { * "resource": "url", * "url": "https://mysite.com/import.zip" * } * } * */ export interface ImportWordPressFilesStep { step: "importWordPressFiles"; /** * The zip file containing the top-level WordPress files and * directories. */ wordPressFilesZip: ResourceType; /** * The path inside the zip file where the WordPress files are. */ pathInZip?: string; } /** * Imports top-level WordPress files from a given zip file into * the `documentRoot`. For example, if a zip file contains the * `wp-content` and `wp-includes` directories, they will replace * the corresponding directories in Playground's `documentRoot`. * * Imported copies of Playground-owned runtime artifacts are discarded. For * example, an archive cannot replace `mu-plugins/sqlite-database-integration`, * `mu-plugins/0-playground.php`, or a Playground-generated `db.php`. If those * paths still exist in the importing document root, its copies are retained. * An unmarked custom `db.php` remains part of the imported site. * * A `formatVersion: 2` archive is otherwise authoritative for user-owned * `wp-content`: a customized Twenty Twenty-Five theme replaces the boot * default, while an absent theme remains deleted. For an older archive, stock * paths omitted by the exporter, such as `plugins/akismet`, `plugins/hello.php`, * and `themes/twentytwentyfive`, are restored from the importing document root * only when absent from the archive. * * @param playground Playground client. * @param wordPressFilesZip Zipped WordPress site. */ export declare const importWordPressFiles: StepHandler>; /** * @inheritDoc importThemeStarterContent * @example * * * { * "step": "importThemeStarterContent" * } * */ export interface ImportThemeStarterContentStep { /** The step identifier. */ step: "importThemeStarterContent"; /** * The name of the theme to import content from. */ themeSlug?: string; } /** * Imports a theme Starter Content into WordPress. * * @param playground Playground client. */ export declare const importThemeStarterContent: StepHandler; /** * @inheritDoc importWxr * @example * * * { * "step": "importWxr", * "file": { * "resource": "url", * "url": "https://your-site.com/starter-content.wxr" * } * } * */ export interface ImportWxrStep { step: "importWxr"; /** The file to import */ file: ResourceType; /** * Whether to fetch and import attachment files referenced by the WXR file. * * @default true */ fetchAttachments?: boolean; /** * Whether to rewrite imported URLs to the current site URL. * * @default true */ rewriteUrls?: boolean; /** * Explicit URL replacements to apply when URL rewriting is enabled. */ urlMapping?: Record; /** * Whether to import comments from the WXR file. * * @default true */ importComments?: boolean; /** * The fallback local user for imported authors that cannot be mapped. * * @default "admin" */ defaultAuthorUsername?: string; /** * How to assign imported WXR authors to local WordPress users. * * @default "default-author" */ authorsMode?: "create" | "default-author" | "map"; /** * Remote WXR author usernames keyed to existing local usernames. */ authorsMap?: Record; /** * Whether to create local users for imported WXR authors. * * @default false */ importUsers?: boolean; /** * The importer to use. Possible values: * * - `default`: The importer from https://github.com/humanmade/WordPress-Importer * - `data-liberation`: The experimental Data Liberation WXR importer developed at * https://github.com/WordPress/wordpress-playground/issues/1894 * * This option is deprecated. The syntax will not be removed, but once the * Data Liberation importer matures, it will become the only supported * importer and the `importer` option will be ignored. * * @deprecated */ importer?: "data-liberation" | "default"; } /** * Imports a WXR file into WordPress. * * @param playground Playground client. * @param file The file to import. */ export declare const importWxr: StepHandler>; /** * @inheritDoc enableMultisite * @hasRunnableExample * @example * * * { * "step": "enableMultisite" * } * */ export interface EnableMultisiteStep { step: "enableMultisite"; /** wp-cli.phar path */ wpCliPath?: string; } /** * Defines the [Multisite](https://developer.wordpress.org/advanced-administration/multisite/create-network/) constants in a `wp-config.php` file. * * This step can be called multiple times, and the constants will be merged. * * @param playground The playground client. * @param enableMultisite */ export declare const enableMultisite: StepHandler; /** * @inheritDoc wpCLI * @hasRunnableExample * @example * * * { * "step": "wp-cli", * "command": "wp post create --post_title='Test post' --post_excerpt='Some content'" * } * */ export interface WPCLIStep { /** The step identifier. */ step: "wp-cli"; /** The WP CLI command to run. */ command: string | string[]; /** wp-cli.phar path */ wpCliPath?: string; } /** * Runs PHP code using [WP-CLI](https://developer.wordpress.org/cli/commands/). */ export declare const wpCLI: StepHandler>; /** * @inheritDoc resetData * @example * * * { * "step": "resetData" * } * */ export interface ResetDataStep { step: "resetData"; /** * Content types to remove. When omitted, all posts, pages, custom post * types, and comments are removed. */ contentTypes?: Array<"posts" | "pages" | "comments">; } /** * Deletes the selected WordPress content through WordPress APIs so dependent * records are removed with it. Empty tables have their sequences reset so * later imports receive the identifiers they would on a site without the * removed content. * * @param playground Playground client. */ export declare const resetData: StepHandler; /** * @inheritDoc setSiteLanguage * @hasRunnableExample * @example * * * { * "step": "setSiteLanguage", * "language": "en_US" * } * */ export interface SetSiteLanguageStep { step: "setSiteLanguage"; /** The language to set, e.g. 'en_US' */ language: string; } /** * Sets the site language and download translations. */ export declare const setSiteLanguage: StepHandler; export type Step = GenericStep; export type StepDefinition = Step & { progress?: { weight?: number; caption?: string; }; }; /** * If you add a step here, make sure to also * add it to the exports below. */ export type GenericStep = ActivatePluginStep | ActivateThemeStep | CpStep | DefineWpConfigConstsStep | DefineSiteUrlStep | EnableMultisiteStep | ImportWxrStep | ImportThemeStarterContentStep | ImportWordPressFilesStep | InstallPluginStep | InstallThemeStep | LoginStep | MkdirStep | MvStep | ResetDataStep | RequestStep | RmStep | RmdirStep | RunPHPStep | RunPHPWithOptionsStep | RunWpInstallationWizardStep | RunSqlStep | SetSiteOptionsStep | UnzipStep | UpdateUserMetaStep | WriteFileStep | WriteFilesStep | WPCLIStep | SetSiteLanguageStep; /** * Progress reporting details. */ export type StepProgress = { tracker: ProgressTracker; initialCaption?: string; }; export type StepHandler, Return = any> = ( /** * A PHP instance or Playground client. */ php: UniversalPHP, args: Omit, progressArgs?: StepProgress) => Return; export type MountDevice = { type: "opfs"; path: string; } | { type: "local-fs"; handle: FileSystemDirectoryHandle; }; export interface ReadableFilesystemBackend { read(path: string): Promise; } export declare namespace DataSources { /** * General data sources {{{ * * These types can be used anywhere in the Blueprint schema where a * file or a directory is expected. */ /** * A reference to a HTTP or HTTPS URL. * * The URLs are parsed using the WHATWG URL standard, which means they can * optionally contain usernames and passwords if needed. * * @see https://url.spec.whatwg.org/ * @asType string * @pattern ^[Hh][Tt][Tt][Pp][Ss]?://[^/?#]+ */ export type URLReference = `http://${string}` | `https://${string}`; /** * A reference to a file in the Blueprint Execution Context – see the * main proposal document for more context. * * The path must start with either ./ or / to distinguish it from a * plugin or theme slug. Regardless of the prefix (./ or /), the path * is relative to the Blueprint Execution Context root: * * * Relative paths (./) are relative to the location of blueprint.json file. * * Absolute paths (/) are chrooted at the Blueprint Execution Context root which is * still the directory where blueprint.json is located. * * It is not possible to escape the Blueprint Execution Context via "../" sequences. * * @asType string * @pattern ^(?!.*(?:^|/)\.\.(?:/|$))(?:\./|/).*$ */ export type ExecutionContextPath = `/${string}` | `./${string}`; /** * A file that is inlined within the Blueprint JSON document. * * Example: * * ```json * { * "filename": "index.php", * "content": "" * } * ``` */ export type InlineFile = { /** @pattern ^(?!(?:\.|\.\.)$)[^/]+$ */ filename: string; content: InlineFileContent; }; type InlineFileContent = string; /** * A directory that is inlined within the Blueprint JSON document. * * Example: * * ```json * { * "directoryName": "my-directory", * "files": { * "index.php": "", * "my-sub-directory": { * "files": { * "index.php": "" * } * } * } * } * ``` */ export type InlineDirectory = { /** @pattern ^(?!(?:\.|\.\.)$)[^/]+$ */ directoryName: string; /** @propertyNames { "pattern": "^(?!(?:\\.|\\.\\.)$)[^/]+$" } */ files: Record; }; /** * A child directory inside an inline directory. * * Its directory name comes from the parent `files` record key. */ export type NestedInlineDirectory = { /** @propertyNames { "pattern": "^(?!(?:\\.|\\.\\.)$)[^/]+$" } */ files: Record; }; /** * A reference to a remote git repository. */ export type GitPath = { /** * A HTTP or HTTPS URL of the remote git repository. */ gitRepository: URLReference; /** * A branch name, commit hash, or tag name. * * Defaults to HEAD. */ ref?: string; /** * A path inside the git repository this data reference points to. * * Defaults to the root of the repository. * * @pattern ^(?!.*(?:^|/)\.\.(?:/|$)).*$ */ pathInRepository?: string; }; /** * A union of all general data reference types. */ export type DataReference = URLReference | ExecutionContextPath | InlineFile | InlineDirectory | GitPath; /** * A data reference that must resolve to a single file. */ export type FileDataReference = URLReference | ExecutionContextPath | TargetSitePath | InlineFile; /** * }}} */ /** * Contextual data sources {{{ * * These types are only meaningful in specific, well-known parts of * the Blueprint schema. */ /** Helper types {{{ */ /** * A WordPress.org directory slug. * * Slugs are intentionally treated as opaque strings. Playground should not * reject future WordPress.org slug formats just because they do not match the * directory conventions common today. */ export type Slug = string; /** * @asType string * @pattern ^(?:latest|\d+\.\d+(?:\.\d+)?)$ */ export type SimpleVersionExpression = "latest" | `${number}.${number}` | `${number}.${number}.${number}`; export type VersionNumberComponent = `${bigint}`; /** * @asType string * @pattern ^\d+\.\d+(?:\.\d+)?$ */ export type ComparableVersionExpression = `${VersionNumberComponent}.${VersionNumberComponent}` | `${VersionNumberComponent}.${VersionNumberComponent}.${VersionNumberComponent}`; export type WordPressVersionSuffix = `beta${VersionNumberComponent}` | `rc${VersionNumberComponent}`; /** * @asType string * @pattern ^\d+\.\d+(?:\.\d+)?(?:-(?:beta\d+|[Rr][Cc]\d+))?$ */ export type WordPressVersionConstraintVersion = ComparableVersionExpression | `${ComparableVersionExpression}-${WordPressVersionSuffix}`; /** * @asType string * @pattern ^(?:latest|\d+\.\d+(?:\.\d+)?(?:-(?:beta\d+|[Rr][Cc]\d+))?)$ */ export type WordPressVersionPreferredVersion = "latest" | WordPressVersionConstraintVersion; /** * @asType string * @pattern ^(?:latest|\d+\.\d+(?:\.\d+)?)$ */ export type PHPVersionConstraintVersion = SimpleVersionExpression; /** }}} Helper types */ /** * Plugin directory reference, e.g. "jetpack", "jetpack@6.4", or "akismet@6.4.3". * * These refer to a specific plugin slugs in the WordPress.org plugin repository. * * For example, a reference to "wordpress-seo" means the Yoast SEO plugin as * seen on https://wordpress.org/plugins/wordpress-seo/. * * The Plugin Directory Reference are only meaningful in: * * * The top-level `plugins` array * * The `installPlugin` imperative step */ export type PluginDirectoryReference = Slug | `${Slug}@${SimpleVersionExpression}`; /** * Theme directory reference, e.g. "twentytwentythree", "adventurer@4.6.0", or "twentytwentyfour@latest". * * These refer to specific theme slugs in the WordPress.org theme repository. * * For example, a reference to "adventurer" means the Adventurer theme as * seen on https://wordpress.org/themes/adventurer/. * * These references are only meaningful in: * * * The top-level `themes` array * * The `installTheme` imperative step */ export type ThemeDirectoryReference = Slug | `${Slug}@${SimpleVersionExpression}`; /** * WordPress version, e.g. "latest", "beta", "trunk", "none", "6.4", * "6.4.3", "6.8-RC1", or "6.7-beta2". * * These refer to slugs of specific WordPress releases as listed in * the first table column on https://wordpress.org/download/releases/. * "none" is not a release. It means the Blueprint runs PHP without * installing WordPress. * * The WordPressVersion type is only meaningful in the top-level * `wordpressVersion` property. * * @asType string * @pattern ^(?:latest|beta|trunk|nightly|none|\d+\.\d+(?:\.\d+)?(?:-(?:beta\d+|[Rr][Cc]\d+))?)$ */ export type WordPressVersion = "none" | "beta" | "trunk" | "nightly" | SimpleVersionExpression | `${SimpleVersionExpression}-${WordPressVersionSuffix}`; /** * PHP version, e.g. "8.1", "8.1.3", or "next". * * These refer to PHP versions as listed in https://www.php.net/releases/. * `next` previews the php-src development branch and is currently * supported by the web runtime only. * * The PHPVersion type is only meaningful in the top-level * `phpVersion` property. * * @asType string * @pattern ^(?:latest|next|\d+\.\d+(?:\.\d+)?)$ */ export type PHPVersion = SimpleVersionExpression | "next"; /** * A path within the target WordPress site, relative to the WordPress root * directory. For example, site:wp-content/uploads/2024/01/image.jpg. * * Unlike an execution-context path, this path is resolved from the mutable * target filesystem when the consuming step runs. Earlier steps may therefore * create the referenced file. The runner must keep the path inside the target * WordPress root; it never names a file on the host filesystem. * * @asType string * @pattern ^site:(?!\/*$)(?!\.\.(?:/|$))(?!.*\/\.\.(?:/|$)).+$ */ export type TargetSitePath = `site:${string}`; export {}; } export declare namespace V2Schema { export type BlueprintV2 = { /** * Not a generic 'number' type – this schema is specifically for * Blueprints v2. Version 1 had no "version" field and versions 3, 4, * 5, etc will be different from version 2. */ version: 2; /** * JSON Schema URL. */ $schema?: DataSources.URLReference | DataSources.ExecutionContextPath; blueprintMeta?: { name?: string; description?: string; moreInfo?: string; version?: string; authors?: string[]; homepage?: DataSources.URLReference; donateLink?: DataSources.URLReference; tags?: string[]; license?: LicenseKeyword | string; }; /** * Divergence from Blueprints v1: * * There are no `landingPage` or `login` top-level properties. * Instead, Blueprint v2 introduces a dedicated top-level `applicationOptions` property * for declaring options or opinions for different application contexts. * * To keep Blueprints portable and focused on site creation, this specification * only allows a small set of Playground-specific options. Other environments * cannot declare additional options. Future versions of this specification may * allow additional options – they will be discussed on a case-by-case basis. */ applicationOptions?: { /** * Options for the WordPress Playground. */ "wordpress-playground": { /** * The first page the user is redirected to once the Playground is loaded and * the Blueprint is executed. * * @default "/wp-admin" */ landingPage?: string; /** * Whether to log the user in after the Blueprint is executed. If true, * the user is logged in as "admin". * * @default false */ login?: boolean | { username: string; password: string; }; /** * Whether to allow the site to access the network. * * @default false */ networkAccess?: boolean; /** * Optional PHP extensions to load in the Playground runtime before executing * the Blueprint. Extensions omitted from this list are not disabled. */ loadPhpExtensions?: Array<"intl">; }; }; /** * The content from a vanilla WordPress installation to retain before * applying the rest of the Blueprint. `keep-all` leaves the installation * unchanged, `empty` removes its posts, pages, and comments, a content type * retains only that type, and a list retains the selected content types. * * This policy runs only when the current invocation creates vanilla * WordPress. It is skipped when applying the Blueprint to an existing site, * so it cannot erase content from that site. It is not valid when * `wordpressVersion` is "none". Metadata and relationships follow their * parent content. Empty content tables have their sequences reset so * subsequent imports receive the identifiers they would on a site created * without default content. * * Comments can only be retained together with both posts and pages because * the schema cannot know which type contains their parent records. * * @default "keep-all" */ contentBaseline?: "keep-all" | "empty" | Exclude | [ ContentType, ...ContentType[] ]; /** * The users from a vanilla WordPress installation to retain before applying * the rest of the Blueprint. `keep-all` retains the administrator created by * WordPress, while `empty` removes it before creating the users declared by * this Blueprint. * * Empty user tables have their sequences reset before those users are * created. * * An empty user baseline requires an empty content baseline so removing the * installation administrator cannot silently delete or orphan authored * content. It also requires at least one declared administrator, ensuring * the resulting WordPress site remains manageable. * * Like `contentBaseline`, this policy is skipped when applying the Blueprint * to an existing site and is not valid when `wordpressVersion` is "none". * * @default "keep-all" */ usersBaseline?: "keep-all" | "empty"; /** * SITE OPTIONS {{{ * * There are no "nice" top-level shortcuts such as `siteTitle` to implicitly set "popular" * site options. All the options must be explicitly declared via the `siteOptions` property. * Why? Two reasons: * * * No need to ask developers to learn a new set of identifiers. * * It's unclear which site title should win if the Blueprint declares both * `siteTitle` and `siteOptions.blogname`. * * The tao of Python says: Explicit is better than implicit. Let's stick with that. */ /** * Sets the WPLANG constant and downloads any missing translations for WordPress * core and all the installed plugins and themes. If you need a fine-grained * control over the translations, use imperative steps in the `additionalStepsAfterExecution` * array. * * @default "en_US" */ siteLanguage?: string; /** * Site options. In WordPress, the values are PHP-serializable, but Blueprints are * intentionally restricted to an even stricter subset of those, that are JSON-serializable. * This is to prevent passing JavaScript Date objects and similar. * * The runner **MUST** use the WordPress `update_option` function to store the * siteOptions values defined in this property as WordPress options. Lists and * objects are passed to `update_option` as PHP arrays. * * Site options example: * * ```json * { * "blogname": "Adam's Movies", * "timezone": "Poland/Warsaw", * "gutenberg-experiments": { * 'gutenberg-custom-dataviews': true, * 'gutenberg-new-posts-dashboard': true, * 'gutenberg-quick-edit-dataviews': true * } * } * ``` */ siteOptions?: { /** * Site title. * * Example: "Adam's Movies" * @default "My WordPress Site" */ blogname?: string; /** * Example: "Poland/Warsaw" * @default "UTC" */ timezone_string?: string; /** * Site permalink structure. If present and different from the current permalink structure, * the Blueprint runner will run `$wp_rewrite->flush_rules();`. If you only want to set this * option without flushing the rules, use an explicit `additionalStepsAfterExecution` step. * * Example: "/%year%/%monthnum%/%postname%/" or false for no pretty permalinks. * @default "/%postname%/" */ permalink_structure?: string | false; } & Record, JsonValue>; /** * }}} */ /** * Constants to define in the wp-config.php file. * * The runner may overwrite the define() calls in the wp-config.php file * on the target site. It assumes the wp-config.php file at the Blueprint * Execution Target is writable. * * @see https://github.com/WordPress/blueprints-library/issues/118 */ constants?: WordPressConstants; /** * WordPress version to install or require. * * A string selects the version for a newly created site. A branch such as * `6.8` selects the newest available release in that branch. Strings are * selection hints and do not reject an existing site. `"none"` boots the * PHP runtime without downloading WordPress or initializing its database. * * An object declares compatibility bounds. The runner chooses the newest * available release within those bounds for a new site and verifies an * existing site's installed version against them. `preferred` influences * new-site selection without narrowing compatibility. * * A data reference supplies the WordPress files for a newly created site. * * @default "latest" */ wordpressVersion?: DataSources.WordPressVersion | DataSources.DataReference | { min: DataSources.WordPressVersionConstraintVersion; max?: DataSources.WordPressVersionConstraintVersion; /** * @default "latest" */ preferred?: DataSources.WordPressVersionPreferredVersion; }; /** * The PHP version required for this Blueprint to work. * * In runtimes where we set up the runtime, such as Playground and wp-env, the * runner will choose a version compatible with this constraint. * * In other environments, this is used for validation. The Blueprint engine will * throw an error if the currently running PHP version doesn't match this constraint. * * @default "8.0". Changing the default value will bump the Blueprint version. * * @see https://github.com/WordPress/blueprints-library/issues/47 */ phpVersion?: DataSources.PHPVersion | { min?: DataSources.PHPVersionConstraintVersion; recommended?: DataSources.PHPVersionConstraintVersion; max?: DataSources.PHPVersionConstraintVersion; }; /** * The theme to install and also activate. * * > Why not support an `active` property in the `themes` array? * * Because an `"active"` property would have to default to `false` for themes while it * defaults to `true` for plugins. That's error-prone and confusing. * * @example `"activeTheme": "stylish-press-theme"` * @example `"activeTheme": "adventurer@4.6.0"` * @example * ```json * { * "version": 2, * "activeTheme": { * "source": "https://github.com/richtabor/kanso/archive/refs/heads/main.zip", * "targetDirectoryName": "kanso", * "importStarterContent": true * } * } * ``` */ activeTheme?: ThemeDefinition; /** * Installed themes to install without activating them. * * Example: * * ```json * { * "version": 2, * "themes": [ * "stylish-press-theme", * "adventurer@4.6.0", * { * "source": "https://github.com/richtabor/kanso/archive/refs/heads/main.zip", * "targetDirectoryName": "kanso" * } * ] * } * ``` */ themes?: ThemeDefinition[]; /** * A list of plugins to install and activate. * * Example: * * ```json * { * "version": 2, * "plugins": [ * "jetpack", * "akismet@6.4.3", * "./query-monitor.php", * "./code-block.zip", * { * "source": "https://github.com/woocommerce/woocommerce/archive/refs/heads/6.4.3.zip", * "active": false * } * ] * } * ``` */ plugins?: PluginDefinition[]; /** * A list of mu-plugins to install. * * Example: * * ```json * { * "version": 2, * "muPlugins": [ * { * "filename": "addFilter-0.php", * "content": "; /** * Very basic schema for defining custom post types. * * IMPORTANT: Using this property requires an explicit inclusion of the * `secure-custom-fields` plugin. If it's missing, the Blueprint runner will * throw an error. * * See https://github.com/WordPress/blueprints-library/issues/32 for more context. * * @propertyNames { "pattern": "^[a-z0-9_-]{1,20}$" } */ postTypes?: Record; /** * A list of fonts to register in the site's Font Library. * * Example: * * ```json * fonts: { * "open-sans": "https://example.com/fonts/open-sans.woff2", * "roboto": "./wp-content/fonts/roboto.woff2" * } * ``` * * Or using the full font collection schema: * * ```json * fonts: { * "my-collection": { * "font_families": [ * { * "font_family_settings": { * "name": "Open Sans", * "slug": "open-sans", * "fontFamily": "Open Sans", * "preview": "https://example.com/previews/open-sans.png", * "fontFace": [ * { * "fontFamily": "Open Sans", * "fontWeight": "400", * "fontStyle": "normal", * "src": "./wp-content/fonts/open-sans-regular.woff2" * } * ] * }, * "categories": ["sans-serif"] * } * ] * } * } * ``` */ fonts?: Record; /** * A list of media files to upload to the WordPress Media Library – in formats * supported by the WordPress Media Library. * * Example: * * ```json * media: [ * "https://example.com/images/hero.jpg", * "./wp-content/uploads/2024/01/logo.png", * { * "source": "https://example.com/videos/intro.mp4", * "title": "Introduction Video", * "description": "A brief introduction to our company", * "alt": "Company introduction video" * }, * { * "source": "./wp-content/uploads/2024/01/brochure.pdf", * "title": "Product Brochure", * "description": "Detailed information about our products" * } * ] * ``` * */ media?: Array; content?: Array; users?: Array<{ username: string; email: string; role: string; meta: Record; }>; roles?: Array<{ name: string; capabilities: Record; }>; additionalStepsAfterExecution?: Array; }; /** * Content types created by a vanilla WordPress installation and controlled * by `contentBaseline`. */ type ContentType = "posts" | "pages" | "comments"; type LicenseKeyword = "AFL-3.0" | "Apache-2.0" | "Artistic-2.0" | "BSL-1.0" | "BSD-2-Clause" | "BSD-3-Clause" | "BSD-3-Clause-Clear" | "BSD-4-Clause" | "0BSD" | "CC" | "CC0-1.0" | "CC-BY-4.0" | "CC-BY-SA-4.0" | "WTFPL" | "ECL-2.0" | "EPL-1.0" | "EPL-2.0" | "EUPL-1.1" | "AGPL-3.0" | "GPL" | "GPL-2.0" | "GPL-3.0" | "LGPL" | "LGPL-2.1" | "LGPL-3.0" | "ISC" | "LPPL-1.3c" | "MS-PL" | "MIT" | "MPL-2.0" | "OSL-3.0" | "PostgreSQL" | "OFL-1.1" | "NCSA" | "Unlicense" | "Zlib"; type URLMappingConfig = { /** * Whether to rewrite the hrefs in the remote site's content URLs in the WXR file * from the remote site domain to the current site domain's (and path etc). * * Possible values: * * * "rewrite" – Rewrite the hrefs to the current site domain's (and path etc). * * "preserve" – Preserve the hrefs as they are. * * @default "rewrite". */ urlsMode?: "rewrite" | "preserve"; /** * A mapping of base URLs to rewrite. * * @propertyNames { "$ref": "#/definitions/DataSources.URLReference" } */ urlsMap?: Record; }; type ContentDefinition = { type: "mysql-dump"; source: DataSources.FileDataReference | DataSources.FileDataReference[]; } | ({ type: "posts"; source: DataSources.FileDataReference | WordPressPost | (DataSources.FileDataReference | WordPressPost)[]; } & URLMappingConfig) /** * WXR files to import. * * Example: * * ```json * { * "version": 2, * "content": [ * { * "type": "wxr", * "source": "https://raw.githubusercontent.com/wordpress/blueprints/trunk/blueprints/stylish-press/woo-products.wxr" * }, * { * "type": "wxr", * "source": "https://raw.githubusercontent.com/wordpress/blueprints/trunk/blueprints/stylish-press/site-content.wxr", * "urlsMode": "rewrite", * "staticAssets": "hotlink", * "importUsers": false, * "importComments": false * } * ] * } * ``` */ | WXRContentDefinition; type WXRContentDefinition = WXRContentBase & ({ /** * Map remote authors to existing local authors. */ authorsMode: "map"; authorsMap: Record; } | { /** * How to handle authors that don't exist on the current site. * * Possible values: * * * "create" – Create a new author. * * "default-author" – Use the default author. * * @default "create". */ authorsMode?: "create" | "default-author"; authorsMap?: Record; }); type WXRContentBase = { type: "wxr"; source: DataSources.FileDataReference | DataSources.FileDataReference[]; /** * Static assets handling. * * Possible values: * * * "fetch" – Fetch the static assets and save them to the local filesystem. * * "hotlink" – Hotlink the static assets from the remote site. * * @default "fetch". */ staticAssets?: "fetch" | "hotlink"; /** * The default author to use when `mode` is "default-author". * * @default "admin". */ defaultAuthorUsername?: string; /** * Whether to import users from the remote site. * * @default false. */ importUsers?: boolean; /** * Whether to import comments from the remote site. * * @default false. */ importComments?: boolean; } & URLMappingConfig; type MediaDefinition = DataSources.FileDataReference | { source: DataSources.FileDataReference; title?: string; description?: string; alt?: string; caption?: string; }; type PluginDefinition = DataSources.DataReference | DataSources.PluginDirectoryReference | PluginObjectDefinition; type PluginObjectDefinition = { source: DataSources.DataReference | DataSources.PluginDirectoryReference; /** * Whether to activate the plugin. * * @default true. */ active?: boolean; /** * Parameters to pass to the plugin during activation. * * These options are stored in a site option that the plugin can access * during its activation hook. The option name is: * * ```php * 'blueprint_activation_' . plugin_basename( __FILE__ ) * ``` * * This ensures uniqueness even when multiple versions of the same plugin exist. * This is similar to how the `register_activation_hook` function requires the * plugin file path as its first argument. * * The Blueprint runner will remove the option after activating the plugin. * * Example: * * In the Blueprint: * ```json * { * "source": "woocommerce", * "activationOptions": { * "storeCity": "Wrocław", * "storeCountry": "Poland", * "storePostalCode": "53-607" * } * } * ``` * * In the plugin's activation hook: * * ```php * register_activation_hook( __FILE__, function( $network_wide ) { * // Get the activation options from the transient * $option_name = 'blueprint_activation_' . plugin_basename( __FILE__ ); * $blueprint_activation_options = get_option( $option_name ) ?? []; * * if ( $blueprint_activation_options ) { * $store_city = $blueprint_activation_options['storeCity'] ?? ''; * $store_country = $blueprint_activation_options['storeCountry'] ?? ''; * $store_postal_code = $blueprint_activation_options['storePostalCode'] ?? ''; * * // ...do something with the options... * } * * // Continue with normal activation... * } ); * ``` */ activationOptions?: Record; /** * An explicit directory name within wp-content/plugins to install the plugin at. * If not provided, it will be inferred from the plugin source. * * @pattern ^(?!(?:\.|\.\.)$)[^/]+$ */ targetDirectoryName?: string; /** * Sometimes it's fine when a plugin fails to install. * * Use-case: * Compatibility testing. A Blueprint may install WordPress nightly with * a number of plugins to test. Some of those plugins may not yet be compatible * with the latest version of WordPress. This is something to take not of, * but not a strong reason to fail the entire Blueprint installation. * * @see https://github.com/WordPress/wordpress-playground/issues/600 * @default "throw" */ onError?: "skip-plugin" | "throw"; /** * How to handle a plugin that is already installed. * * @default "overwrite" */ ifAlreadyInstalled?: "overwrite" | "skip" | "error"; /** * Human-readable name of the plugin for the progress bar. * * For example, with the following Blueprint: * * ```json * { * "plugins": [ * { * "source": "https://github.com/Automattic/jetpack/archive/refs/heads/beta.zip", * "humanReadableName": "Jetpack Beta" * } * ] * } * ``` * * The progress bar will show "Installing Jetpack Beta plugin" instead of * "Installing https://github.com/Automattic/jetpack/archive/refs/heads/beta.zip". */ humanReadableName?: string; }; type ThemeDefinition = DataSources.ThemeDirectoryReference | DataSources.DataReference | ThemeObjectDefinition; type ThemeObjectDefinition = { source: DataSources.ThemeDirectoryReference | DataSources.DataReference; /** * Whether to import the theme's starter content after installing it. */ importStarterContent?: boolean; /** * An explicit directory name within wp-content/themes to install the theme at. * If not provided, it will be inferred from the theme source. * * @pattern ^(?!(?:\.|\.\.)$)[^/]+$ */ targetDirectoryName?: string; /** * Sometimes it's fine when a theme fails to install. * * @default "throw" */ onError?: "skip-theme" | "throw"; /** * How to handle a theme that is already installed. * * @default "overwrite" */ ifAlreadyInstalled?: "overwrite" | "skip" | "error"; /** * Human-readable name of the theme for the progress bar. * * For example, with the following Blueprint: * * ```json * { * "themes": [ * { * "source": "https://github.com/Automattic/adventurer/archive/refs/heads/beta.zip", * "humanReadableName": "Adventurer" * } * ] * } * ``` * * The progress bar will show "Installing Adventurer theme" instead of * "Installing https://github.com/Automattic/adventurer/archive/refs/heads/beta.zip". */ humanReadableName?: string; }; type RemoteUsername = string; type LocalUsername = string; /** * WordPress register_post_type() arguments representation. {{{ * * The inline docstrings are copied from the WordPress code reference. * * @see https://developer.wordpress.org/reference/functions/register_post_type/ */ /** * Post type key. Must not exceed 20 characters and may only * contain lowercase alphanumeric characters, dashes, and underscores. */ type PostTypeKey = string; type Block = [ string, Record ]; type PostType = { /** * Name of the post type shown in the menu. Usually plural. * Default is value of $labels['name']. */ label?: string; /** * An array of labels for this post type. * If not set, post labels are inherited for non-hierarchical types * and page labels for hierarchical ones * * The labels documented for WordPress 6.8 are listed below, * and this type also supports an arbitrary set of labels to * support future WordPress releases. * * @see https://developer.wordpress.org/reference/functions/get_post_type_labels/ */ labels?: { /** * General name for the post type, usually plural. * Default is 'Posts' / 'Pages'. */ name?: string; /** * Name for one object of this post type. * Default is 'Post' / 'Page'. */ singular_name?: string; /** * Label for adding a new item. * Default is 'Add New' / 'Add New'. */ add_new?: string; /** * Label for adding a new singular item. * Default is 'Add New Post' / 'Add New Page'. */ add_new_item?: string; /** * Label for editing a singular item. * Default is 'Edit Post' / 'Edit Page'. */ edit_item?: string; /** * Label for the new item page title. * Default is 'New Post' / 'New Page'. */ new_item?: string; /** * Label for viewing a singular item. * Default is 'View Post' / 'View Page'. */ view_item?: string; /** * Label for viewing post type archives. * Default is 'View Posts' / 'View Pages'. */ view_items?: string; /** * Label for searching plural items. * Default is 'Search Posts' / 'Search Pages'. */ search_items?: string; /** * Label used when no items are found. * Default is 'No posts found' / 'No pages found'. */ not_found?: string; /** * Label used when no items are in the Trash. * Default is 'No posts found in Trash' / 'No pages found in Trash'. */ not_found_in_trash?: string; /** * Label used to prefix parents of hierarchical items. * Default is 'Parent Page:'. */ parent_item_colon?: string; /** * Label to signify all items in a submenu link. * Default is 'All Posts' / 'All Pages'. */ all_items?: string; /** * Label for archives in nav menus. * Default is 'Post Archives' / 'Page Archives'. */ archives?: string; /** * Label for the attributes meta box. * Default is 'Post Attributes' / 'Page Attributes'. */ attributes?: string; /** * Label for the media frame button. * Default is 'Insert into post' / 'Insert into page'. */ insert_into_item?: string; /** * Label for the media frame filter. * Default is 'Uploaded to this post' / 'Uploaded to this page'. */ uploaded_to_this_item?: string; /** * Label for the featured image meta box title. * Default is 'Featured image'. */ featured_image?: string; /** * Label for setting the featured image. * Default is 'Set featured image'. */ set_featured_image?: string; /** * Label for removing the featured image. * Default is 'Remove featured image'. */ remove_featured_image?: string; /** * Label in the media frame for using a featured image. * Default is 'Use as featured image'. */ use_featured_image?: string; /** * Label for the menu name. * Default is the same as name. */ menu_name?: string; /** * Label for the table views hidden heading. * Default is 'Filter posts list' / 'Filter pages list'. */ filter_items_list?: string; /** * Label for the date filter in list tables. * Default is 'Filter by date'. */ filter_by_date?: string; /** * Label for the table pagination hidden heading. * Default is 'Posts list navigation' / 'Pages list navigation'. */ items_list_navigation?: string; /** * Label for the table hidden heading. * Default is 'Posts list' / 'Pages list'. */ items_list?: string; /** * Label used when an item is published. * Default is 'Post published.' / 'Page published.' */ item_published?: string; /** * Label used when an item is published with private visibility. * Default is 'Post published privately.' / 'Page published privately.' */ item_published_privately?: string; /** * Label used when an item is switched to a draft. * Default is 'Post reverted to draft.' / 'Page reverted to draft.' */ item_reverted_to_draft?: string; /** * Label used when an item is moved to Trash. * Default is 'Post trashed.' / 'Page trashed.' */ item_trashed?: string; /** * Label used when an item is scheduled for publishing. * Default is 'Post scheduled.' / 'Page scheduled.' */ item_scheduled?: string; /** * Label used when an item is updated. * Default is 'Post updated.' / 'Page updated.' */ item_updated?: string; /** * Title for a navigation link block variation. * Default is 'Post Link' / 'Page Link'. */ item_link?: string; /** * Description for a navigation link block variation. * Default is 'A link to a post.' / 'A link to a page.' */ item_link_description?: string; } & Record; /** * A short descriptive summary of what the post type is. */ description?: string; /** * Whether a post type is intended for use publicly either via the admin interface or by front-end users. * While the default settings of $exclude_from_search, $publicly_queryable, $show_ui, and $show_in_nav_menus * are inherited from $public, each does not rely on this relationship and controls a very specific intention. * Default false. */ public?: boolean; /** * Whether the post type is hierarchical (e.g. page). * Default false. */ hierarchical?: boolean; /** * Whether to exclude posts with this post type from front end search results. * Default is the opposite value of $public. */ exclude_from_search?: boolean; /** * Whether queries can be performed on the front end for the post type as part of parse_request(). * Endpoints would include: * * ?post_type={post_type_key} * * ?{post_type_key}={single_post_slug} * * ?{post_type_query_var}={single_post_slug} * If not set, the default is inherited from $public. */ publicly_queryable?: boolean; /** * Whether to generate and allow a UI for managing this post type in the admin. * Default is value of $public. */ show_ui?: boolean; /** * Where to show the post type in the admin menu. To work, $show_ui must be true. * If true, the post type is shown in its own top level menu. * If false, no menu is shown. * If a string of an existing top level menu ('tools.php' or 'edit.php?post_type=page', for example), * the post type will be placed as a sub-menu of that. * Default is value of $show_ui. */ show_in_menu?: boolean | string; /** * Makes this post type available via the admin bar. * Default is value of $show_in_menu. */ show_in_admin_bar?: boolean; /** * Makes this post type available for selection in navigation menus. * Default is value of $public. */ show_in_nav_menus?: boolean; /** * Whether to include the post type in the REST API. * Set this to true for the post type to be available in the block editor. */ show_in_rest?: boolean; /** * To change the base URL of REST API route. * Default is $post_type. */ rest_base?: string; /** * To change the namespace URL of REST API route. * Default is wp/v2. */ rest_namespace?: string; /** * REST API controller class name. * Default is 'WP_REST_Posts_Controller'. */ rest_controller_class?: string; /** * The URL to the icon to be used for this menu. * Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme — * this should begin with 'data:image/svg+xml;base64,'. * Pass the name of a Dashicons helper class to use a font icon, e.g. 'dashicons-chart-pie'. * Pass 'none' to leave div.wp-menu-image empty so an icon can be added via CSS. * Defaults to use the posts icon. */ menu_icon?: string; /** * The position in the menu order the post type should appear. * To work, $show_in_menu must be true. * Default null (at the bottom). */ menu_position?: string | number; /** * Whether to rename the capabilities for this post type. */ rename_capabilities?: boolean; /** * The singular capability name for this post type. */ singular_capability_name?: string; /** * The plural capability name for this post type. */ plural_capability_name?: string; /** * An array of taxonomy identifiers that will be registered for the post type. * Taxonomies can be registered later with register_taxonomy() or register_taxonomy_for_object_type(). */ taxonomies?: string[]; /** * The query var name for this post type. */ query_var_name?: string; /** * Provide a callback function that sets up the meta boxes for the edit form. * Do remove_meta_box() and add_meta_box() calls in the callback. * Default null. */ register_meta_box_cb?: string; /** * Custom text for the "Enter title here" placeholder in the title field. */ enter_title_here?: string; /** * The string to use to build the read, edit, and delete capabilities. * May be passed as an array to allow for alternative plurals when using this argument as a base to construct the capabilities, * e.g. array('story', 'stories'). * Default 'post'. */ capability_type?: string | [ string, string ]; /** * Array of capabilities for this post type. * $capability_type is used as a base to construct capabilities by default. * See get_post_type_capabilities(). */ capabilities?: { [key: string]: string; }; /** * Whether to use the internal default meta capability handling. * Default false. */ map_meta_cap?: boolean; /** * Core feature(s) the post type supports. Serves as an alias for calling add_post_type_support() directly. * * Core features include 'title', 'editor', 'comments', 'revisions', 'trackbacks', 'author', 'excerpt', * 'page-attributes', 'thumbnail', 'custom-fields', and 'post-formats'. * * Additionally, the 'revisions' feature dictates whether the post type will store revisions, * the 'autosave' feature dictates whether the post type will be autosaved, * and the 'comments' feature dictates whether the comments count will show on the edit screen. * * For backward compatibility reasons, adding 'editor' support implies 'autosave' support too. * * A feature can also be specified as an array of arguments to provide additional information about supporting that feature. * * Example: array( 'my_feature', array( 'field' => 'value' ) ). * * If false, no features will be added. * Default is an array containing 'title' and 'editor'. */ supports?: Array<"title" | "editor" | "author" | "thumbnail" | "excerpt" | "trackbacks" | "custom-fields" | "comments" | "revisions" | "page-attributes" | "post-formats"> & string[]; /** * Whether there should be post type archives, or if a string, the archive slug to use. * Will generate the proper rewrite rules if $rewrite is enabled. * Default false. */ has_archive?: boolean | string; /** * Triggers the handling of rewrites for this post type. To prevent rewrite, set to false. * Defaults to true, using $post_type as slug. * To specify rewrite rules, an array can be passed with any of these keys: * - slug (string): Customize the permastruct slug. Defaults to $post_type key. * - with_front (bool): Whether the permastruct should be prepended with WP_Rewrite::$front. Default true. * - feeds (bool): Whether the feed permastruct should be built for this post type. Default is value of $has_archive. * - pages (bool): Whether the permastruct should provide for pagination. Default true. * - ep_mask (int): Endpoint mask to assign. If not specified and permalink_epmask is set, inherits from $permalink_epmask. * If not specified and permalink_epmask is not set, defaults to EP_PERMALINK. */ rewrite?: boolean | { slug?: string; with_front?: boolean; pages?: boolean; feeds?: boolean; ep_mask?: number; }; /** * Sets the query_var key for this post type. * Defaults to $post_type key. * If false, a post type cannot be loaded at ?{query_var}={post_slug}. * If specified as a string, the query ?{query_var_string}={post_slug} will be valid. */ query_var?: boolean | string; /** * Whether to allow this post type to be exported. * Default true. */ can_export?: boolean; /** * Whether to delete posts of this type when deleting a user. * If true, posts of this type belonging to the user will be moved to Trash when the user is deleted. * If false, posts of this type belonging to the user will *not* be trashed or deleted. * If not set (the default), posts are trashed if post type supports the 'author' feature. * Otherwise posts are not trashed or deleted. * Default null. */ delete_with_user?: boolean; /** * Array of blocks to use as the default initial state for an editor session. * Each item should be an array containing block name and optional attributes. */ template?: Array; /** * Whether the block template should be locked if $template is set. * If set to 'all', the user is unable to insert new blocks, move existing blocks and delete blocks. * If set to 'insert', the user is able to move existing blocks but is unable to insert new blocks and delete blocks. * Default false. */ template_lock?: "all" | "insert" | false; }; /** * }}} */ /** * FONTS DECLARATIONS {{{ * This mirrors WordPress core's font-collection.json schema. */ /** * Font face settings with added preview property. */ type FontFace = { /** URL to a preview image of the font. */ preview?: string; /** CSS font-family value. */ fontFamily: string; /** CSS font-style value. */ fontStyle?: string; /** List of available font weights, separated by a space. */ fontWeight?: string | number; /** CSS font-display value. */ fontDisplay?: "auto" | "block" | "fallback" | "swap" | "optional"; /** Paths or URLs to the font files. */ src: DataSources.FileDataReference | DataSources.FileDataReference[]; /** CSS font-stretch value. */ fontStretch?: string; /** CSS ascent-override value. */ ascentOverride?: string; /** CSS descent-override value. */ descentOverride?: string; /** CSS font-variant value. */ fontVariant?: string; /** CSS font-feature-settings value. */ fontFeatureSettings?: string; /** CSS font-variation-settings value. */ fontVariationSettings?: string; /** CSS line-gap-override value. */ lineGapOverride?: string; /** CSS size-adjust value. */ sizeAdjust?: string; /** CSS unicode-range value. */ unicodeRange?: string; }; /** * Font collection schema for WordPress Font Library. */ type FontCollection = { /** JSON schema URI for font-collection.json. */ $schema?: string; /** Array of font families ready to be installed. */ font_families: Array<{ /** Font family settings with added preview property. */ font_family_settings: { /** Name of the font family preset, translatable. */ name: string; /** Kebab-case unique identifier for the font family preset. */ slug: string; /** CSS font-family value. */ fontFamily: string; /** URL to a preview image of the font family. */ preview?: string; /** Array of font-face definitions. */ fontFace?: FontFace[]; }; /** Array of category slugs. */ categories?: string[]; }>; }; /** * WordPress Content Schema {{{ */ /** * Post data type. It is inspired by the wp_insert_post() arguments, * but it diverges from it in a few ways. */ type WordPressPost = { /** * Username of the post author. * * If missing, the default value will be resolved in the following order * until one is available: * * * Default user defined in the runner configuration. * * The first administrator in the database. * * The first user in the database. * * A newly created user. * * The aggressive resolution is necessary because post_author is NOT NULL * in the database schema. */ post_author?: number; /** * The date of the post in UTC. Accepts format 'YYYY-MM-DD HH:MM:SS'. * Can be used to schedule future posts (when used with post_status: 'future'). * * @default Current time */ post_date?: string; /** * The main post content. Can contain HTML, shortcodes, etc. * While technically optional, posts are usually expected to have content. * * @default '' */ post_content?: string; /** The post title. */ post_title: string; /** The post excerpt. Default empty. */ post_excerpt?: string; /** The post status */ post_status?: "publish" | "pending" | "draft" | "auto-draft" | "future" | "private" | "inherit" | "trash"; /** The post type (e.g., 'post', 'page'). Default 'post'. */ post_type?: string; /** * Whether comments are allowed ('open' or 'closed'). * * @default 'open'. */ comment_status?: "open" | "closed"; /** A password to protect access. Default empty. */ post_password?: string; /** The URL slug. Default sanitized post_title for new posts. */ post_name?: string; /** Post parent name for hierarchical post types (e.g., pages). Default empty. */ post_parent_name?: string; /** Menu order within a post type. Default 0. */ menu_order?: number; /** MIME type for attachments. Default empty. */ post_mime_type?: string; /** Global Unique ID. Default empty. */ guid?: string; /** Array of category slugs. Defaults to the site's default category. */ post_category?: string[]; /** Array of tag names. Default empty. */ post_tags?: Array; /** * Taxonomy terms keyed by taxonomy name. * For hierarchical taxonomies: array of term names. * For non-hierarchical: array of term names or slugs. * * Examples: * ```json * tax_input: { * // For hierarchical taxonomies like categories * "category": ["Books", "Fiction", "Science Fiction"], * * // For non-hierarchical taxonomies like tags * "post_tag": ["bestseller", "featured", "summer-reading"], * * // For custom taxonomies * "genre": ["mystery", "thriller"], * "author": ["Jane Doe", "John Smith"] * } * ``` */ tax_input?: Record>; /** * Post meta keyed by meta key to value. Default empty. * * Examples: * ```json * meta_input: { * // Simple values * "price": "19.99", * "in_stock": true, * "stock": 42, * * // Array values * "related_products": [123, 456, 789], * "product_colors": ["red", "blue", "green"], * * // Object values * "_product_attributes": { * "color": { * "name": "Color", * "value": "Red", * "position": 0, * "visible": true * } * }, * "seo_data": { * "title": "Custom SEO Title", * "description": "Custom meta description", * "keywords": ["product", "featured"] * } * } * ``` */ meta_input?: Record; /** * Specifies the page template file to use. * This parameter only applies if post_type is 'page'. For other post types, it's ignored. * Provide the template filename (e.g., 'template-contact.php'). Include subdirectory if applicable (e.g., 'templates/full-width.php'). * To set a template for non-page post types, use meta_input with key '_wp_page_template'. * * @default '' */ page_template?: string; }; /** * }}} */ type ActivatePluginStep = { step: "activatePlugin"; /** * Path to the plugin directory as absolute path * (/wordpress/wp-content/plugins/plugin-name); or the plugin entry file * relative to the plugins directory (plugin-name/plugin-name.php). */ pluginPath: string; /** * Human-readable name of the plugin for the progress bar. * * For example, with the following Blueprint: * * ```json * { * "steps": [ * { * "step": "activatePlugin", * "pluginPath": "wordpress-seo/wp-seo.php", * "humanReadableName": "Yoast SEO" * } * ] * } * ``` * * The progress bar will show "Activating Yoast SEO" instead of * "Activating wordpress-seo/wp-seo.php". */ humanReadableName?: string; }; type ActivateThemeStep = { step: "activateTheme"; /** * The name of the theme directory inside wp-content/themes/ */ themeDirectoryName: string; /** * Human-readable name of the theme for the progress bar. * * For example, with the following Blueprint: * * ```json * { * "steps": [ * { * "step": "activateTheme", * "themeDirectoryName": "twentytwentythree", * "humanReadableName": "Twenty Twenty-Three" * } * ] * } * ``` * * The progress bar will show "Activating Twenty Twenty-Three" instead of * "Activating twentytwentythree". */ humanReadableName?: string; }; type CpStep = { step: "cp"; fromPath: string; toPath: string; }; type WordPressConstants = Record & Partial<{ WP_DEBUG: boolean; WP_DEBUG_LOG: boolean; WP_DEBUG_DISPLAY: boolean; SCRIPT_DEBUG: boolean; }>; type DefineConstantsStep = { step: "defineConstants"; constants: WordPressConstants; }; type EnableMultisiteStep = { /** Converts the target WordPress installation into a multisite network. */ step: "enableMultisite"; }; type ImportContentStep = { step: "importContent"; content: ContentDefinition[]; }; type ImportMediaStep = { step: "importMedia"; media: MediaDefinition[]; }; type ImportThemeStarterContentStep = { step: "importThemeStarterContent"; /** * The name of the theme to import content from. */ themeSlug?: string; }; type MkdirStep = { step: "mkdir"; path: string; }; type MvStep = { step: "mv"; fromPath: string; toPath: string; }; type RmStep = { step: "rm"; path: string; }; type RmdirStep = { step: "rmdir"; path: string; }; type ResetDataStep = { step: "resetData"; /** * Content types to remove. When omitted, all posts, pages, custom post * types, and comments are removed. */ contentTypes?: Array; }; type RunPHPStep = { step: "runPHP"; /** * The PHP file to execute. */ code: DataSources.FileDataReference; /** * Environment variables to set for this run. */ env?: Record; }; type RunSQLStep = { step: "runSQL"; source: DataSources.FileDataReference; }; /** * Sets the site language and download translations for WordPress core * and all the installed plugins and themes. */ type SetSiteLanguageStep = { step: "setSiteLanguage"; /** * The language to set, e.g. 'en_US' */ language: string; }; type SetSiteOptionsStep = { step: "setSiteOptions"; options: Record; }; /** * Unzips a file. While this step is not strictly necessary, it is * very convenient for: * * * Working with GitHub releases that output doubly zipped data. * * Preprocessing zipped data before using them in the Blueprint. */ type UnzipStep = { step: "unzip"; /** * The zip file resource to extract. */ zipFile: DataSources.FileDataReference; /** * The path to extract the zip file to inside the virtual filesystem. */ extractToPath: string; }; type WpCliStep = { step: "wp-cli"; command: string; wpCliPath?: string; }; type WriteFilesStep = { step: "writeFiles"; files: Record; }; type PluginStep = { step: "installPlugin"; } & PluginObjectDefinition; type ThemeStep = { step: "installTheme"; /** * Whether to activate the theme after installing it. * * This is not a part of the theme definition. Only the step * can explicitly provide this option. The default value is `true`. */ active?: boolean; } & ThemeObjectDefinition; type Step = ActivatePluginStep | ActivateThemeStep | CpStep | DefineConstantsStep | EnableMultisiteStep | ImportContentStep | ImportMediaStep | ImportThemeStarterContentStep | PluginStep | ThemeStep | MkdirStep | MvStep | RmStep | RmdirStep | ResetDataStep | RunPHPStep | RunSQLStep | SetSiteLanguageStep | SetSiteOptionsStep | UnzipStep | WpCliStep | WriteFilesStep; type JsonValue = string | boolean | number | JsonValue[] | { [key: string]: JsonValue; }; export {}; } export type BlueprintV2Declaration = V2Schema.BlueprintV2; export type BlueprintV2 = BlueprintV2Declaration | BlueprintBundle; /** * A filesystem structure containing a /blueprint.json file and any * resources referenced by that blueprint. */ export type BlueprintBundle = ReadableFilesystemBackend; export type BlueprintDeclaration = BlueprintV1Declaration | BlueprintV2Declaration; export type Blueprint = BlueprintV1 | BlueprintV2; export interface RuntimeConfiguration { phpVersion: AllPHPVersion; wpVersion: string; intl: boolean; networking: boolean; extraLibraries: ExtraLibrary[]; constants: PHPConstants; } export type ExtraLibrary = "wp-cli"; export type PHPConstants = Record; export type StreamBundledFile = (relativePath: string) => Promise; export type BlueprintV1 = BlueprintV1Declaration | BlueprintBundle; /** * PHP versions accepted in Blueprint schema. * Includes deprecated versions (7.2, 7.3) which are automatically * upgraded to 7.4 during compilation. */ export type BlueprintPHPVersion = AllPHPVersion | "7.2" | "7.3"; /** * The Blueprint declaration, typically stored in a blueprint.json file. */ export type BlueprintV1Declaration = { /** * The URL to navigate to after the blueprint has been run. */ landingPage?: string; /** * Optional description. It doesn't do anything but is exposed as * a courtesy to developers who may want to document which blueprint * file does what. * * @deprecated Use meta.description instead. */ description?: string; /** * Optional metadata. Used by the Blueprints gallery at https://github.com/WordPress/blueprints */ meta?: { /** * A clear and concise name for your Blueprint. */ title: string; /** * A brief explanation of what your Blueprint offers. */ description?: string; /** * A GitHub username of the author of this Blueprint. */ author: string; /** * Relevant categories to help users find your Blueprint in the future * Blueprints section on WordPress.org. */ categories?: string[]; }; /** * The preferred PHP and WordPress versions to use. */ preferredVersions?: { /** * The preferred PHP version to use. * If not specified, the latest supported version will be used. * * Note: PHP 7.2 and 7.3 are deprecated and will be automatically upgraded to 7.4. */ php: BlueprintPHPVersion | "latest"; /** * The preferred WordPress version to use, or `false` to boot a * PHP-only Playground without downloading or installing WordPress. * If not specified, the latest supported version will be used. * * When set to `false`, WordPress-specific Blueprint fields * (`plugins`, `siteOptions`, `login`, and WordPress-only steps) * are rejected at compile time. */ wp: string | "latest" | false; }; features?: { /** Should boot with support for Intl dynamic extension */ intl?: boolean; /** Should boot with support for network request via wp_safe_remote_get? */ networking?: boolean; }; /** * Extra libraries to preload into the Playground instance. */ extraLibraries?: ExtraLibrary[]; /** * PHP Constants to define on every request */ constants?: PHPConstants; /** * WordPress plugins to install and activate */ plugins?: Array; /** * WordPress site options to define */ siteOptions?: Record & { /** The site title */ blogname?: string; }; /** * User to log in as. * If true, logs the user in as admin/password. */ login?: boolean | { username: string; password: string; }; /** * @deprecated No longer used. Feel free to remove it from your Blueprint. */ phpExtensionBundles?: any; /** * The steps to run after every other operation in this Blueprint was * executed. */ steps?: Array; }; export declare class BlueprintReflection { private readonly declaration; private readonly bundle; private readonly version; static create(blueprint: Blueprint): Promise; static createFromDeclaration(declaration: BlueprintV1Declaration | BlueprintV2Declaration, bundle?: BlueprintBundle | undefined): BlueprintReflection; protected constructor(declaration: BlueprintV1Declaration | BlueprintV2Declaration, bundle: BlueprintBundle | undefined, version: number); getVersion(): number; getDeclaration(): V2Schema.BlueprintV2 | BlueprintV1Declaration; isBundle(): boolean; getBundle(): ReadableFilesystemBackend | undefined; getBlueprint(): Blueprint; } export interface _SchemaObject { id?: string; $id?: string; $schema?: string; [x: string]: any; } export interface SchemaObject extends _SchemaObject { id?: string; $id?: string; $schema?: string; $async?: false; [x: string]: any; } export interface AsyncSchema extends _SchemaObject { $async: true; } export type AnySchemaObject = SchemaObject | AsyncSchema; export interface ErrorObject, S = unknown> { keyword: K; instancePath: string; schemaPath: string; params: P; propertyName?: string; message?: string; schema?: S; parentSchema?: AnySchemaObject; data?: unknown; } /** Thrown when a Blueprint declaration does not conform to its schema. */ export declare class InvalidBlueprintError extends Error { readonly validationErrors?: unknown; constructor(message: string, validationErrors?: unknown); } /** * Error thrown when a single Blueprint step fails during execution. * * This error carries structured information about the failing step so that * consumers (e.g. the Playground UI) do not have to parse human‑readable * error messages to understand what went wrong. */ export declare class BlueprintStepExecutionError extends Error { readonly stepNumber: number; readonly step: StepDefinition; readonly messages: string[]; constructor(options: { stepNumber: number; step: StepDefinition; cause: unknown; }); } export type CompiledV1Step = (php: UniversalPHP) => Promise | void; export interface CompiledBlueprintV1 { /** The requested versions of PHP and WordPress for the blueprint */ versions: { php: AllPHPVersion; wp: string; }; features: { /** Should boot with support for Intl dynamic extension */ intl: boolean; /** Should boot with support for network request via wp_safe_remote_get? */ networking: boolean; }; extraLibraries: ExtraLibrary[]; /** The compiled steps for the blueprint */ run: (playground: UniversalPHP) => Promise; } export type OnStepCompleted = (output: any, step: StepDefinition) => any; export interface CompileBlueprintV1Options { /** Optional progress tracker to monitor progress */ progress?: ProgressTracker; /** Optional semaphore to control access to a shared resource */ semaphore?: Semaphore; /** Optional callback with step output */ onStepCompleted?: OnStepCompleted; /** Optional callback with blueprint validation result */ onBlueprintValidated?: (blueprint: BlueprintV1Declaration) => void; /** * Proxy URL to use for cross-origin requests. * * For example, if corsProxy is set to "https://cors.wordpress.net/proxy.php", * then the CORS requests to https://github.com/WordPress/gutenberg.git would actually * be made to https://cors.wordpress.net/proxy.php?https://github.com/WordPress/gutenberg.git. */ corsProxy?: string; /** * A filesystem to use for the blueprint. */ streamBundledFile?: StreamBundledFile; /** * Additional headers to pass to git operations. * A function that returns headers based on the URL being accessed. */ gitAdditionalHeadersCallback?: (url: string) => Record; /** * Additional steps to add to the blueprint. */ additionalSteps?: any[]; } export declare function compileBlueprintV1(input: BlueprintV1Declaration | BlueprintBundle, options?: CompileBlueprintV1Options): Promise; export declare function isBlueprintBundle(input: any): input is BlueprintBundle; export declare function getBlueprintDeclaration(blueprint: BlueprintV1 | BlueprintBundle): Promise; export type BlueprintValidationResult = { valid: true; } | { valid: false; errors: ErrorObject[]; }; export declare function validateBlueprint(blueprintMaybe: object): BlueprintValidationResult; /** * Determines if a step is a StepDefinition object * * @param step The object to test * @returns Whether the object is a StepDefinition */ export declare function isStepDefinition(step: Step | string | undefined | false | null): step is StepDefinition; export declare function runBlueprintV1Steps(compiledBlueprint: CompiledBlueprintV1, playground: UniversalPHP): Promise; /** * Validates either Blueprint declaration version without loading the v2 * validator for v1 declarations. */ export declare function validateBlueprintDeclaration(blueprintMaybe: unknown): Promise; /** * Exports the WordPress database as a WXR file using * the core WordPress export tool. * * @param playground Playground client * @returns WXR file */ export declare function exportWXR(playground: UniversalPHP): Promise; /** * Creates a Playground site archive containing user-owned wp-content, * wp-config.php, and export metadata. Runtime artifacts are supplied by the * Playground that imports the archive. * * @param playground Playground client. */ export declare const zipWpContent: (playground: UniversalPHP) => Promise; /** Describes whether Playground creates a site or applies to mounted files. */ export type BlueprintV2SiteMode = "create-new-site" | "apply-to-existing-site"; /** * Verifies that an existing site satisfies its Blueprint v2 WordPress version. * * Only constraint objects restrict an existing site. Shorthand versions, * including `latest` and concrete releases, are new-site selection hints. * `preferred` is also a selection hint and does not narrow compatibility. */ export declare function assertBlueprintV2WordPressVersionCompatibility(declaration: BlueprintV2Declaration, installedVersion: string): Promise; export type ResolveRuntimeConfigurationOptions = { /** Determines whether WordPress is selected for download or checked in place. */ siteMode?: BlueprintV2SiteMode; }; /** * Resolves the runtime settings required before executing a Blueprint. * * Blueprint v1 settings come from its compiled form. Blueprint v2 settings are * delegated to the v2 runtime configuration resolver. Existing-site mode * validates WordPress constraints without selecting a release to download. */ export declare function resolveRuntimeConfiguration(blueprint: Blueprint, options?: ResolveRuntimeConfigurationOptions): Promise; export type BlueprintV2ApplicationOptions = BlueprintV2Declaration["applicationOptions"]; export type BlueprintV2ContentBaseline = NonNullable; export type BlueprintV2Constants = NonNullable; export type BlueprintV2SiteOptions = NonNullable; export type BlueprintV2MuPlugin = NonNullable[number]; export type BlueprintV2Theme = NonNullable[number]; export type BlueprintV2ActiveTheme = NonNullable; export type BlueprintV2Plugin = NonNullable[number]; export type BlueprintV2Fonts = NonNullable; export type BlueprintV2Media = NonNullable[number]; export type BlueprintV2Role = NonNullable[number]; export type BlueprintV2User = NonNullable[number]; export type BlueprintV2PostTypes = NonNullable; export type BlueprintV2Content = NonNullable[number]; export type BlueprintV2Step = NonNullable[number]; export type BlueprintV2ExecutionPlan = BlueprintV2ExecutionPlanItem[]; export type BlueprintV2StepPlan = StepDefinition[]; export type BlueprintV2ExecutionPlanItem = { type: "applyContentBaseline"; contentBaseline: BlueprintV2ContentBaseline; sourcePath: "/contentBaseline"; } | { type: "applyUsersBaseline"; sourcePath: "/usersBaseline"; } | { type: "defineWpConfigConsts"; consts: BlueprintV2Constants; } | { type: "setSiteOptions"; options: BlueprintV2SiteOptions; } | { type: "installMuPlugin"; muPlugin: BlueprintV2MuPlugin; sourcePath: string; } | { type: "installTheme"; theme: BlueprintV2Theme; active: false; sourcePath: string; } | { type: "installTheme"; theme: BlueprintV2ActiveTheme; active: true; sourcePath: string; } | { type: "installPlugin"; plugin: BlueprintV2Plugin; sourcePath: string; } | { type: "installFonts"; fonts: BlueprintV2Fonts; } | { type: "importMedia"; media: BlueprintV2Media; sourcePath: string; } | { type: "setSiteLanguage"; language: string; } | { type: "defineRoles"; roles: BlueprintV2Role[]; } | { type: "defineUsers"; users: BlueprintV2User[]; } | { type: "definePostTypes"; postTypes: BlueprintV2PostTypes; } | { type: "importContent"; content: BlueprintV2Content; sourcePath: string; } | { type: "runStep"; step: BlueprintV2Step; sourcePath: string; }; export type CompiledBlueprintV2 = { runtime: RuntimeConfiguration; applicationOptions?: BlueprintV2ApplicationOptions; plan: BlueprintV2ExecutionPlan; steps: BlueprintV2StepPlan; unsupportedPlan: BlueprintV2ExecutionPlan; run: (playground: UniversalPHP) => Promise; }; export type CompileBlueprintV2Options = Pick & ResolveRuntimeConfigurationOptions & { onBlueprintValidated?: (blueprint: BlueprintV2Declaration) => void; }; export type ResolveBlueprintV2WordPressSourceOptions = Pick; /** * Compiles a Blueprint v2 declaration into the pieces the TypeScript runner can * understand today. * * It resolves runtime options, creates an ordered v2 execution plan, and lowers * supported plan items into v1 step records. Fully lowered plans run through the * existing v1 runner; unsupported items stay visible and block execution before * any partial work is applied. */ export declare function compileBlueprintV2(declaration: BlueprintV2Declaration, options?: CompileBlueprintV2Options): Promise; /** * Loads a custom WordPress source into the file expected by the boot API. * * Built-in versions and HTTP(S) ZIP URLs already use each consumer's normal * WordPress download path. Execution-context, inline, and Git references need * the Blueprint resource loader to turn them into a concrete archive first. */ export declare function resolveBlueprintV2WordPressSource(declaration: BlueprintV2Declaration, options?: ResolveBlueprintV2WordPressSourceOptions): Promise; /** * Converts the top-level Blueprint v2 fields into a simple ordered plan. * * The plan keeps the original v2 data intact. It only decides execution order * and records where each item came from, which makes unsupported items visible * instead of silently dropping them during lowering. */ export declare function createBlueprintV2ExecutionPlan(declaration: BlueprintV2Declaration, siteMode?: BlueprintV2SiteMode): BlueprintV2ExecutionPlan; export declare class BlueprintFetchError extends Error { readonly url: string; constructor(message: string, url: string, options?: ErrorOptions); } export interface ResolveRemoteBlueprintOptions { fetch?: typeof fetch; corsProxy?: string; } /** * Resolves a remote blueprint from a URL. * * @param url - The URL of the blueprint to resolve. * @returns A promise that resolves to the resolved blueprint. */ export declare function resolveRemoteBlueprint(url: string, options?: ResolveRemoteBlueprintOptions): Promise; /** * Returns the paths reserved for legacy runtime artifacts. db.php is included * only when the file carries Playground's marker; unmarked user drop-ins * remain part of the site snapshot. */ export declare function getLegacyPlaygroundRuntimeWpContentPaths(playground: UniversalPHP, wpContentPath: string): Promise; export type BlueprintExecutionPath = "v1" | "v2"; export type CompiledBlueprintForExecution = { version: 1; declaration: BlueprintV1Declaration; compiled: CompiledBlueprintV1; run: (playground: UniversalPHP) => Promise; } | { version: 2; declaration: BlueprintV2Declaration; compiled: CompiledBlueprintV2; run: (playground: UniversalPHP) => Promise; }; export interface CompileBlueprintForExecutionOptions extends Omit, ResolveRuntimeConfigurationOptions { onBlueprintValidated?: (blueprint: BlueprintDeclaration) => void; } export type BlueprintExecutionInput = Blueprint | BlueprintBundle | string; /** * Compiles a Blueprint into the shape consumers need before execution. * * The legacy `compileBlueprint()` export intentionally remains v1-only for * backwards compatibility. This helper is the version-aware entrypoint that * newer callers can migrate to as Blueprint v2 support grows. */ export declare function compileBlueprintForExecution(input: BlueprintExecutionInput, options?: CompileBlueprintForExecutionOptions): Promise; /** * @deprecated This function is a no-op. Playground no longer uses a proxy to download plugins and themes. * To be removed in v0.3.0 */ export declare function setPluginProxyURL(): void; export type WordPressInstallMode = "download-and-install" | "install-from-existing-files" | "install-from-existing-files-if-needed" | "do-not-attempt-installing"; /** * Represents the type of node in PHP file system. */ export type FSNodeType = "file" | "directory"; /** * Represents an update operation on a file system node. */ export type UpdateFileOperation = { /** The type of operation being performed. */ operation: "WRITE"; /** The path of the node being updated. */ path: string; /** Optional. The new contents of the file. */ data?: Uint8Array; nodeType: "file"; }; /** * Represents a directory operation. */ export type CreateOperation = { /** The type of operation being performed. */ operation: "CREATE"; /** The path of the node being created. */ path: string; /** The type of the node being created. */ nodeType: FSNodeType; }; export type DeleteOperation = { /** The type of operation being performed. */ operation: "DELETE"; /** The path of the node being updated. */ path: string; /** The type of the node being updated. */ nodeType: FSNodeType; }; /** * Represents a rename operation on a file or directory in PHP file system. */ export type RenameOperation = { /** The type of operation being performed. */ operation: "RENAME"; /** The original path of the file or directory being renamed. */ path: string; /** The new path of the file or directory after the rename operation. */ toPath: string; /** The type of node being renamed (file or directory). */ nodeType: FSNodeType; }; export type FilesystemOperation = CreateOperation | UpdateFileOperation | DeleteOperation | RenameOperation; /** * Built-in PHP extensions shipped with `@php-wasm/web`. */ export type BuiltInPHPWebExtensionName = "intl"; /** * External PHP extension source that can be installed before PHP starts. * * External sources are supported in JSPI runtimes only. Asyncify support is * limited to bundled extensions shipped with this package. */ export type RuntimePHPWebExtensionSource = Omit; /** * PHP extension request accepted by `loadWebRuntime()`. * * The array may mix built-in extension names with external extension sources: * * ```ts * await loadWebRuntime('8.4', { * extensions: [ * 'intl', * { source: { format: 'manifest', manifestUrl } }, * ], * }); * ``` */ export type PHPWebExtension = BuiltInPHPWebExtensionName | { name: BuiltInPHPWebExtensionName; } | RuntimePHPWebExtensionSource; export type SyncProgress = { /** The number of files that have been synced. */ files: number; /** The number of all files that need to be synced. */ total: number; /** The current stage of the initial sync. */ phase?: "copying" | "flushing"; }; export type SyncProgressCallback = (progress: SyncProgress) => void | Promise; declare function createMemoizedFetch(originalFetch?: (input: RequestInfo | URL, init?: RequestInit) => Promise): (url: string, options?: RequestInit) => Promise; export interface MountDescriptor { mountpoint: string; device: MountDevice; initialSyncDirection: "opfs-to-memfs" | "memfs-to-opfs"; } export type WorkerBootOptions = { wpVersion?: string; /** A caller-provided WordPress archive used instead of downloading one. */ wordPressZip?: File; sqliteDriverVersion?: string; phpVersion?: AllPHPVersion; sapiName?: string; scope: string; extensions?: PHPWebExtension[]; withNetworking: boolean; mounts?: Array; /** @deprecated Use `wordpressInstallMode` instead. */ shouldInstallWordPress?: boolean; corsProxyUrl?: string; /** Blueprint v2 declaration used for worker-side execution or preflight checks. */ blueprint?: BlueprintDeclaration; /** * How to handle WordPress installation. * Defaults to `download-and-install`. */ wordpressInstallMode?: WordPressInstallMode; /** * Path aliases that map URL prefixes to filesystem paths outside * the document root. Similar to Nginx's `alias` directive. */ pathAliases?: PathAlias[]; }; declare abstract class PlaygroundWorkerEndpoint extends PHPWorker { booted: boolean; /** * A string representing the scope of the Playground instance. */ scope: string | undefined; /** * A string representing the requested version of WordPress. */ requestedWordPressVersion: string | undefined; /** * A string representing the version of WordPress that was loaded. */ loadedWordPressVersion: string | undefined; unmounts: Record any>; private opfsMounts; private networkTransport; private requestHandler; protected downloadMonitor: EmscriptenDownloadMonitor; protected memoizedFetch: ReturnType; constructor(monitor: EmscriptenDownloadMonitor); protected computeSiteUrl(scope: string): string; protected createRequestHandler({ siteUrl, sapiName, corsProxyUrl, knownRemoteAssetPaths, extensions, withNetworking, phpVersion, pathAliases, }: { siteUrl: string; sapiName: string; corsProxyUrl?: string; knownRemoteAssetPaths: Set; extensions?: PHPWebExtension[]; withNetworking: boolean; phpVersion: AllPHPVersion; pathAliases?: PathAlias[]; }): Promise; protected finalizeAfterBoot(requestHandler: any, withNetworking: boolean, knownRemoteAssetPaths: Set): Promise; protected getRequestHandler(required?: true): PHPRequestHandler; protected getRequestHandler(required: false): PHPRequestHandler | undefined; /** * @returns WordPress module details, including the static assets directory and default theme. */ getWordPressModuleDetails(): Promise<{ majorVersion: string | undefined; staticAssetsDirectory: string | undefined; }>; getMinifiedWordPressVersions(): Promise<{ all: { trunk: string; beta: string; "7.0": string; "6.9": string; "6.8": string; "6.7": string; "6.6": string; "6.5": string; "6.4": string; "6.3": string; }; latest: string; }>; hasOpfsMount(mountpoint: string): Promise; mountOpfs(options: MountDescriptor, onProgress?: SyncProgressCallback): Promise; flushOpfs(mountpoint: string): Promise; /** * Flushes and detaches an OPFS mount. * * On success, clears its tracking. If the final flush fails, keeps the mount * registered for retry and rejects with the original persistence error. * Other unmount failures clear tracking because the mount did not guarantee * that it remained live. */ unmountOpfs(mountpoint: string): Promise; backfillStaticFilesRemovedFromMinifiedBuild(): Promise; hasCachedStaticFilesRemovedFromMinifiedBuild(): Promise; abstract boot(_: any): Promise; /** * Pre-fetch the slow initial burst of wp_update_* requests to greatly * improve the first wp-admin load time. */ prefetchUpdateChecks(): Promise; journalFSEvents(root: string, callback: (op: FilesystemOperation) => void): Promise<() => any>; replayFSJournal(events: FilesystemOperation[]): Promise; protected mountOpfsIntoPhp(php: PHP, options: MountDescriptor, onProgress?: SyncProgressCallback): Promise; } export interface ProgressBarOptions { caption?: string; progress?: number; isIndefinite?: boolean; visible?: boolean; } export interface WebClientMixin extends ProgressReceiver { /** * Sets the progress bar options. * @param options The progress bar options. */ setProgress(options: ProgressBarOptions): Promise; /** * Sets the loaded state. */ setLoaded(): Promise; /** * Sets the navigation event listener. * @param fn The function to be called when a navigation event occurs. */ onNavigation(fn: (url: string) => void): Promise; /** * Navigates to the requested path. * @param requestedPath The requested path. */ goTo(requestedPath: string): Promise; /** * Gets the current URL. */ getCurrentURL(): Promise; /** * Renders the site's front page in a disposable 1024×768 browsing context * and returns a compact 320×240 image. * * This method does not persist the image or synchronize it with OPFS. * Callers own the result's lifecycle and must discard it if the site changes * while the asynchronous capture is running. * * DOM cloning and canvas rendering run in the captured document's event * loop. A worker handles supported resource fetches, while explicit task * yields keep that document responsive during cloning. */ captureSiteThumbnail(): Promise; /** * Sets the iframe sandbox flags. * @param flags The iframe sandbox flags. */ setIframeSandboxFlags(flags: string[]): Promise; /** * The onDownloadProgress event listener. */ onDownloadProgress: PlaygroundWorkerEndpoint["onDownloadProgress"]; journalFSEvents: PlaygroundWorkerEndpoint["journalFSEvents"]; replayFSJournal: PlaygroundWorkerEndpoint["replayFSJournal"]; addEventListener: PlaygroundWorkerEndpoint["addEventListener"]; removeEventListener: PlaygroundWorkerEndpoint["removeEventListener"]; backfillStaticFilesRemovedFromMinifiedBuild: PlaygroundWorkerEndpoint["backfillStaticFilesRemovedFromMinifiedBuild"]; hasCachedStaticFilesRemovedFromMinifiedBuild: PlaygroundWorkerEndpoint["hasCachedStaticFilesRemovedFromMinifiedBuild"]; /** @inheritDoc @php-wasm/universal!UniversalPHP.onMessage */ onMessage(listener: MessageListener): Promise<() => Promise>; mountOpfs(options: MountDescriptor, onProgress?: SyncProgressCallback): Promise; flushOpfs(mountpoint: string): Promise; /** * Flushes and detaches an OPFS mount. * * On success, clears its tracking. If the final flush fails, keeps the mount * registered for retry and rejects with the original persistence error. * Other unmount failures clear tracking because the mount did not guarantee * that it remained live. */ unmountOpfs(mountpoint: string): Promise; boot(options: WorkerBootOptions): Promise; } export type SiteThumbnail = { /** The encoded image's MIME type. */ mime: string; /** The base64 payload without a data URL prefix. */ data: string; }; /** * The Playground Client interface. */ export interface PlaygroundClient extends RemoteAPI { } export interface StartPlaygroundOptions { iframe: HTMLIFrameElement; remoteUrl: string; progressTracker?: ProgressTracker; disableProgressBar?: boolean; blueprint?: BlueprintV1; /** * PHP extensions to install before the runtime starts. */ extensions?: PHPWebExtension[]; onBlueprintStepCompleted?: OnStepCompleted; onBlueprintValidated?: (blueprint: BlueprintV1Declaration) => void; /** * Called when the playground client is connected, but before the blueprint * steps are run. * * @param playground * @returns */ onClientConnected?: (playground: PlaygroundClient) => void; /** * The SAPI name PHP will use. * @internal * @private */ sapiName?: string; mounts?: Array; /** * @deprecated Use `wordpressInstallMode` instead. * * Whether to download/install WordPress files. Set this to `false` when * WordPress files are already available, for example from `mounts` or a * saved site. */ shouldInstallWordPress?: boolean; /** * The string prefix used in the site URL served by the currently * running remote.html. E.g. for a prefix like `/scope:playground/`, * the scope would be `playground`. See the `@php-wasm/scopes` package * for more details. */ scope?: string; /** * Proxy URL to use for cross-origin requests. * * For example, if corsProxy is set to "https://cors.wordpress.net/proxy.php", * then the CORS requests to https://github.com/WordPress/wordpress-playground.git would actually * be made to https://cors.wordpress.net/proxy.php?https://github.com/WordPress/wordpress-playground.git. * * The Blueprints library will arbitrarily choose which requests to proxy. If you need * to proxy every single request, do not use this option. Instead, you should preprocess * your Blueprint to replace all cross-origin URLs with the proxy URL. */ corsProxy?: string; /** * Additional headers to pass to git operations. * A function that returns headers based on the URL being accessed. */ gitAdditionalHeadersCallback?: (url: string) => Record; /** * The version of the SQLite driver to use. * Defaults to the latest development version. */ sqliteDriverVersion?: string; /** * How to handle WordPress installation. * Defaults to `download-and-install`. */ wordpressInstallMode?: WordPressInstallMode; /** * Path aliases that map URL prefixes to filesystem paths outside * the document root. Similar to Nginx's `alias` directive. * * @example * ```ts * pathAliases: [ * { urlPrefix: '/phpmyadmin', fsPath: '/tools/phpmyadmin' } * ] * ``` */ pathAliases?: PathAlias[]; } export interface StartPlaygroundWebOptions extends Omit { blueprint?: Blueprint; onBlueprintValidated?: (blueprint: BlueprintDeclaration) => void; } /** * Loads playground in iframe and returns a PlaygroundClient instance. * * @param iframe Any iframe with Playground's remote.html loaded. * @param options Options for loading the playground. * @returns A PlaygroundClient instance. */ export declare function startPlaygroundWeb(options: StartPlaygroundWebOptions): Promise; export {};