Everybody is welcome! People of all experience levels can join and begin contributing and should feel comfortable and safe making mistakes.
People of all backgrounds belong here as long as they treat others with dignity and respect and do not harass or belittle others.
It's ok to ask questions by opening an issue!
I (@f-f) am also on the PureScript Discord, so you can also ask
questions in the #spago
channel.
Any open issue that is not assigned to anyone is good to work on!
If it's your first time contributing then it's probably best to pick the ones marked with "good first issue".
The easiest way you can help is by contributing documentation (look for issues with the label "document me").
Do not worry if it's just about copypasting some instructions from an issue to the README, everything is welcome!
If you wish to contribute documentation, this is a suggested read
# Install dependencies
npm ci
# Bootstrap
spago bundle -p spago-bin
# From now on you can build with the local files in the output folder, e.g.:
./bin/index.dev.js bundle -p spago-bin
# Or from the built bundle:
./bin/bundle.js bundle -p spago-bin
# From now on you can use the bootstrapped build to see the changes you make:
./bin/index.dev.js build --pedantic-packages --some-new-build-flag
# ...but you can of course still just use the global `spago` command:
spago build
# Can of course run the tests with
spago test
# Can select a subset of tests to run
spago test -- --example "bundle" # run only bundle tests
spago test -- --example "browser" # run only tests that mention browser in their name
# Can select a subset of tests by a regular expression
spago test -- --example-matches "bundle|browser" # run bundle tests _and_ those that mention browser
# To see tests' stdout/stderr output while the tests are running, run
SPAGO_TEST_DEBUG=1 spago
# To overwrite fixture's with the test's run, run
SPAGO_TEST_ACCEPT=1 spago
If you edit any title in the readme, run doctoc
to update the Table of Contents:
doctoc --notitle README.md
If you want to contribute new or edit existing flowcharts, download yEd, use that program to edit the .graphml
files, and then export them as an SVG or PNG file via the CTRL+E shortcut. When a dialog box appears, just press 'ok' and use the default export settings.
The following are recommendations to make using yEd
easier/faster:
- In the 'Preferences' dialog
- Under the 'General' tab, change the "Mouse Wheel Behavior" to "[Wheel] Up/Down, [Shift+Wheel] Left/Right, [Ctrl+Wheel] In/Out"
- Under the 'Editor' tab, check the "Create Node on background click" box
- Under the 'Editor' tab, check the "Edit Label on Create Node" box
- Under the 'Editor' tab, check the "Dynamically Adjust Node Size to Label Size" box
- Click on an edge between two nodes...
- ... and press F2 to add text to that edge
- ... and press F6 to edit its properties. Under the 'Label' tab, change the "Placement"'s "Model" dropdown to "Free" to get full control over where the edge's text can appear.
All changes must happen through a Pull Request.
Everyone with the "commit bit" can merge changes.
Just ask! I (@f-f) hand out the commit bit freely to anybody who displays sustained interest in the project, sometimes even if they don't ask. However, you shouldn't assume that you are undeserving if I haven't given you the commit bit. I might just be busy or forgetful, so I appreciate a helpful reminder. You can ask directly by e-mail (see my account profile) or by opening an issue, whichever you prefer.
I hand out the commit bit freely because mistakes are easy to fix or roll back. Learn by doing and get your hands dirty!
File paths are very important in Spago. A very big chunk of Spago does is shuffling files around and manipulating their paths. Representing them as plain strings is not enough.
Spago has three different kinds of paths, represented as distinct types:
RootPath
can generally be the root of anything, but in practice it usually points to the root directory of the current workspace. It is constructed inMain.purs
close to the entry point and is available in allReaderT
environments asrootPath :: RootPath
LocalPath
is path of a particular file or directory within the workspace. It doesn't have to be literally within the workspace directory - e.g. a custom dependency that lives somewhere on the local file system, - but it's still relative to the workspace. ALocalPath
is explicitly broken into two parts: aRootPath
and the "local" part relative to the root. This is useful for printing out workspace-relative paths in user-facing output, while still retaining the full path for actual file operations. ALocalPath
can be constructed by appending to aRootPath
. Once so constructed, theLocalPath
always retains the same root, no matter what subsequent manipulations are done to it. Therefore, if you have aLocalPath
value, its root is probably pointing to the current workspace directory.GlobalPath
is for things that are not related to the current workspace. Examples include paths to executables, such asnode
andpurs
, and global directories, such asregistryPath
andglobalCachePath
.
Paths can be appended by using the </>
operator. It is overloaded for all
three path types and allows to append string segments to them. When appending to
a RootPath
, the result comes out as LocalPath
. You cannot produce a new
RootPath
by appending.
Most code that deals with the workspace operates in LocalPath
values. Most
code that deals with external and global things operates in GlobalPath
values.
Lower-level primitives, such as in the Spago.FS
module, are polymorphic and
can take all three path types as parameters.
For example:
rootPath <- Path.mkRootPath =<< Paths.cwd
config <- readConfig (rootPath </> "spago.yaml")
let srcDir = rootPath </> "src"
compileResult <- callCompiler [ srcDir </> "Main.purs", srcDir </> "Lib.purs" ]
FS.writeFile (rootPath </> "result.json") (serialize compileResult)