@php-wasm/web 0.7.1 → 0.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -59,6 +59,7 @@ declare class PHPResponse implements PHPResponseData {
59
59
  /** @inheritDoc */
60
60
  readonly httpStatusCode: number;
61
61
  constructor(httpStatusCode: number, headers: Record<string, string[]>, body: ArrayBuffer, errors?: string, exitCode?: number);
62
+ static forHttpCode(httpStatusCode: number, text?: string): PHPResponse;
62
63
  static fromRawData(data: PHPResponseData): PHPResponse;
63
64
  toRawData(): PHPResponseData;
64
65
  /**
@@ -437,23 +438,57 @@ export interface ListFilesOptions {
437
438
  */
438
439
  prependPath: boolean;
439
440
  }
440
- declare const SupportedPHPVersions: readonly [
441
- "8.3",
442
- "8.2",
443
- "8.1",
444
- "8.0",
445
- "7.4",
446
- "7.3",
447
- "7.2",
448
- "7.1",
449
- "7.0"
450
- ];
451
- export type SupportedPHPVersion = (typeof SupportedPHPVersions)[number];
441
+ export type PHPRuntimeId = number;
442
+ export type PHPRuntime = any;
443
+ export type PHPLoaderModule = {
444
+ dependencyFilename: string;
445
+ dependenciesTotalSize: number;
446
+ init: (jsRuntime: string, options: EmscriptenOptions) => PHPRuntime;
447
+ };
448
+ export type EmscriptenOptions = {
449
+ onAbort?: (message: string) => void;
450
+ /**
451
+ * Set to true for debugging tricky WebAssembly errors.
452
+ */
453
+ debug?: boolean;
454
+ ENV?: Record<string, string>;
455
+ locateFile?: (path: string) => string;
456
+ noInitialRun?: boolean;
457
+ print?: (message: string) => void;
458
+ printErr?: (message: string) => void;
459
+ quit?: (status: number, toThrow: any) => void;
460
+ onRuntimeInitialized?: () => void;
461
+ monitorRunDependencies?: (left: number) => void;
462
+ onMessage?: (listener: EmscriptenMessageListener) => void;
463
+ instantiateWasm?: (info: WebAssembly.Imports, receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => void;
464
+ } & Record<string, any>;
465
+ export type EmscriptenMessageListener = (type: string, data: string) => void;
466
+ export interface SemaphoreOptions {
467
+ /**
468
+ * The maximum number of concurrent locks.
469
+ */
470
+ concurrency: number;
471
+ /**
472
+ * The maximum time to wait for a lock to become available.
473
+ */
474
+ timeout?: number;
475
+ }
476
+ declare class Semaphore {
477
+ private _running;
478
+ private concurrency;
479
+ private timeout?;
480
+ private queue;
481
+ constructor({ concurrency, timeout }: SemaphoreOptions);
482
+ get remaining(): number;
483
+ get running(): number;
484
+ acquire(): Promise<() => void>;
485
+ run<T>(fn: () => T | Promise<T>): Promise<T>;
486
+ }
452
487
  export type RewriteRule = {
453
488
  match: RegExp;
454
489
  replacement: string;
455
490
  };
456
- export interface PHPRequestHandlerConfiguration {
491
+ export interface BaseConfiguration {
457
492
  /**
458
493
  * The directory in the PHP filesystem where the server will look
459
494
  * for the files to serve. Default: `/var/www`.
@@ -468,18 +503,47 @@ export interface PHPRequestHandlerConfiguration {
468
503
  */
469
504
  rewriteRules?: RewriteRule[];
470
505
  }
471
- declare class PHPRequestHandler {
472
- #private;
473
- rewriteRules: RewriteRule[];
506
+ export type PHPRequestHandlerFactoryArgs<PHP extends BasePHP> = PHPFactoryOptions & {
507
+ requestHandler: PHPRequestHandler<PHP>;
508
+ };
509
+ export type PHPRequestHandlerConfiguration<PHP extends BasePHP> = BaseConfiguration & ({
474
510
  /**
475
- * The PHP instance
511
+ * PHPProcessManager is required because the request handler needs
512
+ * to make a decision for each request.
513
+ *
514
+ * Static assets are served using the primary PHP's filesystem, even
515
+ * when serving 100 static files concurrently. No new PHP interpreter
516
+ * is ever created as there's no need for it.
517
+ *
518
+ * Dynamic PHP requests, however, require grabbing an available PHP
519
+ * interpreter, and that's where the PHPProcessManager comes in.
476
520
  */
477
- php: BasePHP;
521
+ processManager: PHPProcessManager<PHP>;
522
+ } | {
523
+ phpFactory: (requestHandler: PHPRequestHandlerFactoryArgs<PHP>) => Promise<PHP>;
524
+ /**
525
+ * The maximum number of PHP instances that can exist at
526
+ * the same time.
527
+ */
528
+ maxPhpInstances?: number;
529
+ });
530
+ declare class PHPRequestHandler<PHP extends BasePHP> {
531
+ #private;
532
+ rewriteRules: RewriteRule[];
533
+ processManager: PHPProcessManager<PHP>;
478
534
  /**
535
+ * The request handler needs to decide whether to serve a static asset or
536
+ * run the PHP interpreter. For static assets it should just reuse the primary
537
+ * PHP even if there's 50 concurrent requests to serve. However, for
538
+ * dynamic PHP requests, it needs to grab an available interpreter.
539
+ * Therefore, it cannot just accept PHP as an argument as serving requests
540
+ * requires access to ProcessManager.
541
+ *
479
542
  * @param php - The PHP instance.
480
543
  * @param config - Request Handler configuration.
481
544
  */
482
- constructor(php: BasePHP, config?: PHPRequestHandlerConfiguration);
545
+ constructor(config: PHPRequestHandlerConfiguration<PHP>);
546
+ getPrimaryPhp(): Promise<PHP>;
483
547
  /**
484
548
  * Converts a path to an absolute URL based at the PHPRequestHandler
485
549
  * root.
@@ -496,7 +560,6 @@ declare class PHPRequestHandler {
496
560
  * @returns The relative path.
497
561
  */
498
562
  internalUrlToPath(internalUrl: string): string;
499
- get isRequestRunning(): boolean;
500
563
  /**
501
564
  * The absolute URL of this PHPRequestHandler instance.
502
565
  */
@@ -556,57 +619,11 @@ declare class PHPRequestHandler {
556
619
  */
557
620
  request(request: PHPRequest): Promise<PHPResponse>;
558
621
  }
559
- export type PHPRuntimeId = number;
560
- export type PHPRuntime = any;
561
- export type PHPLoaderModule = {
562
- dependencyFilename: string;
563
- dependenciesTotalSize: number;
564
- init: (jsRuntime: string, options: EmscriptenOptions) => PHPRuntime;
565
- };
566
- export type EmscriptenOptions = {
567
- onAbort?: (message: string) => void;
568
- /**
569
- * Set to true for debugging tricky WebAssembly errors.
570
- */
571
- debug?: boolean;
572
- ENV?: Record<string, string>;
573
- locateFile?: (path: string) => string;
574
- noInitialRun?: boolean;
575
- print?: (message: string) => void;
576
- printErr?: (message: string) => void;
577
- quit?: (status: number, toThrow: any) => void;
578
- onRuntimeInitialized?: () => void;
579
- monitorRunDependencies?: (left: number) => void;
580
- onMessage?: (listener: EmscriptenMessageListener) => void;
581
- instantiateWasm?: (info: WebAssembly.Imports, receiveInstance: (instance: WebAssembly.Instance, module: WebAssembly.Module) => void) => void;
582
- } & Record<string, any>;
583
- export type EmscriptenMessageListener = (type: string, data: string) => void;
584
- export interface SemaphoreOptions {
585
- /**
586
- * The maximum number of concurrent locks.
587
- */
588
- concurrency: number;
589
- /**
590
- * The maximum time to wait for a lock to become available.
591
- */
592
- timeout?: number;
593
- }
594
- declare class Semaphore {
595
- private _running;
596
- private concurrency;
597
- private timeout?;
598
- private queue;
599
- constructor({ concurrency, timeout }: SemaphoreOptions);
600
- get remaining(): number;
601
- get running(): number;
602
- acquire(): Promise<() => void>;
603
- run<T>(fn: () => T | Promise<T>): Promise<T>;
604
- }
605
622
  declare const __private__dont__use: unique symbol;
606
- declare abstract class BasePHP implements IsomorphicLocalPHP {
623
+ declare abstract class BasePHP implements IsomorphicLocalPHP, Disposable {
607
624
  #private;
608
625
  protected [__private__dont__use]: any;
609
- requestHandler?: PHPRequestHandler;
626
+ requestHandler?: PHPRequestHandler<any>;
610
627
  /**
611
628
  * An exclusive lock that prevent multiple requests from running at
612
629
  * the same time.
@@ -617,9 +634,9 @@ declare abstract class BasePHP implements IsomorphicLocalPHP {
617
634
  *
618
635
  * @internal
619
636
  * @param PHPRuntime - Optional. PHP Runtime ID as initialized by loadPHPRuntime.
620
- * @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
637
+ * @param requestHandlerOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
621
638
  */
622
- constructor(PHPRuntimeId?: PHPRuntimeId, serverOptions?: PHPRequestHandlerConfiguration);
639
+ constructor(PHPRuntimeId?: PHPRuntimeId);
623
640
  addEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
624
641
  removeEventListener(eventType: PHPEvent["type"], listener: PHPEventListener): void;
625
642
  dispatchEvent<Event extends PHPEvent>(event: Event): void;
@@ -644,7 +661,10 @@ declare abstract class BasePHP implements IsomorphicLocalPHP {
644
661
  setPhpIniEntry(key: string, value: string): void;
645
662
  /** @inheritDoc */
646
663
  chdir(path: string): void;
647
- /** @inheritDoc */
664
+ /**
665
+ * Do not use. Use new PHPRequestHandler() instead.
666
+ * @deprecated
667
+ */
648
668
  request(request: PHPRequest): Promise<PHPResponse>;
649
669
  /** @inheritDoc */
650
670
  run(request: PHPRunOptions): Promise<PHPResponse>;
@@ -683,10 +703,100 @@ declare abstract class BasePHP implements IsomorphicLocalPHP {
683
703
  */
684
704
  hotSwapPHPRuntime(runtime: number, cwd?: string): void;
685
705
  exit(code?: number): void;
706
+ [Symbol.dispose](): void;
686
707
  }
708
+ export type PHPFactoryOptions = {
709
+ isPrimary: boolean;
710
+ };
711
+ export type PHPFactory<PHP extends BasePHP> = (options: PHPFactoryOptions) => Promise<PHP>;
712
+ export interface ProcessManagerOptions<PHP extends BasePHP> {
713
+ /**
714
+ * The maximum number of PHP instances that can exist at
715
+ * the same time.
716
+ */
717
+ maxPhpInstances?: number;
718
+ /**
719
+ * The number of milliseconds to wait for a PHP instance when
720
+ * we have reached the maximum number of PHP instances and
721
+ * cannot spawn a new one. If the timeout is reached, we assume
722
+ * all the PHP instances are deadlocked and a throw MaxPhpInstancesError.
723
+ *
724
+ * Default: 5000
725
+ */
726
+ timeout?: number;
727
+ /**
728
+ * The primary PHP instance that's never killed. This instance
729
+ * contains the reference filesystem used by all other PHP instances.
730
+ */
731
+ primaryPhp?: PHP;
732
+ /**
733
+ * A factory function used for spawning new PHP instances.
734
+ */
735
+ phpFactory?: PHPFactory<PHP>;
736
+ }
737
+ export interface SpawnedPHP<PHP extends BasePHP> {
738
+ php: PHP;
739
+ reap: () => void;
740
+ }
741
+ declare class PHPProcessManager<PHP extends BasePHP> implements AsyncDisposable {
742
+ private primaryPhp?;
743
+ private primaryIdle;
744
+ private nextInstance;
745
+ /**
746
+ * All spawned PHP instances, including the primary PHP instance.
747
+ * Used for bookkeeping and reaping all instances on dispose.
748
+ */
749
+ private allInstances;
750
+ private phpFactory?;
751
+ private maxPhpInstances;
752
+ private semaphore;
753
+ constructor(options?: ProcessManagerOptions<PHP>);
754
+ /**
755
+ * Get the primary PHP instance.
756
+ *
757
+ * If the primary PHP instance is not set, it will be spawned
758
+ * using the provided phpFactory.
759
+ *
760
+ * @throws {Error} when called twice before the first call is resolved.
761
+ */
762
+ getPrimaryPhp(): Promise<PHP>;
763
+ /**
764
+ * Get a PHP instance.
765
+ *
766
+ * It could be either the primary PHP instance, an idle disposable PHP instance,
767
+ * or a newly spawned PHP instance – depending on the resource availability.
768
+ *
769
+ * @throws {MaxPhpInstancesError} when the maximum number of PHP instances is reached
770
+ * and the waiting timeout is exceeded.
771
+ */
772
+ acquirePHPInstance(): Promise<SpawnedPHP<PHP>>;
773
+ /**
774
+ * Initiated spawning of a new PHP instance.
775
+ * This function is synchronous on purpose – it needs to synchronously
776
+ * add the spawn promise to the allInstances array without waiting
777
+ * for PHP to spawn.
778
+ */
779
+ private spawn;
780
+ /**
781
+ * Actually acquires the lock and spawns a new PHP instance.
782
+ */
783
+ private doSpawn;
784
+ [Symbol.asyncDispose](): Promise<void>;
785
+ }
786
+ declare const SupportedPHPVersions: readonly [
787
+ "8.3",
788
+ "8.2",
789
+ "8.1",
790
+ "8.0",
791
+ "7.4",
792
+ "7.3",
793
+ "7.2",
794
+ "7.1",
795
+ "7.0"
796
+ ];
797
+ export type SupportedPHPVersion = (typeof SupportedPHPVersions)[number];
687
798
  export interface PHPWebLoaderOptions {
688
799
  emscriptenOptions?: EmscriptenOptions;
689
- requestHandler?: PHPRequestHandlerConfiguration;
690
800
  onPhpLoaderModuleLoaded?: (module: PHPLoaderModule) => void;
691
801
  /** @deprecated To be replaced with `extensions` in the future */
692
802
  loadAllExtensions?: boolean;
@@ -715,26 +825,35 @@ declare class EmscriptenDownloadMonitor extends EventTarget {
715
825
  /**
716
826
  * A PHP client that can be used to run PHP code in the browser.
717
827
  */
718
- export declare class WebPHPEndpoint implements IsomorphicLocalPHP {
828
+ export declare class WebPHPEndpoint implements Omit<IsomorphicLocalPHP, "setSapiName" | "setPhpIniEntry" | "setPhpIniPath"> {
719
829
  /** @inheritDoc @php-wasm/universal!RequestHandler.absoluteUrl */
720
830
  absoluteUrl: string;
721
831
  /** @inheritDoc @php-wasm/universal!RequestHandler.documentRoot */
722
832
  documentRoot: string;
723
833
  /** @inheritDoc */
724
- constructor(php: BasePHP, monitor?: EmscriptenDownloadMonitor);
725
- /** @inheritDoc @php-wasm/universal!RequestHandler.pathToInternalUrl */
834
+ constructor(requestHandler: PHPRequestHandler<WebPHP>, monitor?: EmscriptenDownloadMonitor);
835
+ /**
836
+ * @internal
837
+ * @deprecated
838
+ * Do not use this method directly in the code consuming
839
+ * the web API. It will change or even be removed without
840
+ * a warning.
841
+ */
842
+ protected __internal_getPHP(): WebPHP | undefined;
843
+ setPrimaryPHP(php: WebPHP): Promise<void>;
844
+ /** @inheritDoc @php-wasm/universal!PHPRequestHandler.pathToInternalUrl */
726
845
  pathToInternalUrl(path: string): string;
727
- /** @inheritDoc @php-wasm/universal!RequestHandler.internalUrlToPath */
846
+ /** @inheritDoc @php-wasm/universal!PHPRequestHandler.internalUrlToPath */
728
847
  internalUrlToPath(internalUrl: string): string;
729
848
  /**
730
849
  * The onDownloadProgress event listener.
731
850
  */
732
851
  onDownloadProgress(callback: (progress: CustomEvent<ProgressEvent>) => void): Promise<void>;
733
852
  /** @inheritDoc @php-wasm/universal!IsomorphicLocalPHP.mv */
734
- mv(fromPath: string, toPath: string): void;
853
+ mv(fromPath: string, toPath: string): Promise<void>;
735
854
  /** @inheritDoc @php-wasm/universal!IsomorphicLocalPHP.rmdir */
736
- rmdir(path: string, options?: RmDirOptions): void;
737
- /** @inheritDoc @php-wasm/universal!RequestHandler.request */
855
+ rmdir(path: string, options?: RmDirOptions): Promise<void>;
856
+ /** @inheritDoc @php-wasm/universal!PHPRequestHandler.request */
738
857
  request(request: PHPRequest): Promise<PHPResponse>;
739
858
  /** @inheritDoc @php-wasm/web!WebPHP.run */
740
859
  run(request: PHPRunOptions): Promise<PHPResponse>;