@php-wasm/universal 3.0.46 → 3.0.52

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/lib/index.d.ts CHANGED
@@ -28,7 +28,7 @@ export type { MountHandler, UnmountFunction } from './php';
28
28
  export { loadPHPRuntime, popLoadedRuntime } from './load-php-runtime';
29
29
  export type { Emscripten } from './emscripten-types';
30
30
  export type { DataModule, EmscriptenOptions, PHPLoaderModule, PHPRuntime, PHPRuntimeId, RuntimeType, } from './load-php-runtime';
31
- export type { PHPRequestHandlerConfiguration, RewriteRule, } from './php-request-handler';
31
+ export type { PHPRequestHandlerConfiguration, RewriteRule, PathAlias, } from './php-request-handler';
32
32
  export { PHPRequestHandler, applyRewriteRules, inferMimeType, } from './php-request-handler';
33
33
  export type { FileNotFoundGetActionCallback, FileNotFoundToInternalRedirect, FileNotFoundToResponse, FileNotFoundAction, CookieStore, } from './php-request-handler';
34
34
  export { rotatePHPRuntime } from './rotate-php-runtime';
@@ -28,11 +28,7 @@ export interface PHPInstanceManager extends AsyncDisposable {
28
28
  /**
29
29
  * Acquire a PHP instance for processing a request.
30
30
  *
31
- * @param options.considerPrimary - Whether the primary instance can be used.
32
- * Set to false for operations that would corrupt the primary (e.g., CLI commands).
33
31
  * @returns An acquired PHP instance with a reap function.
34
32
  */
35
- acquirePHPInstance(options?: {
36
- considerPrimary?: boolean;
37
- }): Promise<AcquiredPHP>;
33
+ acquirePHPInstance(): Promise<AcquiredPHP>;
38
34
  }
