# package.osy

> The manifest that makes a git repository a publishable Osy# package. It names the package, says which of the repository's files actually ship, declares the platform floor its source needs, and lists the packages it builds on.

<!-- id: project-package · area: project · stability: preview · html: https://osysharp.com/reference/project/package/ -->

## Summary        {#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.osy` you write now is checked but not yet consumed.

## Signature      {#signature}
```osy syntax
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    {#description}

### What a package says about itself   {#settings}

| 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   {#roles}

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:

```osy preview
package Osysharp.Charts {
  version "1.0.0";
  summary "Composable charts, in Osy#.";

  model "*.osy";
  model "vocabularies/*.osy";
}
```

### A control and its bundle travel together   {#controls}

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.

```osy preview
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}

`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.

```osy preview
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   {#min-platform}

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:

```console
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   {#location}

`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:

```console
a `package` declaration belongs in `package.osy` at the root of the package's repository, not in `m.osy`.
```

## See also       {#see-also}
- [app.osy](https://osysharp.com/reference/project/manifest/) — `app.osy`, the same idea for an application
- [project layout](https://osysharp.com/reference/project/layout/) — where files go in a project
- [use](https://osysharp.com/reference/types/use/) — `use` and version pins
