Skip to content

Commit b6d6ef6

Browse files
Support file URL resources in command line environment (#34)
## Motivation for the change, related issues In #25, we want to ship a wp-cli.phar and wordpress-importer.zip with the Blueprints library in order to eliminate hard-coded references to the Playground web app (That way, we can host a private Playground without reference to the public one). In addition, it's probably better to just version the binary dependencies along with the library. But this made existing code and tests awkward: We want to reference a wp-cli.phar shipped with the Blueprints lib but need to reference it differently depending on whether the Blueprints lib is running on the command line or in a browser. It turns out we can use the same resource type to do both if we base wp-cli.phar URLs on `import.meta.url`. In a browser environment, it is an http(s):// URL, and in Node.js, the it is a file:// URL. In both cases, Vite is able to make sure public asset URLs based on `import.meta.url` are properly set. ## Implementation details This PR updates the FetchResource abstract type to be able to resolve data when the specified URL is a file:// URL and the module's URL is also a file:// URL (indicating a runtime that is loading from local FS). ## Testing Instructions (or ideally a Blueprint) - Added test for file URLs. - CI
1 parent 469a7cc commit b6d6ef6

File tree

2 files changed

+45
-14
lines changed

2 files changed

+45
-14
lines changed

packages/playground/blueprints/src/lib/resources.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { readFileSync } from 'node:fs';
12
import { UrlResource, GitDirectoryResource } from './resources';
23

34
describe('UrlResource', () => {
@@ -20,6 +21,19 @@ describe('UrlResource', () => {
2021
'https://raw.githubusercontent.com/WordPress/wordpress-develop/trunk/src/wp-includes/version.php'
2122
);
2223
});
24+
25+
it('should resolve file URLs in command-line environment', async () => {
26+
const thisTestCode = new Blob([readFileSync(__filename)]);
27+
const fileUrlForThisTestCode = new URL(__filename, 'file:');
28+
const resource = new UrlResource({
29+
resource: 'url',
30+
url: fileUrlForThisTestCode.href,
31+
caption: 'File URL Test',
32+
});
33+
34+
const result = await resource.resolve();
35+
expect(await result.text()).toBe(await thisTestCode.text());
36+
});
2337
});
2438

2539
describe('GitDirectoryResource', () => {

packages/playground/blueprints/src/lib/resources.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -301,22 +301,39 @@ export abstract class FetchResource extends Resource<File> {
301301
this.progress?.setCaption(this.caption);
302302
const url = this.getURL();
303303
try {
304-
let response = await fetchWithCorsProxy(
305-
url,
306-
undefined,
307-
this.corsProxy
304+
const looksLikeFileUrl = url.startsWith('file:');
305+
const looksLikeCommandLineEnvironment = import.meta.url.startsWith(
306+
'file:'
308307
);
309-
if (!response.ok) {
310-
throw new Error(`Could not download "${url}"`);
308+
let blob: Blob;
309+
if (looksLikeFileUrl && looksLikeCommandLineEnvironment) {
310+
const [nodeFs, nodeUrl] = await Promise.all([
311+
import('fs'),
312+
import('url'),
313+
]);
314+
315+
const filePath = nodeUrl.fileURLToPath(url);
316+
const buffer = nodeFs.readFileSync(filePath);
317+
blob = new Blob([buffer]);
318+
} else {
319+
let response = await fetchWithCorsProxy(
320+
url,
321+
undefined,
322+
this.corsProxy
323+
);
324+
if (!response.ok) {
325+
throw new Error(`Could not download "${url}"`);
326+
}
327+
response = await cloneResponseMonitorProgress(
328+
response,
329+
this.progress?.loadingListener ?? noop
330+
);
331+
if (response.status !== 200) {
332+
throw new Error(`Could not download "${url}"`);
333+
}
334+
blob = await response.blob();
311335
}
312-
response = await cloneResponseMonitorProgress(
313-
response,
314-
this.progress?.loadingListener ?? noop
315-
);
316-
if (response.status !== 200) {
317-
throw new Error(`Could not download "${url}"`);
318-
}
319-
return new File([await response.blob()], this.name);
336+
return new File([blob], this.name);
320337
} catch (e) {
321338
throw new Error(
322339
`Could not download "${url}".

0 commit comments

Comments
 (0)