Summary#
app.osy describes an application: everything a compile consumes, tests included. package.osy describes an
artifact: what goes into the archive somebody else fetches. A repository carries tests, CI, docs and
node_modules; none of those are the package, and the manifest's globs are where that line is drawn.
A package's identity is Owner.Name, and the owner is what makes the name yours — it maps to the GitHub account or
organisation that publishes it, so nobody can publish under a name they do not control.
Preview. The manifest parses and validates today. Fetching, publishing and resolving a package against it are being built, so a
package.osyyou write now is checked but not yet consumed.
Signature#
package <Owner>.<Name> {
version "1.0.0"; // required — what a `use` constraint resolves against
minPlatform "0.9.0"; // the platform floor this package's SOURCE needs
contract 3; // the control ABI generation, a separate axis
summary "One line.";
model "model/**/*.osy"; // the Osy# a consumer's compiler reads
controls "controls/**"; // built control bundles and their chunks
fonts "fonts/**";
use <Owner>.<Other>@1; // a package this one builds on
}Description#
What a package says about itself#
| Setting | Literal | What it decides |
|---|---|---|
version | string | Required. The version a use Owner.Name@1; constraint resolves against, and the git tag publishing creates. A package without one cannot be depended on. |
minPlatform | string | The oldest platform this package's source will run on. Read first, before anything else in the manifest — see below. |
contract | whole number | The control ABI generation the package's controls are written against. Independent of version: a package can ship many versions against one ABI. |
summary | string | One line, shown when somebody is deciding whether to depend on you. |
A setting is declared once. A role may repeat, and every glob applies — that difference is the whole reason the two are separate vocabularies.
Which of the repository’s files ship#
Each role is a glob, and the globs are what decides what ships. Declare a role and your globs replace its default.
| Role | Default | What it carries |
|---|---|---|
model | model/**/*.osy | The Osy# a consumer's compiler reads. A package that ships none declares nothing. |
controls | controls/** | Built control bundles and their chunks. |
fonts | **/fonts/*.woff2 and the other three web font formats | Font files, pinned by hash. |
icons | **/icons/*.svg | Build-time glyphs, exactly as in an app. |
svg | **/art/*.svg | Illustrations rendered inline, keeping their own fills. |
textures | **/textures/*.png and the other raster formats | Raster assets. |
sounds | **/sounds/*.mp3 and the other audio formats | Audio assets. |
There is no tests role, and that is deliberate: a package's tests are its repository's business and run before an
archive exists. They are not part of what somebody downloads.
Nothing assumes your sources live under src/. A flat repository is a normal package — say so and it works:
package Osysharp.Charts {
version "1.0.0";
summary "Composable charts, in Osy#.";
model "*.osy";
model "vocabularies/*.osy";
}A control and its bundle travel together#
A control is two halves: a control declaration in your Osy#, and the JavaScript bundle it names. They go into one
archive under one hash, so a consumer cannot end up with one half from one build and the other from another. That is
not a rule anybody has to remember — the halves are not two artifacts.
package Someone.Editor {
version "2.0.0";
minPlatform "1.0.0";
contract 3;
model "model/**/*.osy";
controls "controls/**";
fonts "fonts/**";
}Depending on another package#
use inside a package manifest means what it means inside app.osy: this is a dependency, at this version. Ask for
a package and its own dependencies come with it.
package Someone.Dashboard {
version "1.4.0";
model "model/**/*.osy";
use Osysharp.Charts@1;
use Someone.Editor@2;
}A dependency is transitive; an import is not. Fetching Someone.Dashboard fetches Osysharp.Charts too, because
the dashboard needs it to compile. It does not put the charts in your app's scope. If a page of yours names a
chart directly, your own app.osy says use Osysharp.Charts@1;. That is C#'s rule — a using never re-exports — and
it is what stops an app quietly depending on something it never declared, then breaking the day a package drops it.
minPlatform is read first, and that is not an implementation detail#
A package published against a newer platform carries fields an older one has never heard of. If the older platform checked the vocabulary first, it would complain about one of those — which reads like a broken package and is actually an out-of-date reader.
So minPlatform is understood before anything else in the manifest is interpreted. An old platform meeting a new
package says the one useful thing:
package 'Someone.Future' needs platform >= 2.0.0; this platform is 1.4.0.
Upgrade the platform, or use a version of the package published for this one.Once the floor is met, the unknown entries are the story again and each is named.
Where the file goes#
package.osy sits at the root of the package's repository, and it is the only file a package block belongs in.
Writing one inside an app's model/ is refused, because nothing in an application reads it:
a `package` declaration belongs in `package.osy` at the root of the package's repository, not in `m.osy`.See also#
- app.osy —
app.osy, the same idea for an application - project layout — where files go in a project
- use —
useand version pins