@@ -6,24 +6,18 @@ export type PHPFactoryOptions = {
6
6
  export type PHPFactory = (options: PHPFactoryOptions) => Promise<PHP>;
7
7
  export interface ProcessManagerOptions {
8
8
  /**
9
- * The maximum number of PHP instances that can exist at
9
+ * The maximum number of PHP instances that can be in use at
10
10
  * the same time.
11
11
  */
12
12
  maxPhpInstances?: number;
13
13
  /**
14
14
  * The number of milliseconds to wait for a PHP instance when
15
- * we have reached the maximum number of PHP instances and
16
- * cannot spawn a new one. If the timeout is reached, we assume
17
- * all the PHP instances are deadlocked and a throw MaxPhpInstancesError.
15
+ * all instances are busy. If the timeout is reached, we assume
16
+ * all the PHP instances are deadlocked and throw MaxPhpInstancesError.
18
17
  *
19
- * Default: 5000
18
+ * Default: 30000
20
19
  */
21
20
  timeout?: number;
22
- /**
23
- * The primary PHP instance that's never killed. This instance
24
- * contains the reference filesystem used by all other PHP instances.
25
- */
26
- primaryPhp?: PHP;
27
21
  /**
28
22
  * A factory function used for spawning new PHP instances.
29
23
  */
@@ -33,86 +27,53 @@ export declare class MaxPhpInstancesError extends Error {
33
27
  constructor(limit: number);
34
28
  }
35
29
  /**
36
- * A PHP Process manager.
37
- *
38
- * Maintains:
39
- * * A single "primary" PHP instance that's never killed – it contains the
40
- * reference filesystem used by all other PHP instances.
41
- * * A pool of disposable PHP instances that are spawned to handle a single
42
- * request and reaped immediately after.
43
- *
44
- * When a new request comes in, PHPProcessManager yields the idle instance to
45
- * handle it, and immediately starts initializing a new idle instance. In other
46
- * words, for n concurrent requests, there are at most n+1 PHP instances
47
- * running at the same time.
30
+ * A PHP Process manager that maintains a pool of reusable PHP instances.
48
31
  *
49
- * A slight nuance is that the first idle instance is not initialized until the
50
- * first concurrent request comes in. This is because many use-cases won't
51
- * involve parallel requests and, for those, we can avoid eagerly spinning up a
52
- * second PHP instance.
32
+ * Instances are spawned on demand up to `maxPhpInstances` and reused across
33
+ * requests. The first instance spawned is the "primary" instance which
34
+ * contains the reference filesystem used by all other instances.
53
35
  *
54
- * This strategy is inspired by Cowboy, an Erlang HTTP server. Handling a
55
- * single extra request can happen immediately, while handling multiple extra
56
- * requests requires extra time to spin up a few PHP instances. This is a more
57
- * resource-friendly tradeoff than keeping 5 idle instances at all times.
36
+ * The semaphore controls how many requests can be processed concurrently.
37
+ * When all instances are busy, new requests wait in a queue until an
38
+ * instance becomes available or the timeout is reached.
58
39
  */
59
40
  export declare class PHPProcessManager implements PHPInstanceManager {
60
- private primaryPhp?;
61
- private primaryPhpPromise?;
62
- private primaryIdle;
63
- private nextInstance;
64
- /**
65
- * All spawned PHP instances, including the primary PHP instance.
66
- * Used for bookkeeping and reaping all instances on dispose.
67
- */
68
- private allInstances;
69
- private phpFactory?;
41
+ /** All PHP instances that have been spawned. */
42
+ private instances;
43
+ /** Instances that are currently idle and available for use. */
44
+ private idleInstances;
45
+ /** Maximum number of concurrent PHP instances allowed. */
70
46
  private maxPhpInstances;
47
+ /** Factory function for creating new PHP instances. */
48
+ private phpFactory?;
49
+ /** Controls concurrent access to PHP instances. */
71
50
  private semaphore;
51
+ /** Prevents spawning duplicate primary instances during concurrent calls. */
52
+ private primaryPhpPromise?;
72
53
  constructor(options?: ProcessManagerOptions);
73
54
  /**
74
- * Get the primary PHP instance.
75
- *
76
- * If the primary PHP instance is not set, it will be spawned
77
- * using the provided phpFactory.
78
- *
79
- * @throws {Error} when called twice before the first call is resolved.
55
+ * Get the primary PHP instance (the first one spawned).
56
+ * If no instance exists yet, one will be spawned and marked as idle.
80
57
  */
81
58
  getPrimaryPhp(): Promise<PHP>;
82
59
  /**
83
- * Get a PHP instance.
84
- *
85
- * It could be either the primary PHP instance, an idle disposable PHP
86
- * instance, or a newly spawned PHP instance – depending on the resource
87
- * availability.
60
+ * Acquire a PHP instance for processing a request.
88
61
  *
89
- * @param considerPrimary - Whether to consider the primary PHP instance.
90
- * It matters because PHP.cli() sets the SAPI to CLI and
91
- * kills the entire process after it finishes running,
92
- * making the primary PHP instance non-reusable for
93
- * subsequent .run() calls. This is fine for one-off
94
- * child PHP instances, but not for the primary PHP
95
- * that's meant to continue working for the entire duration
96
- * of the ProcessManager lifetime. Therefore, we don't
97
- * consider the primary PHP instance by default unless
98
- * the caller explicitly requests it.
62
+ * Returns an idle instance from the pool, or spawns a new one if
63
+ * the pool isn't at capacity. If all instances are busy, waits
64
+ * until one becomes available.
99
65
  *
100
- * @throws {MaxPhpInstancesError} when the maximum number of PHP instances is reached
101
- * and the waiting timeout is exceeded.
66
+ * @throws {MaxPhpInstancesError} when the timeout is reached waiting
67
+ * for an available instance.
102
68
  */
103
- acquirePHPInstance({ considerPrimary, }?: {
104
- considerPrimary?: boolean;
105
- }): Promise<AcquiredPHP>;
69
+ acquirePHPInstance(): Promise<AcquiredPHP>;
106
70
  /**
107
- * Initiated spawning of a new PHP instance.
108
- * This function is synchronous on purpose – it needs to synchronously
109
- * add the spawn promise to the allInstances array without waiting
110
- * for PHP to spawn.
71
+ * Get an idle instance or spawn a new one.
111
72
  */
112
- private spawn;
73
+ private getOrSpawnInstance;
113
74
  /**
114
- * Actually acquires the lock and spawns a new PHP instance.
75
+ * Spawn a new PHP instance.
115
76
  */
116
- private doSpawn;
77
+ private spawnInstance;
117
78
  [Symbol.asyncDispose](): Promise<void>;
118
79
  }
@@ -36,6 +36,26 @@ export interface CookieStore {
36
36
  */
37
37
  getCookieRequestHeader(): string;
38
38
  }
39
+ /**
40
+ * Maps a URL path prefix to an absolute filesystem path.
41
+ * Similar to Nginx's `alias` directive or Apache's `Alias` directive.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * // Requests to /phpmyadmin/* will be served from /tools/phpmyadmin/*
46
+ * { urlPrefix: '/phpmyadmin', fsPath: '/tools/phpmyadmin' }
47
+ * ```
48
+ */
49
+ export type PathAlias = {
50
+ /**
51
+ * The URL path prefix to match (e.g., '/phpmyadmin').
52
+ */
53
+ urlPrefix: string;
54
+ /**
55
+ * The absolute filesystem path to serve files from.
56
+ */
57
+ fsPath: string;
58
+ };
39
59
  interface BaseConfiguration {
40
60
  /**
41
61
  * The directory in the PHP filesystem where the server will look
@@ -50,6 +70,18 @@ interface BaseConfiguration {
50
70
  * Rewrite rules
51
71
  */
52
72
  rewriteRules?: RewriteRule[];
73
+ /**
74
+ * Path aliases that map URL prefixes to filesystem paths outside
75
+ * the document root. Similar to Nginx's `alias` directive.
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * pathAliases: [
80
+ * { urlPrefix: '/phpmyadmin', fsPath: '/tools/phpmyadmin' }
81
+ * ]
82
+ * ```
83
+ */
84
+ pathAliases?: PathAlias[];
53
85
  /**
54
86
  * A callback that decides how to handle a file-not-found condition for a
55
87
  * given request URI.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@php-wasm/universal",
3
- "version": "3.0.46",
3
+ "version": "3.0.52",
4
4
  "description": "PHP.wasm – emscripten bindings for PHP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -37,18 +37,18 @@
37
37
  "module": "./index.js",
38
38
  "types": "index.d.ts",
39
39
  "license": "GPL-2.0-or-later",
40
- "gitHead": "845cbc01dba047db8bf0b4ae2670b924e3517087",
40
+ "gitHead": "fd79b4d41ec8858ecacde7a814818fac95c40246",
41
41
  "engines": {
42
42
  "node": ">=20.18.3",
43
43
  "npm": ">=10.1.0"
44
44
  },
45
45
  "dependencies": {
46
46
  "ini": "4.1.2",
47
- "@php-wasm/node-polyfills": "3.0.46",
48
- "@php-wasm/logger": "3.0.46",
49
- "@php-wasm/util": "3.0.46",
50
- "@php-wasm/stream-compression": "3.0.46",
51
- "@php-wasm/progress": "3.0.46"
47
+ "@php-wasm/node-polyfills": "3.0.52",
48
+ "@php-wasm/logger": "3.0.52",
49
+ "@php-wasm/util": "3.0.52",
50
+ "@php-wasm/stream-compression": "3.0.52",
51
+ "@php-wasm/progress": "3.0.52"
52
52
  },
53
53
  "packageManager": "npm@10.9.2",
54
54
  "overrides": {
@@ -59,7 +59,9 @@
59
59
  "@playwright/test": "1.55.1",
60
60
  "ws": "8.18.3",
61
61
  "tmp": "0.2.5",
62
- "form-data": "^4.0.4"
62
+ "form-data": "^4.0.4",
63
+ "lodash": "^4.17.23",
64
+ "glob": "^9.3.0"
63
65
  },
64
66
  "optionalDependencies": {
65
67
  "fs-ext": "2.1.1"