search hotlink icon profile hotlink icon
Package avatar Public | 1.1.x - 1.x.x

On This Page

Via the required structure wrapper, you expose your package directories to Fusion and users by marking them with their paths. Each path is relative to the package root, begins with a leading /, can include multiple segments separated by /, and maps to values explained in the following sections:

Note

Paths can map to existing directories or ones Fusion will generate. Do not create empty directories manually.

Stateful Directory Indicator

The only required structure entry is the stateful directory indicator. It specifies a custom path inside your package where Fusion stores stateful files:

                {
    "structure": {
        "/path": "stateful"
    }
}
            

Stateful files are data generated during task execution that reflect the current state of the package rather than its static source files. Depending on the task, the package's position in the dependency graph, and the environment-specific metadata files, Fusion regenerates all or a subset of the following files each time it manages the package.

Requireable files returning datasets in each package individually:

Additional root package files:

  • PrefixAutoloader.php: prebuilt autoloader
  • snapshot.local.json: local dependency versions
  • snapshot.dev.json: shared dependency versions
  • snapshot.json: production dependency versions

Dependency Source

Packages usually depend on other packages to reuse existing logic. To let Fusion resolve and download such dependencies for your package, define their source locations in the metadata structure as a sequence of segments separated by /.

Note

As an example of a typical sequence of segments, we use Fusion's own source valvoid.com/valvoid/fusion/1.1.0, available on the package's detail page.

Leading API Segment

The first segment of a source identifies which of the configured hub APIs to use:

  • valvoid.com: our example source
  • gitlab.com
  • github.com
  • bitbucket.org
  • git
  • dir

Wrapped Path Segments

The segments between the leading API segment and the trailing reference segment define the path to the package on the external host, which, depending on the platform, may represent various naming conventions such as package, organization/project, project, or another type of identifier.

Note

In addition to the external platform identifier, the path segments also serve as the package identifier segments in the metadata, and therefore must match them.

As in our example source, the path segments valvoid/fusion correspond to the default Valvoid API identifier:

                $url = "<api>/v1/registry/" .

    // identifier
    urlencode("valvoid/fusion") . "/1.1.0/fusion.json";
            

And the metadata package identifier it returns:

                {
    "id": "valvoid/fusion"
}
            

In the case of a superset path, non-identifier segments are excluded by the single quote ' character prefix. For example, Fusion also has a GitLab repository illustrating a superset path: gitlab.com/valvoid/fusion/'code

Trailing Reference Segment

The last source segment is a logical expression that the required package versions must satisfy. In addition to the semantic version, the expression may consist of the following parts:

  • The && and || operators
  • The condition brackets ()
  • The version tag name {0,10} indicator
  • The offset : indicator
  • One of the signs as prefix before the version:
    • != not equal
    • == equal
    • = greater than or equal
    • <= less than or equal
    • > greater than
    • < less than

In our example source, the trailing segment 1.1.0 covers all production versions without breaking changes and is shorthand for >=1.1.0 && <2.0.0 (valvoid.com/valvoid/fusion/>=1.1.0 && <2.0.0), meaning versions must be at least 1.1.0 but less than 2.0.0. Production here refers to semantic versions without a release part (for example, 1.1.0-alpha), which Fusion ignores by default if not explicitly defined.

Note

Since a semantic version by itself already implies a range, signless semantic version references are used as shorthand range expressions for all versions without breaking changes.

Note

Fusion ignores by default the release part if not explicitly defined.

If a source, such as Fusion's GitLab gitlab.com/valvoid/fusion/'code, points to a VCS repository, the trailing reference segment may need to be more flexible, allowing a version tag prefix, such as v1.2.3, or an offset, such as:

  • ==v1.1.3-dev:main: branch (head commit)
  • ==1.2.3:541bae1712ad746fecc67b633ae4e1f2de73851e: commit
  • ==v1.2.3+23453:v1.0.0: tag

Note

Fake offset versions must be prefixed with == and use : to specify a VCS reference.

Nested Dependencies

