WordPress / blueprints-library

28 stars 4 forks source link

Blueprints: Mount local directories #46

Open adamziel opened 1 year ago

adamziel commented 1 year ago

Description

Let's allow mounting filesystem directories in Blueprints.

Rationale

For local Playground, that would be useful for mounting:

In the browser, that would be useful for mounting:

Implementation

Blueprints are isomorphic and we'd need an isomorphic of handling mounts. A mounted "resource" would have to be an abstraction so that every platform can defer to a platform-specific implementation. We already have a notion of resources, perhaps it would fit in here, too:

{
    "steps": [
        {
            "step": "mount",
            "resource": {
                "resource": "localPath",
                "path": "gutenberg"
            },
            "vfsPath": "wp-content/plugins/gutenberg"
        }
    ]
}

Actually – should mounts be steps? The only two reasons I can think of is to mount them not earlier than X or to unmount them later. Neither seems compelling, so perhaps this would be a better API:

{
    "steps": [ /* ... */ ],
    "mounts": {
        // Keyed by vfsPath:
        "wp-content/plugins/gutenberg": {
            "resource": "localPath",
            "path": "gutenberg"
        }
   }
}

However, localPath doesn't make sense on the web where JavaScript only has access to the directory selected by the user. Here's yet another idea:

{
    "steps": [ /* ... */ ],
    "mounts": {
        // Keyed by vfsPath:
        "wp-content/plugins/gutenberg": {
            /**
             * Source from the `gutenberg` host directory when running locally.
             * Source from the `gutenberg` opfs directory when running in the browser.
             * Source from the `gutenberg` VSCode.dev directory when running there.
             */
            "path": "gutenberg",
            "priority": [
                // Source it from opfs if available, otherwise try the next one
                "opfs",
                // Ask the user to pick a directory if it can be done in the current runtime
                "localDirectoryPicker",
                // Treat `gutenberg` as a path on the host when that's supported
                "hostPath"
            ]
        },
        // Or use a shorthand notation
        "wp-content/plugins/friends": "friends"
   }
}

But then, with few mounts, it would be a bad UX to ask the user to select five directories in the browser. It would be much more convenient to just pick one and have Blueprints figure it out from there. Let's keep thinking about this.

Here's a few open questions:

adamziel commented 9 months ago

Thinking about this again:

How about a following, wp-now specific API, then?

{
    "wpNow" : {
        "pathMapping": [
            { "vfsPath": "/wordpress/wp-content/themes", "localPath": "../wp-content/themes" },
            { "vfsPath": "/wordpress/wp-content/plugins", "localPath": "../plugins" }
        }
    }
}

It would be a Blueprint extension provided by wp-now and would not work on the web at all. If a use-case emerges for isomorphic path mappings, we'll revisit this issue and discuss creating a new Blueprint option.

cc @danielbachhuber

eliot-akira commented 3 months ago

Local paths are specific to my machine. As a concept this doesn't fit with reusable, cross-environment Blueprints.

Maybe another approach is for wp-now to read any existing config for wp-env, and apply their mappings to mount local directories. It would be convenient for projects that currently have a .wp-env.json file, if wp-now could be (more or less) a drop-in replacement.

The "config override" concept in wp-env is useful for local dev environment. Maybe there could be an equivalent, like blueprints.local.json for local-only config or steps. But I guess that only makes sense for wp-now.

Using a local directory picker in the browser to mount it into the virtual file system sounds potentially useful, but that seems outside the scope of blueprints. Might be suitable for the "browser chrome" that frames the Playground, along with import/export/etc.

In general, it does seem that mounting directories is only practical on the server side, which can be handled by wp-now.


It would be great if the syntax for mappings is equivalent to wp-env. I have a project with a .wp-env.override.json like:

{
  "mappings": {
    "wp-content/plugins/advanced-custom-fields": "../advanced-custom-fields-pro",
    "wp-content/plugins/elementor": "./vendor/tangible/elementor"
  }
}

A notable difference from the proposed syntax for wp-now, is that wp-env only allows for mapping targets within the wordpress folder (site root). That might not be enough for wp-now, for example to map php.ini.

Another difference is that the properties vfsPath and localPath are implicit. That might be OK if those are the only possible types of source and target.