@php-wasm/universal 0.1.39 → 0.1.41
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.cjs +40 -0
- package/index.js +1070 -0
- package/lib/base-php.d.ts +70 -0
- package/lib/error-event-polyfill.d.ts +30 -0
- package/{src/lib/index.ts → lib/index.d.ts} +4 -36
- package/lib/is-local-php.d.ts +2 -0
- package/lib/is-remote-php.d.ts +2 -0
- package/{src/lib/load-php-runtime.ts → lib/load-php-runtime.d.ts} +23 -100
- package/lib/php-browser.d.ts +52 -0
- package/lib/php-request-handler.d.ts +43 -0
- package/lib/php-response.d.ts +54 -0
- package/lib/rethrow-file-system-error.d.ts +13 -0
- package/lib/supported-php-versions.d.ts +4 -0
- package/lib/universal-php.d.ts +309 -0
- package/{src/lib/urls.ts → lib/urls.d.ts} +4 -19
- package/lib/wasm-error-reporting.d.ts +26 -0
- package/package.json +4 -3
- package/.eslintrc.json +0 -18
- package/LICENSE +0 -339
- package/README.md +0 -0
- package/project.json +0 -50
- package/src/lib/base-php.ts +0 -555
- package/src/lib/error-event-polyfill.ts +0 -50
- package/src/lib/is-local-php.ts +0 -8
- package/src/lib/is-remote-php.ts +0 -8
- package/src/lib/php-browser.ts +0 -137
- package/src/lib/php-request-handler.ts +0 -381
- package/src/lib/php-response.ts +0 -104
- package/src/lib/rethrow-file-system-error.ts +0 -125
- package/src/lib/supported-php-versions.ts +0 -14
- package/src/lib/universal-php.ts +0 -354
- package/src/lib/wasm-error-reporting.ts +0 -172
- package/tsconfig.json +0 -22
- package/tsconfig.lib.json +0 -14
- package/tsconfig.spec.json +0 -20
- package/vite.config.ts +0 -47
- /package/{src/index.ts → index.d.ts} +0 -0
package/src/lib/base-php.ts
DELETED
|
@@ -1,555 +0,0 @@
|
|
|
1
|
-
import { PHPBrowser } from './php-browser';
|
|
2
|
-
import {
|
|
3
|
-
PHPRequestHandler,
|
|
4
|
-
PHPRequestHandlerConfiguration,
|
|
5
|
-
} from './php-request-handler';
|
|
6
|
-
import { PHPResponse } from './php-response';
|
|
7
|
-
import { rethrowFileSystemError } from './rethrow-file-system-error';
|
|
8
|
-
import { getLoadedRuntime } from './load-php-runtime';
|
|
9
|
-
import type { PHPRuntimeId } from './load-php-runtime';
|
|
10
|
-
import {
|
|
11
|
-
FileInfo,
|
|
12
|
-
IsomorphicLocalPHP,
|
|
13
|
-
PHPRequest,
|
|
14
|
-
PHPRequestHeaders,
|
|
15
|
-
PHPRunOptions,
|
|
16
|
-
RmDirOptions,
|
|
17
|
-
} from './universal-php';
|
|
18
|
-
import {
|
|
19
|
-
getFunctionsMaybeMissingFromAsyncify,
|
|
20
|
-
improveWASMErrorReporting,
|
|
21
|
-
UnhandledRejectionsTarget,
|
|
22
|
-
} from './wasm-error-reporting';
|
|
23
|
-
|
|
24
|
-
const STRING = 'string';
|
|
25
|
-
const NUMBER = 'number';
|
|
26
|
-
|
|
27
|
-
export const __private__dont__use = Symbol('__private__dont__use');
|
|
28
|
-
/**
|
|
29
|
-
* An environment-agnostic wrapper around the Emscripten PHP runtime
|
|
30
|
-
* that universals the super low-level API and provides a more convenient
|
|
31
|
-
* higher-level API.
|
|
32
|
-
*
|
|
33
|
-
* It exposes a minimal set of methods to run PHP scripts and to
|
|
34
|
-
* interact with the PHP filesystem.
|
|
35
|
-
*/
|
|
36
|
-
export abstract class BasePHP implements IsomorphicLocalPHP {
|
|
37
|
-
protected [__private__dont__use]: any;
|
|
38
|
-
#phpIniOverrides: [string, string][] = [];
|
|
39
|
-
#webSapiInitialized = false;
|
|
40
|
-
#wasmErrorsTarget: UnhandledRejectionsTarget | null = null;
|
|
41
|
-
requestHandler?: PHPBrowser;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Initializes a PHP runtime.
|
|
45
|
-
*
|
|
46
|
-
* @internal
|
|
47
|
-
* @param PHPRuntime - Optional. PHP Runtime ID as initialized by loadPHPRuntime.
|
|
48
|
-
* @param serverOptions - Optional. Options for the PHPRequestHandler. If undefined, no request handler will be initialized.
|
|
49
|
-
*/
|
|
50
|
-
constructor(
|
|
51
|
-
PHPRuntimeId?: PHPRuntimeId,
|
|
52
|
-
serverOptions?: PHPRequestHandlerConfiguration
|
|
53
|
-
) {
|
|
54
|
-
if (PHPRuntimeId !== undefined) {
|
|
55
|
-
this.initializeRuntime(PHPRuntimeId);
|
|
56
|
-
}
|
|
57
|
-
if (serverOptions) {
|
|
58
|
-
this.requestHandler = new PHPBrowser(
|
|
59
|
-
new PHPRequestHandler(this, serverOptions)
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** @inheritDoc */
|
|
65
|
-
get absoluteUrl() {
|
|
66
|
-
return this.requestHandler!.requestHandler.absoluteUrl;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** @inheritDoc */
|
|
70
|
-
get documentRoot() {
|
|
71
|
-
return this.requestHandler!.requestHandler.documentRoot;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/** @inheritDoc */
|
|
75
|
-
pathToInternalUrl(path: string): string {
|
|
76
|
-
return this.requestHandler!.requestHandler.pathToInternalUrl(path);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/** @inheritDoc */
|
|
80
|
-
internalUrlToPath(internalUrl: string): string {
|
|
81
|
-
return this.requestHandler!.requestHandler.internalUrlToPath(
|
|
82
|
-
internalUrl
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
initializeRuntime(runtimeId: PHPRuntimeId) {
|
|
87
|
-
if (this[__private__dont__use]) {
|
|
88
|
-
throw new Error('PHP runtime already initialized.');
|
|
89
|
-
}
|
|
90
|
-
const runtime = getLoadedRuntime(runtimeId);
|
|
91
|
-
if (!runtime) {
|
|
92
|
-
throw new Error('Invalid PHP runtime id.');
|
|
93
|
-
}
|
|
94
|
-
this[__private__dont__use] = runtime;
|
|
95
|
-
|
|
96
|
-
this.#wasmErrorsTarget = improveWASMErrorReporting(runtime);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** @inheritDoc */
|
|
100
|
-
setPhpIniPath(path: string) {
|
|
101
|
-
if (this.#webSapiInitialized) {
|
|
102
|
-
throw new Error('Cannot set PHP ini path after calling run().');
|
|
103
|
-
}
|
|
104
|
-
this[__private__dont__use].ccall(
|
|
105
|
-
'wasm_set_phpini_path',
|
|
106
|
-
null,
|
|
107
|
-
['string'],
|
|
108
|
-
[path]
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** @inheritDoc */
|
|
113
|
-
setPhpIniEntry(key: string, value: string) {
|
|
114
|
-
if (this.#webSapiInitialized) {
|
|
115
|
-
throw new Error('Cannot set PHP ini entries after calling run().');
|
|
116
|
-
}
|
|
117
|
-
this.#phpIniOverrides.push([key, value]);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** @inheritDoc */
|
|
121
|
-
chdir(path: string) {
|
|
122
|
-
this[__private__dont__use].FS.chdir(path);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/** @inheritDoc */
|
|
126
|
-
async request(
|
|
127
|
-
request: PHPRequest,
|
|
128
|
-
maxRedirects?: number
|
|
129
|
-
): Promise<PHPResponse> {
|
|
130
|
-
if (!this.requestHandler) {
|
|
131
|
-
throw new Error('No request handler available.');
|
|
132
|
-
}
|
|
133
|
-
return this.requestHandler.request(request, maxRedirects);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
/** @inheritDoc */
|
|
137
|
-
async run(request: PHPRunOptions): Promise<PHPResponse> {
|
|
138
|
-
if (!this.#webSapiInitialized) {
|
|
139
|
-
this.#initWebRuntime();
|
|
140
|
-
this.#webSapiInitialized = true;
|
|
141
|
-
}
|
|
142
|
-
this.#setScriptPath(request.scriptPath || '');
|
|
143
|
-
this.#setRelativeRequestUri(request.relativeUri || '');
|
|
144
|
-
this.#setRequestMethod(request.method || 'GET');
|
|
145
|
-
const { host, ...headers } = {
|
|
146
|
-
host: 'example.com:443',
|
|
147
|
-
...normalizeHeaders(request.headers || {}),
|
|
148
|
-
};
|
|
149
|
-
this.#setRequestHostAndProtocol(host, request.protocol || 'http');
|
|
150
|
-
this.#setRequestHeaders(headers);
|
|
151
|
-
if (request.body) {
|
|
152
|
-
this.#setRequestBody(request.body);
|
|
153
|
-
}
|
|
154
|
-
if (request.fileInfos) {
|
|
155
|
-
for (const file of request.fileInfos) {
|
|
156
|
-
this.#addUploadedFile(file);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
if (request.code) {
|
|
160
|
-
this.#setPHPCode(' ?>' + request.code);
|
|
161
|
-
}
|
|
162
|
-
return await this.#handleRequest();
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
#initWebRuntime() {
|
|
166
|
-
if (this.#phpIniOverrides.length > 0) {
|
|
167
|
-
const overridesAsIni =
|
|
168
|
-
this.#phpIniOverrides
|
|
169
|
-
.map(([key, value]) => `${key}=${value}`)
|
|
170
|
-
.join('\n') + '\n\n';
|
|
171
|
-
this[__private__dont__use].ccall(
|
|
172
|
-
'wasm_set_phpini_entries',
|
|
173
|
-
null,
|
|
174
|
-
[STRING],
|
|
175
|
-
[overridesAsIni]
|
|
176
|
-
);
|
|
177
|
-
}
|
|
178
|
-
this[__private__dont__use].ccall('php_wasm_init', null, [], []);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
#getResponseHeaders(): {
|
|
182
|
-
headers: PHPResponse['headers'];
|
|
183
|
-
httpStatusCode: number;
|
|
184
|
-
} {
|
|
185
|
-
const headersFilePath = '/tmp/headers.json';
|
|
186
|
-
if (!this.fileExists(headersFilePath)) {
|
|
187
|
-
throw new Error(
|
|
188
|
-
'SAPI Error: Could not find response headers file.'
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const headersData = JSON.parse(this.readFileAsText(headersFilePath));
|
|
193
|
-
const headers: PHPResponse['headers'] = {};
|
|
194
|
-
for (const line of headersData.headers) {
|
|
195
|
-
if (!line.includes(': ')) {
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
const colonIndex = line.indexOf(': ');
|
|
199
|
-
const headerName = line.substring(0, colonIndex).toLowerCase();
|
|
200
|
-
const headerValue = line.substring(colonIndex + 2);
|
|
201
|
-
if (!(headerName in headers)) {
|
|
202
|
-
headers[headerName] = [] as string[];
|
|
203
|
-
}
|
|
204
|
-
headers[headerName].push(headerValue);
|
|
205
|
-
}
|
|
206
|
-
return {
|
|
207
|
-
headers,
|
|
208
|
-
httpStatusCode: headersData.status,
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
#setRelativeRequestUri(uri: string) {
|
|
213
|
-
this[__private__dont__use].ccall(
|
|
214
|
-
'wasm_set_request_uri',
|
|
215
|
-
null,
|
|
216
|
-
[STRING],
|
|
217
|
-
[uri]
|
|
218
|
-
);
|
|
219
|
-
if (uri.includes('?')) {
|
|
220
|
-
const queryString = uri.substring(uri.indexOf('?') + 1);
|
|
221
|
-
this[__private__dont__use].ccall(
|
|
222
|
-
'wasm_set_query_string',
|
|
223
|
-
null,
|
|
224
|
-
[STRING],
|
|
225
|
-
[queryString]
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
#setRequestHostAndProtocol(host: string, protocol: string) {
|
|
231
|
-
this[__private__dont__use].ccall(
|
|
232
|
-
'wasm_set_request_host',
|
|
233
|
-
null,
|
|
234
|
-
[STRING],
|
|
235
|
-
[host]
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
let port;
|
|
239
|
-
try {
|
|
240
|
-
port = parseInt(new URL(host).port, 10);
|
|
241
|
-
} catch (e) {
|
|
242
|
-
// ignore
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (!port || isNaN(port) || port === 80) {
|
|
246
|
-
port = protocol === 'https' ? 443 : 80;
|
|
247
|
-
}
|
|
248
|
-
this[__private__dont__use].ccall(
|
|
249
|
-
'wasm_set_request_port',
|
|
250
|
-
null,
|
|
251
|
-
[NUMBER],
|
|
252
|
-
[port]
|
|
253
|
-
);
|
|
254
|
-
|
|
255
|
-
if (protocol === 'https' || (!protocol && port === 443)) {
|
|
256
|
-
this.addServerGlobalEntry('HTTPS', 'on');
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
#setRequestMethod(method: string) {
|
|
261
|
-
this[__private__dont__use].ccall(
|
|
262
|
-
'wasm_set_request_method',
|
|
263
|
-
null,
|
|
264
|
-
[STRING],
|
|
265
|
-
[method]
|
|
266
|
-
);
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
#setRequestHeaders(headers: PHPRequestHeaders) {
|
|
270
|
-
if (headers['cookie']) {
|
|
271
|
-
this[__private__dont__use].ccall(
|
|
272
|
-
'wasm_set_cookies',
|
|
273
|
-
null,
|
|
274
|
-
[STRING],
|
|
275
|
-
[headers['cookie']]
|
|
276
|
-
);
|
|
277
|
-
}
|
|
278
|
-
if (headers['content-type']) {
|
|
279
|
-
this[__private__dont__use].ccall(
|
|
280
|
-
'wasm_set_content_type',
|
|
281
|
-
null,
|
|
282
|
-
[STRING],
|
|
283
|
-
[headers['content-type']]
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
if (headers['content-length']) {
|
|
287
|
-
this[__private__dont__use].ccall(
|
|
288
|
-
'wasm_set_content_length',
|
|
289
|
-
null,
|
|
290
|
-
[NUMBER],
|
|
291
|
-
[parseInt(headers['content-length'], 10)]
|
|
292
|
-
);
|
|
293
|
-
}
|
|
294
|
-
for (const name in headers) {
|
|
295
|
-
this.addServerGlobalEntry(
|
|
296
|
-
`HTTP_${name.toUpperCase().replace(/-/g, '_')}`,
|
|
297
|
-
headers[name]
|
|
298
|
-
);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
#setRequestBody(body: string) {
|
|
303
|
-
this[__private__dont__use].ccall(
|
|
304
|
-
'wasm_set_request_body',
|
|
305
|
-
null,
|
|
306
|
-
[STRING],
|
|
307
|
-
[body]
|
|
308
|
-
);
|
|
309
|
-
this[__private__dont__use].ccall(
|
|
310
|
-
'wasm_set_content_length',
|
|
311
|
-
null,
|
|
312
|
-
[NUMBER],
|
|
313
|
-
[new TextEncoder().encode(body).length]
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
#setScriptPath(path: string) {
|
|
318
|
-
this[__private__dont__use].ccall(
|
|
319
|
-
'wasm_set_path_translated',
|
|
320
|
-
null,
|
|
321
|
-
[STRING],
|
|
322
|
-
[path]
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
addServerGlobalEntry(key: string, value: string) {
|
|
327
|
-
this[__private__dont__use].ccall(
|
|
328
|
-
'wasm_add_SERVER_entry',
|
|
329
|
-
null,
|
|
330
|
-
[STRING, STRING],
|
|
331
|
-
[key, value]
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
/**
|
|
336
|
-
* Adds file information to $_FILES superglobal in PHP.
|
|
337
|
-
*
|
|
338
|
-
* In particular:
|
|
339
|
-
* * Creates the file data in the filesystem
|
|
340
|
-
* * Registers the file details in PHP
|
|
341
|
-
*
|
|
342
|
-
* @param fileInfo - File details
|
|
343
|
-
*/
|
|
344
|
-
#addUploadedFile(fileInfo: FileInfo) {
|
|
345
|
-
const { key, name, type, data } = fileInfo;
|
|
346
|
-
|
|
347
|
-
const tmpPath = `/tmp/${Math.random().toFixed(20)}`;
|
|
348
|
-
this.writeFile(tmpPath, data);
|
|
349
|
-
|
|
350
|
-
const error = 0;
|
|
351
|
-
this[__private__dont__use].ccall(
|
|
352
|
-
'wasm_add_uploaded_file',
|
|
353
|
-
null,
|
|
354
|
-
[STRING, STRING, STRING, STRING, NUMBER, NUMBER],
|
|
355
|
-
[key, name, type, tmpPath, error, data.byteLength]
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
#setPHPCode(code: string) {
|
|
360
|
-
this[__private__dont__use].ccall(
|
|
361
|
-
'wasm_set_php_code',
|
|
362
|
-
null,
|
|
363
|
-
[STRING],
|
|
364
|
-
[code]
|
|
365
|
-
);
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
async #handleRequest(): Promise<PHPResponse> {
|
|
369
|
-
let exitCode: number;
|
|
370
|
-
|
|
371
|
-
/*
|
|
372
|
-
* Emscripten throws WASM failures outside of the promise chain so we need
|
|
373
|
-
* to listen for them here and rethrow in the correct context. Otherwise we
|
|
374
|
-
* get crashes and unhandled promise rejections without any useful error messages
|
|
375
|
-
* or stack traces.
|
|
376
|
-
*/
|
|
377
|
-
let errorListener: any;
|
|
378
|
-
try {
|
|
379
|
-
// eslint-disable-next-line no-async-promise-executor
|
|
380
|
-
exitCode = await new Promise<number>(async (resolve, reject) => {
|
|
381
|
-
errorListener = (e: ErrorEvent) => {
|
|
382
|
-
const rethrown = new Error('Rethrown');
|
|
383
|
-
rethrown.cause = e.error;
|
|
384
|
-
(rethrown as any).betterMessage = e.message;
|
|
385
|
-
reject(rethrown);
|
|
386
|
-
};
|
|
387
|
-
this.#wasmErrorsTarget?.addEventListener(
|
|
388
|
-
'error',
|
|
389
|
-
errorListener
|
|
390
|
-
);
|
|
391
|
-
|
|
392
|
-
try {
|
|
393
|
-
resolve(
|
|
394
|
-
/**
|
|
395
|
-
* This is awkward, but Asyncify makes wasm_sapi_handle_request return
|
|
396
|
-
* Promise<Promise<number>>.
|
|
397
|
-
*
|
|
398
|
-
* @TODO: Determine whether this is a bug in emscripten or in our code.
|
|
399
|
-
*/
|
|
400
|
-
await await this[__private__dont__use].ccall(
|
|
401
|
-
'wasm_sapi_handle_request',
|
|
402
|
-
NUMBER,
|
|
403
|
-
[],
|
|
404
|
-
[]
|
|
405
|
-
)
|
|
406
|
-
);
|
|
407
|
-
} catch (e) {
|
|
408
|
-
reject(e);
|
|
409
|
-
}
|
|
410
|
-
});
|
|
411
|
-
} catch (e) {
|
|
412
|
-
/**
|
|
413
|
-
* An exception here means an irrecoverable crash. Let's make
|
|
414
|
-
* it very clear to the consumers of this API – every method
|
|
415
|
-
* call on this PHP instance will throw an error from now on.
|
|
416
|
-
*/
|
|
417
|
-
for (const name in this) {
|
|
418
|
-
if (typeof this[name] === 'function') {
|
|
419
|
-
(this as any)[name] = () => {
|
|
420
|
-
throw new Error(
|
|
421
|
-
`PHP runtime has crashed – see the earlier error for details.`
|
|
422
|
-
);
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
(this as any).functionsMaybeMissingFromAsyncify =
|
|
427
|
-
getFunctionsMaybeMissingFromAsyncify();
|
|
428
|
-
|
|
429
|
-
const err = e as Error;
|
|
430
|
-
const message = (
|
|
431
|
-
'betterMessage' in err ? err.betterMessage : err.message
|
|
432
|
-
) as string;
|
|
433
|
-
const rethrown = new Error(message);
|
|
434
|
-
rethrown.cause = err;
|
|
435
|
-
throw rethrown;
|
|
436
|
-
} finally {
|
|
437
|
-
this.#wasmErrorsTarget?.removeEventListener('error', errorListener);
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
const { headers, httpStatusCode } = this.#getResponseHeaders();
|
|
441
|
-
return new PHPResponse(
|
|
442
|
-
httpStatusCode,
|
|
443
|
-
headers,
|
|
444
|
-
this.readFileAsBuffer('/tmp/stdout'),
|
|
445
|
-
this.readFileAsText('/tmp/stderr'),
|
|
446
|
-
exitCode
|
|
447
|
-
);
|
|
448
|
-
}
|
|
449
|
-
|
|
450
|
-
/** @inheritDoc */
|
|
451
|
-
@rethrowFileSystemError('Could not create directory "{path}"')
|
|
452
|
-
mkdir(path: string) {
|
|
453
|
-
this[__private__dont__use].FS.mkdirTree(path);
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
/** @inheritDoc */
|
|
457
|
-
@rethrowFileSystemError('Could not create directory "{path}"')
|
|
458
|
-
mkdirTree(path: string) {
|
|
459
|
-
this.mkdir(path);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/** @inheritDoc */
|
|
463
|
-
@rethrowFileSystemError('Could not read "{path}"')
|
|
464
|
-
readFileAsText(path: string) {
|
|
465
|
-
return new TextDecoder().decode(this.readFileAsBuffer(path));
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
/** @inheritDoc */
|
|
469
|
-
@rethrowFileSystemError('Could not read "{path}"')
|
|
470
|
-
readFileAsBuffer(path: string): Uint8Array {
|
|
471
|
-
return this[__private__dont__use].FS.readFile(path);
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
/** @inheritDoc */
|
|
475
|
-
@rethrowFileSystemError('Could not write to "{path}"')
|
|
476
|
-
writeFile(path: string, data: string | Uint8Array) {
|
|
477
|
-
this[__private__dont__use].FS.writeFile(path, data);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
/** @inheritDoc */
|
|
481
|
-
@rethrowFileSystemError('Could not unlink "{path}"')
|
|
482
|
-
unlink(path: string) {
|
|
483
|
-
this[__private__dont__use].FS.unlink(path);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/** @inheritDoc */
|
|
487
|
-
@rethrowFileSystemError('Could not move "{path}"')
|
|
488
|
-
mv(fromPath: string, toPath: string) {
|
|
489
|
-
this[__private__dont__use].FS.mv(fromPath, toPath);
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
/** @inheritDoc */
|
|
493
|
-
@rethrowFileSystemError('Could not remove directory "{path}"')
|
|
494
|
-
rmdir(path: string, options: RmDirOptions = { recursive: true }) {
|
|
495
|
-
if (options?.recursive) {
|
|
496
|
-
this.listFiles(path).forEach((file) => {
|
|
497
|
-
const filePath = `${path}/${file}`;
|
|
498
|
-
if (this.isDir(filePath)) {
|
|
499
|
-
this.rmdir(filePath, options);
|
|
500
|
-
} else {
|
|
501
|
-
this.unlink(filePath);
|
|
502
|
-
}
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
this[__private__dont__use].FS.rmdir(path);
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
/** @inheritDoc */
|
|
509
|
-
@rethrowFileSystemError('Could not list files in "{path}"')
|
|
510
|
-
listFiles(path: string): string[] {
|
|
511
|
-
if (!this.fileExists(path)) {
|
|
512
|
-
return [];
|
|
513
|
-
}
|
|
514
|
-
try {
|
|
515
|
-
return this[__private__dont__use].FS.readdir(path).filter(
|
|
516
|
-
(name: string) => name !== '.' && name !== '..'
|
|
517
|
-
);
|
|
518
|
-
} catch (e) {
|
|
519
|
-
console.error(e, { path });
|
|
520
|
-
return [];
|
|
521
|
-
}
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
/** @inheritDoc */
|
|
525
|
-
@rethrowFileSystemError('Could not stat "{path}"')
|
|
526
|
-
isDir(path: string): boolean {
|
|
527
|
-
if (!this.fileExists(path)) {
|
|
528
|
-
return false;
|
|
529
|
-
}
|
|
530
|
-
return this[__private__dont__use].FS.isDir(
|
|
531
|
-
this[__private__dont__use].FS.lookupPath(path).node.mode
|
|
532
|
-
);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
/** @inheritDoc */
|
|
536
|
-
@rethrowFileSystemError('Could not stat "{path}"')
|
|
537
|
-
fileExists(path: string): boolean {
|
|
538
|
-
try {
|
|
539
|
-
this[__private__dont__use].FS.lookupPath(path);
|
|
540
|
-
return true;
|
|
541
|
-
} catch (e) {
|
|
542
|
-
return false;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
export function normalizeHeaders(
|
|
548
|
-
headers: PHPRunOptions['headers']
|
|
549
|
-
): PHPRunOptions['headers'] {
|
|
550
|
-
const normalized: PHPRunOptions['headers'] = {};
|
|
551
|
-
for (const key in headers) {
|
|
552
|
-
normalized[key.toLowerCase()] = headers[key];
|
|
553
|
-
}
|
|
554
|
-
return normalized;
|
|
555
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Node.js Polyfill for ErrorEvent.
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
const kError = Symbol('error');
|
|
6
|
-
const kMessage = Symbol('message');
|
|
7
|
-
|
|
8
|
-
interface ErrorEventOptions {
|
|
9
|
-
/* The error that generated this event */
|
|
10
|
-
error?: Error;
|
|
11
|
-
/* The error message */
|
|
12
|
-
message?: string;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Class representing an error event.
|
|
16
|
-
*
|
|
17
|
-
* @extends Event
|
|
18
|
-
*/
|
|
19
|
-
class ErrorEvent2 extends Event {
|
|
20
|
-
[kError]: any;
|
|
21
|
-
[kMessage]: any;
|
|
22
|
-
/**
|
|
23
|
-
* Create a new `ErrorEvent`.
|
|
24
|
-
*
|
|
25
|
-
* @param type The name of the event
|
|
26
|
-
* @param options A dictionary object that allows for setting
|
|
27
|
-
* attributes via object members of the same name.
|
|
28
|
-
*/
|
|
29
|
-
constructor(type: 'error', options: ErrorEventOptions = {}) {
|
|
30
|
-
super(type);
|
|
31
|
-
|
|
32
|
-
this[kError] = options.error === undefined ? null : options.error;
|
|
33
|
-
this[kMessage] = options.message === undefined ? '' : options.message;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
get error() {
|
|
37
|
-
return this[kError];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get message() {
|
|
41
|
-
return this[kMessage];
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
Object.defineProperty(ErrorEvent2.prototype, 'error', { enumerable: true });
|
|
45
|
-
Object.defineProperty(ErrorEvent2.prototype, 'message', { enumerable: true });
|
|
46
|
-
|
|
47
|
-
export const ErrorEvent =
|
|
48
|
-
typeof globalThis.ErrorEvent === 'function'
|
|
49
|
-
? globalThis.ErrorEvent
|
|
50
|
-
: ErrorEvent2;
|
package/src/lib/is-local-php.ts
DELETED
package/src/lib/is-remote-php.ts
DELETED