[!IMPORTANT]
This documentation concerns the new PureScript rewrite of Spago. If you are looking for the Haskell codebase (versions up to 0.21.x), please head over to the [spago-legacy] repo.
[!WARNING]
This new Spago is still in alpha, so while most of it works well, there will be some rough edges here and there. Please report them if you find any!
The recommended installation method for Windows, Linux and macOS is npm (see the latest releases on npm
[here][spago-npm]):
npm install -g spago@next
Other installation methods available:
With Nix, using [purescript-overlay]
General notes:
The assumption is that you already installed the [PureScript compiler][purescript].
If not, get it with npm install -g purescript, or the recommended method for your OS.
You might have issues with npm and Docker (e.g. getting the message âDownloading the spago binary failed..â etc)
You have two options:
either do not run npm as root, because it doesnât work well with binaries. Use it as a nonprivileged user.
or use --unsafe-perm: npm install -g --unsafe-perm spago@next
If you have a look at the spago.yaml file, youâll see that it contains two sections:
[the workspace section]!(#the-workspace), which details the configuration for the dependencies of the project as a whole (which can be a monorepo, and contain more than one package), and other general configuration settings.
In this sample project, the only configuration needed is the [package set]!(#whats-a-package-set) version from which all the dependencies will be chosen. See [here]!(#querying-package-sets) for more info about how to query the package sets.
[the package section]!(#whats-a-package), that is about the configuration of the package at hand, such as its name, dependencies, and so on.
For more info about all the various configuration settings, visit the section about [the configuration format]!(#the-configuration-file).
To build and run your project, use:
Terminal window
$ spago run
This will:
download and compile the necessary dependencies (equivalent to spago install)
compile this sample project in the output/ directory (equivalent to spago build).
You can take a look at the content of output/Main/index.js to see what kind of JavaScript has been generated from your new Main.purs file
run the generated JS, which is roughly equivalent to running
The above code imports the JS file you just looked at, and runs its main with Node.
You can also bundle the project in a single file with an entry point, so it can be run directly (useful for CLI apps):
Terminal window
$ spago bundle --bundle-type app --platform node
$ node .
Great! If you read unitl here you should be set to go write some PureScript without worrying too much about the build đ
Where to go from here? There are a few places you should check out:
see [the âHow to achieve Xâ]!(#how-do-i) section for practical advice without too much explanation
see instead the [Concepts and Explanations]!(#concepts-and-explanations) section for more in-depth explanations about the concepts that power Spago, such as [package sets]!(#whats-a-package-set), or [the Workspace]!(#the-workspace).
Great UX: a good build system just does whatâs most expected and gets out of the way so you can focus on actually thinking about the software itself, instead of spending your time configuring the build.
Minimal dependencies: users should not be expected to install a myriad of tools on their system to support various workflows. Spago only expects git and purs to be installed.
Reproducible builds: we exploit [package sets]!(#whats-a-package-set) and [lock files]!(#the-lock-file) to make your build reproducible, so that if your project builds today it will also build tomorrow and every day after that.
Some tools that inspired spago are: [Rustâs Cargo][cargo], [Haskellâs Stack][stack],
[psc-package][psc-package], [pulp][pulp] and [bazel][bazel].
# You can then create a `spago.yaml` file with `migrate`
spago-legacymigrate
# Ready to remove the dhall files and move to the new spago
npminstall-gspago@next
rmspago.dhallpackages.dhall
[!NOTE]
The spago-legacy NPM package has exactly the same content as the spago@0.21.0 release, which is the last one released from the legacy codebase, and the only release to contain the migrate command. The new codebaseâs releases start from spago@0.93.0.
Some packages might not be found or have the wrong version, in which case
youâll have to carefully:
try to run spago install some-package for packages found in the package set (see [how to query the set]!(#querying-package-sets))
[add the packages that are missing from the set]!(#add-a-package-to-the-package-set)
In all cases, youâll want to switch to the new Registry package sets, so replace something like this:
This is because the legacy package set format - while being supported - is pointing at git repositories, so Spago will fetch them using git, which can get quite slow and error-prone.
The new package sets are instead pointing at the Registry, and can fetch compressed archives from our CDN, which is much faster and more reliable.
To figure out what package set youâre supposed to be using, see the section about [querying package sets]!(#querying-package-sets).
You might also want to check out the section about [differences from legacy spago]!(#differences-from-legacy-spago).
Same as above, but with an additional spago init command just after you install [spago-legacy], so that the bower.json file is converted into a spago.dhall file.
Package sets are the default experience to ensure that you always get a buildable project out of the box, but one does not necessarily have to use them.
If youâd like to set up a project that uses the Registry solver to figure out a build plan, you can use:
Terminal window
$ spago init --use-solver
When using the solver (and when [publishing a package]!(#publish-my-library)), itâs important to specify the version bounds for your dependencies, so that the solver can figure out a build plan.
You can ask Spago to come up with a good set of bounds for you by running:
Terminal window
$ spago install --ensure-ranges
You can specify your version ranges manually in the spago.yaml configuration file too:
If you are using the Registry solver then the package must be available in the Registry, while if you
are using package sets it needs to be contained in the set. See [here]!(#add-a-package-to-the-package-set) to know more about adding more packages to the local set.
This will download and compile all the transitive dependencies of your project (i.e. the direct dependencies,
i.e. the ones listed in the dependencies key of spago.yaml, plus all their dependencies,
recursively) to the local .spago folder.
However, running this directly is usually not necessary, as all commands that need the dependencies
to be installed will run this for you.
Running spago fetch is equivalent, but skips the compilation step.
You can build the project and its dependencies by running:
Terminal window
$ spago build
This is mostly just a thin layer above the PureScript compiler command purs compile.
Note: by default the build command will try to install any dependencies that havenât been
fetched yet - if you wish to disable this behaviour, you can pass the --no-install flag.
The build will produce very many JavaScript files in the output/ folder. These
are ES modules, and you can just import them e.g. on Node.
[!NOTE]
The wrapper on the compiler is so thin that you can pass options to purs.
E.g. if you wish to ask purs to emit errors in JSON format, you can run
Terminal window
$ spago build --purs-args "--json-errors"
However, some purs flags are covered by Spago ones, e.g. to change the location of the output folder:
Terminal window
$ spago build --output myOutput
If you want to run the program, just use run:
Terminal window
$ spago run -p package-name -m Module.Containing.Main
# We can pass arguments through to `purs compile`
$ spago run -p package-name -m Module.Containing.Main --purs-args "--verbose-errors"
# We can pass arguments through to the program being run
$ spago run -p package-name -m Module.Containing.Main -- arg1 arg2
Oof! Thatâs a lot of typing. Fortunately itâs possible to configure most of these parameters in the package.run section of your configuration file, so you donât have to supply them at the command line.
See [here]!(#the-configuration-file) for more info about this, but it allows us to instead write:
Terminal window
# The main module can be defined in the configuration file, but
# purs flags still need to be supplied at the command line
spago run -p package-name --purs-args "--verbose-errors"
# It's possible to even pass arguments from the config, which would look like this:
#
# package:
# run:
# main: Main
# execArgs:
# - "arg1"
# - "arg2"
$ spago run -p package-name
Lastly, if you only have a single package defined in the workspace with these parameters defined in the config file, you can just run
# Test.Main is the default here, but you can override it as usual
$ spago test --main Test.Main
Build succeeded.
You should add some tests.
Tests succeeded.
If you are using the spec-node test runner,
you can use its command-line options to select a subset of tests with
--example or rerun previously failed tests with --only-failures:
Terminal window
$ spago test -- --example "some test"
$ spago test -- --only-failures
Note that you have to separate test runner options with a double dash -- to distinguish them from Spagoâs own options.
If youâre on PowerShell (Windows), you will also need to quote the double dash:
Terminal window
> spago test '--' --example "some test"
> spago test '--' --only-failures
This has to do with an unfortunate interaction between Node bootstrapping mechanism and the way PowerShell handles parameters.
As with the run command, itâs possible to configure the tests using the spago.yaml - most importantly to separate test dependencies from the dependencies of your application/library.
Please see [the section about the configuration format]!(#the-configuration-file) for more info, but in the meantime note that itâs possible to install test dependencies by running:
You can run a standalone PureScript file as a script via spago script.
Note: The module name must be Main, and it must export a function main :: Effect Unit.
By default, the following dependencies are installed: effect, console, prelude.
You can run a script via the following, optionally specifying a package set to use, and additional dependencies to pull from there:
There might be cases where youâd like your project to depend on all the packages
that are contained in the package set (this is sometimes called
[âacme buildâ][acme]).
If you have [jq][jq] installed, you can accomplish this in relatively few characters:
Terminal window
$ spago ls packages --json |jq-r'keys[]'|xargsspagoinstall
Override a package in the package set with a local one
Letâs say Iâm a user of the popular aff package. Now, letâs say I stumble upon a bug
in there, but thankfully I figure how to fix it. So I clone it locally and add my fix.
Now if I want to test this version in my current project, how can I tell spago to do it?
Thereâs a section of the spago.yaml file just for that, called extraPackages.
In this case we override the package with its local copy, which should have a spago.yaml - our workspace will look something like this:
workspace:
packageSet:
registry: 41.2.0
extraPackages:
aff:
path: ../my-purescript-aff
Now if we run spago ls packages, weâll see that it is now included as a local package:
Letâs now say that we test that our fix from above works, and we are ready to Pull Request the fix.
So we push our fork and open the PR, but we want to already use the fix in our build, while we wait for it to land upstream and then on the next package set.
In this case, we can just change the override to point to some commit of our fork, like this:
[!WARNING]
You can use a âbranchâ, a âtagâ or a âcommit hashâ as a version.
Itâs strongly recommended to avoid using branches, because if you push new commits to a branch, spago wonât pick them up unless you delete the .spago/packages/aff/your-branch folder.
[!IMPORTANT]
You still need to spago install my-new-package after adding it to the package set, or Spago will not know that you want to use it as a dependency!
If a package is not in the upstream package set you can make it available in your build by adding it to extraPackages.
There are a few possible scenarios - the most straightforward is when a package is already in the registry, then you just need to specify its version:
workspace:
packageSet:
registry: 41.2.0
extraPackages:
some-package-from-the-registry: 4.0.0
Another possibility is that the package is not in the registry (maybe itâs your own fork?), but itâs a git repo somewhere - e.g. if weâd like to add the facebook package:
[!NOTE]
If the upstream library that you are adding has a spago.yaml file, then Spago will just pick up the dependencies from there.
If thatâs not the case, then youâll have the provide the dependencies yourself, adding a dependencies field.
The last possible case is the one picking up a local folder as a package (note: youâll need a spago.yaml file in there):
Since the versioning scheme for package sets does not tell anything about the compiler version or when they were published, you might want
to have a look at the list of all the available ones. You can do that with:
Terminal window
$ spago registry package-sets
This will print a list of all the package sets ever releases, which could be overwhelming, as youâd likely only be interested in the latest one.
This is how you would ask for the latest package sets for each compiler version:
If your project is using the Registry solver (i.e. no package set and only version bounds), then running spago upgrade
will try to put together a new build plan with the latest package versions published on the Registry, given that they are still compatible with your current compiler.
If instead you are using package sets, then spago upgrade will bump your package set version to the latest package set available for your compiler version.
You can pass the --package-set flag if youâd rather upgrade to a specific package set version.
You can of course just edit the workspace.packageSet field in the spago.yaml file.
Spago supports fetching custom package sets from URLs and paths, so you can build your own package set if youâd like - this is useful for example if you want to put together a custom package set for your company, or if you are using an [alternate backend]!(#alternate-backends).
Spago will be happy to use a package set from a local path:
workspace:
packageSet:
path: ../my-custom-package-set.json
Otherwise you can point Spago to any URL on the internet:
âŚand it will try to fetch the content, parse it as JSON and conform it to one of the possible package set schemas.
The first one is what Spago calls a RemotePackageSet, which contains some metadata, and a map of packages in the shapes (2), (3) and (4) described for extraPackages in the [configuration format section]!(#the-configuration-file).
The second format possible is what Spago calls a LegacyPackageSet, and itâs simply a map from package names to the location of the package, described as the (4) option for how to specify extraPackages in the [configuration format section]!(#the-configuration-file).
This is supported to allow for just using legacy package sets, and be able to automatically migrate spago.dhall files to spago.yaml files.
It is not recommended to craft your own package set in the legacy format - please use the RemotePackageSet format instead - but if you do just be aware that youâll need to include a package called metadata that has a version that matches the compiler version that the set is supposed to support.
Spago supports [âmonoreposâ][luu-monorepo] (see [here][monorepo-tools] as well for more monorepo goodness), allowing you to split a pile of code
into different âcompilation unitsâ that might have different dependencies, deliverables, etc, but still compile together.
The vast majority of Spago projects will contain only one package, defined in the package section of the same spago.yaml that contains its workspace.
It is however possible to define multiple packages in the same repository!
The basic rules are:
[a package]!(#whats-a-package) is defined by a spago.yaml file containing a package section.
there can be only one workspace section in the whole repository, which defines the ârootâ of the current [Spago Workspace]!(#the-workspace). This defines your package set/build plan.
Spago will autodetect all the packages inside the workspace
âŚexcept for spago.yaml files with a workspace section, which will be ignored (together with their subfolders, as they establish a the boundary of another âworkspaceâ)
For more info about the concept of Spago Workspaces, see [the dedicated section]!(#the-workspace).
Since this might sound a little abstract, letâs try to picture the case where you might want to have the packages lib1, lib2 and app1.
Then your file tree might look like this:
.
âââ app1
â âââ spago.yaml
â âââ src
â â âââ Main.purs
â âââ test
â âââ Test
â âââ Main.purs
âââ lib1
â âââ spago.yaml
â âââ src
â âââ Main.purs
âââ lib2
â âââ spago.yaml
â âââ src
â â âââ Main.purs
â âââ test
â âââ Test
â âââ Main.purs
âââ spago.yaml
Where:
the top level spago.yaml could look like this:
workspace:
packageSet:
registry: 41.2.0
and the lib1/spago.yaml would look something like this:
package:
name: lib1
dependencies:
- effect
- console
- prelude
then, assuming lib2 depends on lib1, lib2/spago.yaml might look like this:
package:
name: lib2
dependencies:
- effect
- console
- prelude
- lib1# <------ Note the dependency here
test:
main: Test.Lib2.Main
dependencies:
- spec
and then app1/spago.yaml would look something like this:
package:
name: app1
# Note that the app does not include all the dependencies that the lib included
dependencies:
- prelude
- aff# This dep was not used by the library
- lib2# And we have `lib2` as a dependency
Given this setup, Spago will figure out that there are three separate packages in the repository.
You can select a package to perform operations on it by using the --package flag, e.g. the follow will install the maybe package in the lib1/spago.yaml:
Terminal window
spago install -p lib1 maybe
The --package flag is also available for many more commands, such as build, run, test, bundle and so on.
An important property of this âmonorepo setupâ is that the output folder will be shared between all the packages: they will share the same build package set (or build plan when using the solver) and they will be all build together.
[!NOTE]
Remember that you canât have multiple modules with the same name in a single project. This usually happens with the Main module being defined multiple times. Rename these modules to something unique.
There might be cases where you want to have multiple loosely-connected codebases in the same repository that do not necessarily build together all the time. This is sometimes called [a âpolyrepoâ][monorepo-tools].
One such example of this could be a project that has a frontend and a backend, and they are both written in PureScript, but run on different backends: the frontend runs in the browser (so in JavaScript), and the backend runs on Erlang.
Letâs say you might also want to share some code between the two (that was the point of using the same language, no?), so you might have a common package that is used by both.
You can achieve all of this with Spago, by having multiple workspaces - letâs try to visualise this.
The file tree might look like this:
.
âââ client
â  âââ spago.yaml
â  âââ src
â  â  âââ Main.purs
â  âââ test
â  âââ Test
â  âââ Main.purs
âââ common
â  âââ spago.yaml
â  âââ src
â  â  âââ Main.purs
â  âââ test
â  âââ Test
â  âââ Main.purs
âââ server
âââ spago.yaml
âââ src
â  âââ Main.purs
âââ test
âââ Test
âââ Main.purs
Where the common/spago.yaml is just a package with no workspace defined, as itâs going to support both the JS and the Erlang backend:
This is a good-defaults wrapper into esbuild, and itâs meant to be used for bundling small projects. Once your project grows in size, you might want to look into configuring esbuild (or parcel, or webpack) directly.
See the [esbuild getting started][install-esbuild] for installation instructions.
This command supports a few options, and the most important ones are:
the --bundle-type flag, which can be either app or module
the --platform flag, which can be either browser or node
See the help message for more flags, and [the configuration format section]!(#the-configuration-file) for how to configure these options in the spago.yaml file.
When bundling an app, the output will be a single executable file:
Spago does not wrap the entirety of the bundlerâs API (esbuild for JS builds), so itâs possible to pass arguments through to it. E.g. to exclude an NPM package from the bundle you can pass the --external flag to esbuild:
either through the command line, with the --bundler-args flag, i.e. --bundler-args "--external:better-sqlite3".
To build documentation for your project and its dependencies (i.e. a âproject-local
[Pursuit][pursuit]â), you can use the docs command:
Terminal window
$ spago docs
This will generate all the documentation in the ./generated-docs folder of your project.
You might then want to open the index.html file in there.
If you wish for the documentation to be opened in browser when generated, you can pass an open flag:
Terminal window
$ spago docs --open
You can customize the output to other formats beyond html. Supported formats include ctags, etags, and markdown.
For example to generate ctags for use in your editor:
Terminal window
$ spago docs --format ctags
Sometimes youâd like to pull up docs for dependencies even when you have compilation errors in your project. This is a good use case for the âdeps-only flag:
Spago supports compiling with alternate purescript backends, such as [purerl].
To use an alternate backend, include the workspace.backend section in your workspaceâs spago.yaml. See the [configuration format section]!(#the-configuration-file) for more info.
Library authors will often build âecosystemsâ of small interdependent packages that build on each other - if thatâs your situation, and youâd like to publish them all together (following some big refactoring, as it goes!), then you might wonder how to include the new version in the build plan of the next package to publish.
If youâre using the registry solver then this is not an issue, but if your project is based on a package set, then that will not contain your newly published package, since well, you just published it!
You should be able to add the newly released version to your build plan by adding it to the extraPackages section (see here):
package:
name: next-library-to-publish
dependencies:
- newly-published-library: ">=0.0.1 <0.2.0"
workspace:
packageSet:
registry: 41.2.0
extraPackages:
newly-published-library: 0.1.0
[!NOTE]
This only works when the package you add to extraPackages has been published to the registry. Adding a git dependency will produce an error, as publishing to the Registry only admits build plans that only contain packages coming from the Registry.
The Registry does not need authentication when publishing new versions of a package, but it does need it when issuing
operations that modify existing packages, [such as location transfer or unpublishing]!(registry-dev-auth).
This authentication happens through SSH keys: by having your public key in a published version, the Registry can then
authenticate requests that are signed with your private key.
Authentication and operations that use it are automated by Spago, through the spago auth command: if youâd like to
be able to perform authenticated operations you need a SSH keypair, and run spago auth passing those keys in.
This will populate the package.publish.owners field in the spago.yaml - commit that and publish a new version,
and from that moment youâll be able to perform authenticated operations on this package.
If you are the owner of a package and you want to transfer it to another user, youâd need to inform the Registry
about the new location of the repository, so that the new owner will be able to publish new versions of the package.
The transfer procedure is automated by Spago commands, and goes as follows:
Add your (or the new ownerâs) SSH public key to the spago.yaml through spago auth if they are not there already (see previous section)
Transfer the repository to the new owner using the hosting platformâs transfer mechanism (e.g. GitHubâs transfer feature)
Depending on whose key is present in the owners field, either you or the new owner will update the publish.location field in the spago.yaml, and call spago registry transfer to initiate the transfer. If all goes well youâll now be able to publish a new version from the new location.
The -v flag will print out all the purs commands that spago invokes during its operations,
plus a lot of diagnostic info, so you might want to use it to troubleshoot weird behaviours and/or crashes.
[!NOTE]
If you installed Spago not with NPM, but with PNPM or some other package manager, this package manager might have bundled your installation and your package name in the script may end up being incorrect.
For example, when installed with PNPM, the resulting script will reference incorrect package bundle.js instead of spago.
If youâre using something other than NPM, verify the referenced package name in the completions script.
This section details some of the concepts that are useful to know when using Spago. You donât have to read through this all at once, itâs meant to be a reference for when you need it.
Spago considers a âpackageâ any folder that contains:
a spago.yaml file with a valid package section
a src subfolder with PureScript source files
Thatâs all there is to it! You can have many of these in your repository if youâd like, and build them all together. See [the monorepo section]!(#monorepo-support) for more details.
The above holds for âworkspace packagesâ, i.e. the packages for which you have the source locally, and inside your repository. These are the packages âin your projectâ.
Packages on which your project depends on can come from a few different sources:
[the Registry][registry]
local packages - i.e. packages that are on your filesystem but external to your repository
remote packages - i.e. packages that are not on your filesystem, but somewhere on the internet
The bulk of the packages in your build will come from the Registry (often via a package set), but you are able to add local and remote packages to your build as well, by adding them to the workspace.extraPackages section of your spago.yaml file.
See [here]!(#add-a-package-to-the-package-set) and [here]!(#the-configuration-file) for more info about how to add these âextra packagesâ.
Packages have âdependenciesâ, which are other packages that are required for them to build. These dependencies are listed in the dependencies field of the package section of the spago.yaml file. See [here]!(#the-configuration-file) for more info about the structure of a package configuration.
The most generic way of defining a âpackage setâ is âa collection of package versions that are known to build togetherâ. The point of a package set is to provide a âstableâ set of packages that you can use to build your project, without worrying about version conflicts.
In practice, it looks something like [this][sample-package-set] !:
{
"version": "41.2.0",
"compiler": "0.15.10",
"published": "2023-09-15",
"packages": {
"abc-parser": "2.0.1",
"ace": "9.1.0",
"aff": "7.1.0",
"aff-bus": "6.0.0",
"aff-coroutines": "9.0.0",
"aff-promise": "4.0.0",
"aff-retry": "2.0.0",
"affjax": "13.0.0",
"affjax-node": "1.0.0",
"affjax-web": "1.0.0",
"ansi": "7.0.0",
"argonaut": "9.0.0",
...
}
}
The Registry maintains an âofficialâ package set such as the above, which is used by default by Spago, and only contains packages that are contained in the Registry.
Whenever anyone publishes a new package version to the Registry, the pipeline will try to build this package together with the existing set, and if the build succeeds then the new version will be added to this official set.
However, Spago also supports using custom package sets, which can contain packages that are not in the Registry, and can be used to override existing packages with local or remote versions. See [here]!(#custom-package-sets) for more info.
For any software project, itâs usually possible to find a clear line between âthe projectâ and âthe dependencies of the projectâ: we âownâ our sources, while the dependencies only establish some sort of substrate over which our project lives and thrives.
Following this line of reasoning, Spago - taking inspiration from other tools such as [Bazel][bazel] - uses the concept of of a âworkspaceâ to characterise the sum of all the project packages and their dependencies (including only âpotentialâ ones).
A very succint introduction to this idea can be found [in Bazelâs documentation][bazel-workspace] !:
A workspace is a directory tree on your filesystem that contains the source files for the software you want to build.
Each workspace has a text file named WORKSPACE which may be empty, or may contain references to external dependencies required to build the outputs.
Directories containing a file called WORKSPACE are considered the root of a workspace.
Therefore, Bazel ignores any directory trees in a workspace rooted at a subdirectory containing a WORKSPACE file, as they form another workspace.
Spago goes by these same rules, with the difference that we do not use a separate WORKSPACE file, but instead use the workspace section of the spago.yaml file to define what the set of our external dependencies are, and where they come from.
This can be as simple as:
workspace: {}
âŚwhich means that âthis is now a workspace, and all the dependencies are going to be fetched from the Registryâ.
âŚwhich means that âthis is now a workspace, and all the dependencies are going to be fetched using instructions from this custom package set (which could point to the Registry packages or somewhere else), except for the aff package, which is going to be fetched from the local folder ../my-purescript-affâ.
As described in the Bazel docs quoted above, the presence of a workspace section will denote the current folder as the root of a workspace, and Spago will recurse into its subfolders to find all the packages that are part of it - by looking for spago.yaml files with a package section - but ignore the subdirectory trees that are themselves workspaces - i.e. containing spago.yaml files with a workspace section.
The lock file is a file that Spago can generate to cache the build plan, so that it can be reused in subsequent builds.
When using package sets it is disabled by default - since we already get a stable build plan from there - while itâs enabled by default when using the Registry solver.
You can enable it manually by adding a lock: true field to the workspace section of your spago.yaml file, and that will keep it on regardless of which solving mode youâre using.
Run spago ls paths to see all paths used by Spago. But in general, Spago utilizes two main directories for every project:
the local cache directory
the global cache directory
The local cache directory is located at <project-directory>/.spago and its location cannot be changed.
The global cache directoryâs location depends on your OS. Its location can be changed by configuring the corresponding environment variable, if it is used:
Mac: ~/Library/Caches/spago-nodejs. The location cannot be changed.
Linux: ${XDG_CACHE_HOME}/spago-nodejs, or if XDG_CACHE_HOME is not set, ~/.cache/spago-nodejs. See XDG_CACHE_HOME.
Windows: %LOCALAPPDATA%\spago-nodejs\Cache, or if $LOCALAPPDATA% is not set, C:\Users\USERNAME\AppData\Local\spago-nodejs\Cache.
NixOS: ${XDG_RUNTIME_DIR}/spago-nodejs. See XDG_RUNTIME_DIR.
A common scenario is that youâd like to use things like react-basic, or want to depend
on JS libraries like ThreeJS.
In any case, you end up depending on some NPM package.
And it would be really nice if spago would take care of installing all of these
dependencies, so we donât have to worry about running npm besides it, right?
While these scenarios are common, they are also really hard to support.
In fact, it might be that a certain NPM package in your transitive dependencies
would only support the browser, or only node. Should spago warn about that?
And if yes, where should we get all of this info?
Another big problem is that the JS backend is not the only backend around. For example,
PureScript has an fairly active [Erlang backend][purerl] among the others.
These backends are going to use different package managers for their native dependencies,
and while itâs feasible for spago to support the backends themselves, also supporting
all the possible native package managers (and doing things like building package-sets for their
dependenciesâ versions) is not a scalable approach (though we might do this in the future if
thereâs enough demand).
So this is the reason why if you or one of your dependencies need to depend on some ânativeâ
packages, you should run the appropriate package-manager for that (e.g. npm).
The sources field in the configuration file does not exist anymore.
Instead, Spago will look for a src folder in the package root, and will use that as the source folder,
and similarly for the test folder, using that for the test sources.