Once a source is defined, besides specifying the external location, it also serves as a directory-type indicator marking a custom dependencies directory inside your package, such as:

                {
    "structure": {
        "/dependencies": [
            "valvoid.com/valvoid/fusion/1.1.0"
        ]
    }
}
            

Inside the marked directory, Fusion normalizes the dependency graph by using package identifiers as subdirectories. This approach keeps the structure user-readable (if you need to check a dependency in your package) and avoids conflicts, since a path can contain multiple sources and dependencies can have their own dependencies.

For example, our source would result in the subdirectory /dependencies/valvoid/fusion, and if we add another source such as the Box - PHP DI Container, whether added directly or as a nested dependency from Fusion, the directory structure would be:

  • /dependencies/valvoid
    • /box
    • /fusion

The normalized directory is also shareable between scoped metadata files. For example, the structure is the same whether Box is specified in the shared fusion.dev.php or local fusion.local.php metadata:

                return [
    "structure" => [
        "/dependencies" => [
            "valvoid.com/valvoid/box/1.0.0"
        ]
    ]
];
            

Note

Metadata files cannot contain the same source, but they can share the same path.

Recursive Self-Dependency

Since Fusion also manages root packages, you can declare a nice-to-have dependency on your own package, as shown in the metadata of our example source:

                {
    "structure": {
        "valvoid.com/valvoid": "fusion/1.1.0"
    }
}
            

The missing path makes this source different from nested dependencies. It points to the package root, making the source argument optional when updating a root package, such as Fusion:

                fusion build
            

Otherwise, you would need to run:

                fusion build build.source=valvoid.com/valvoid/fusion/1.1.0
            

Note

This type of source acts as a default usability fallback for missing input. It does not apply if a source is explicitly provided by the user, or if the package is nested within another project where the parent package already defines the source.

In shared or local development, you typically do not want the package to update automatically to a production version. You can prevent this by setting the recursive dependency to null in the optional fusion.local.php or fusion.dev.php metadata, as shown in our example (GitLab repo):

                return [
    "structure" => [
        "valvoid.com/valvoid/fusion" => null
    ]
];
            

Structure Segmentation

All metadata files are optimized for user-friendly input. Paths and sources can be broken into segments to reduce redundancy and make configuration easier. For example, using the sources from our previous examples, you can write:

                {
    "structure": {
        "valvoid.com/valvoid": {
            "/dependencies": [
                "fusion/1.1.0",
                "box/1.0.0"
            ]
        }
    }
}
            

Path segments start with / and must be used as keys. Source segments do not start with / and can appear as either keys or values. If a source is split into segments, its key can begin anywhere in the structure, but the final part must always be the source value.

Extendable Directory Indicator

The optional extendable directory indicator marks a path inside your package that can be extended through Fusion's built-in extension logic:

                {
    "structure": {
        "/path": "extendable"
    }
}
            

Note

The directory must not exist if your package has no default content.

A parent package can map its own directory to this internal path as a reference:

                {
    "structure": {
        "/custom": ":your/package/identifier/path"
    }
}
            

Note

The mapping starts with : followed by the package identifier and ends with the extendable path inside the package.

Mappings are stored in the stateful extensions.php file, listing absolute directories of all extenders. Array keys indicate package positions in the dependency graph, in top-down order:

                return [
    "/path" => [

        // dependency of the root package
        // extends your package
        2 => "/absolute/extender/dir",

        // root package
        // has "2" as dependency and also extends your package
        7 => "/other/extender/dir"
    ]
];
            

Note

The mapped directory is only a reference. The extended package must iterate over or process the linked directory. Fusion does not automatically inject its contents.

Mutable Directory Indicator

Fusion recycles existing packages when building a new external package state. The optional mutable directory indicator marks non-recyclable content in your package, for example files generated by a lifecycle callback, that must be copied from the new state into the existing package each time:

                {
    "structure": {
        "/path": "mutable"
    }
}
            

Note

Use mutable for content that cannot be reused across package states. Fusion ensures the latest version is injected into the recycled package during the build process.