Osy#betaRun it on Osyrin: osyrin.com

Reference / Types

use

use Osysharp.Memory; use Osysharp.Ui@3;

Declares a capability your app depends on, written inside the `app { }` manifest block. It provisions the capability (its tables and types become available) and, for a kit, pins a version. It is the dependency; a `using` in a source file then imports the capability's names.

preview4 examples compiled by CImanifestdependencycapabilityuse

Summary#

use declares a capability your app depends on. It goes inside the app { } manifest block — the one place a project says what it is built from:

app Shop {
  model "model/**/*.osy";
  use Osysharp.Memory;      // depend on the Memory capability
  use Osysharp.Ui@3;        // depend on the UI kit, pinned to major 3
}

A use is your app's dependency — the equivalent of a package reference. It provisions the capability (its tables and types become part of your app) and, for a versioned kit, records which version you want. To actually reference a capability's names in a file, add a using for it there.

Signature#

use Osysharp.Memory;        // a platform capability — version-neutral
use Osysharp.Ui@3;          // a kit — pinned to a major (@3 = any 3.x; @3.3 = ≥ 3.3 within 3.x; @3.4.1 = exact)

use is only valid inside the app { } block. A version pin (@…) is only meaningful on a kit — pinning a version-neutral platform capability (which rides the platform binary) is an error.

Description#

What a dependency does#

Declaring use Osysharp.Memory; makes the Memory capability part of your app: its entities and types are provisioned, its features (here, semantic [Searchable] fields and Memory.Search) become available. Remove the use and the capability — and everything that needs it — is gone. The manifest is the single, authoritative list of what your app depends on.

A dependency has a price, and you can ask what it is. A capability that is part of your app puts its tables in your database — so use is a decision with a number attached, not a free import. osy model reports that number, per capability, and separately reports the floor every app carries whether it declares anything or not:

capabilities: Osysharp.Agents, Osysharp.Ui, Osysharp.Workflow
  Osysharp.Agents — 15 tables in your database, 7 types
  Osysharp.Ui — no tables, 8 types
  Osysharp.Workflow — 7 tables in your database, 9 types
carried regardless (not declared, cannot be declined):
  the core baseline — 2 tables
  → 2 tables before this app declares anything
brought in by a declaration you wrote:
  Osysharp.Counters — 1 table — you declare a `Counter`
  Osysharp.EventOutbox — 2 tables — you declare an `[On]` handler
brought in by a capability you declared:
  Osysharp.Memory — 4 tables

Four groups, because they answer four different questions: what you chose, what you cannot decline, what a line you wrote brought with it, and what arrived because something you chose depends on it. A capability that contributes only classes — Osysharp.Ui above — costs nothing in the database at all.

The second group is as small as it can be: two tables. Osysharp.Continuation is there because await surviving a suspension is a property of the LANGUAGE, and Osysharp.AppAdmission because the platform pausing an app for migration is not a thing an app has standing to decline. Everything else — auditing, workflow, memory, agents, storage, scheduling, and both budgets — is a capability you choose, and an app that chooses none carries those two and its own tables.

The third group is the one with no use behind it. Some storage is not a dependency you declare but a consequence of a declaration you already wrote: a Counter needs somewhere to keep the number it has reached, and app.Secrets needs somewhere to keep the sealed value, an [On] handler needs an outbox for the events it hears, and a grant needs somewhere to record the links taken back. Those tables arrive with the declaration and an app that never wrote one does not have them — so the report names the LINE rather than a capability, because the line is what you would change. (Taking the line out later keeps the table and its rows: a recompile is not where data is deleted.)

using vs use#

They are two different things, exactly as a C# project separates its package references from its imports:

WhereWhat it does
use Osysharp.Memory;inside app { }the dependency — provisions the capability, pins a kit version
using Osysharp.Memory;at the top of any source filethe import — brings the capability's names into that file's scope

A file that references a capability's names imports them with using, just like reaching any other namespace:

// model/note.osy
using Osysharp.Memory;

entity Note {
  [Searchable] string Body;      // the [Searchable] feature comes from the Memory capability
}

If your app declares an app { } manifest, that manifest is authoritative for CAPABILITIES: a using Osysharp.X; for a capability you did not use is an error — the same way C# rejects a using for an assembly you never referenced. Add the matching use to the manifest to fix it. (A quick throwaway snippet with no manifest at all is unconstrained — there, a using provisions on its own.)

What about using System.Linq;?#

The first lines of most C# files compile unchanged. The .NET namespaces whose types Osy# provides are accepted as imports that change nothing — their types are always in scope, using or not — and need no use:

usingwhat it stands for here
SystemConvert, Math, Guid, DateTime, the common exceptions
System.LinqLINQ — over a list in hand and over an entity set alike
System.Collections.GenericList<T>, Dictionary<K,V>, HashSet<T>
System.TextStringBuilder
System.Text.JsonJsonSerializer
System.Text.RegularExpressionsRegex
System.NetWebUtility

Any other .NET namespace — System.IO, System.Threading.Tasks, Microsoft.* — is refused by name: Osy# is written like C# but is not .NET, so there is no assembly behind it to import, and it is not a capability to use either. The refusal lists the accepted set above.

using System;
using System.Linq;
using System.Collections.Generic;

int Big(List<int> xs) => xs.Where(x => x > 10).Count();

A bundled KIT needs no use — the using is enough#

Osysharp.Ui, Osysharp.MarkdownEditor, Osysharp.PdfViewer and Osysharp.BarcodeScanner ship inside the platform. There is nothing to fetch and nothing to choose, so for those the using is the whole declaration — the kit composes for the files that import it, and an app that never imports it pays nothing.

Osysharp.Charts is a PACKAGE now, not a bundled kit: it lives at github.com/osysharp/charts, and an app that wants it writes use Osysharp.Charts@1; in its manifest like any other dependency. The kits are becoming packages one at a time; each one that moves gains a use and loses nothing else. See package.osy.

Osysharp.Ui adds the other direction: one use Osysharp.Ui; in the manifest puts it in scope for EVERY FILE, with no using written anywhere. It is the kit almost every app reaches for, and using is FILE-scoped — so a per-file opt-in was not one line per app but one line per file, and the line you forget is in the file you wrote last. Both spellings are legal and they answer different questions: use once for the project, using for one file.

⚠ What it is NOT is automatic. An app whose manifest references no kit does not get one — a package is fetched, and nothing can be fetched that the app never named. Name a kit control with neither spelling present and the refusal says which kit ships it and which two lines bring it in. (A throwaway snippet with no manifest keeps the kit: it has nothing to reference with, which is also why a doc example here can render a control without either line.)

The @version on a kit's use is a PIN, not a permission — the reference is the use itself:

app Shop {
  model "model/**/*.osy";
  use Osysharp.Ui@3;        // the reference, plus a version pin; a bare `use Osysharp.Ui;` is the usual form
  use Osysharp.Memory;      // a CAPABILITY: declared for a different reason — it stands up a vector store
}

The line between them is what the dependency DOES. A kit is syntax you import; a capability changes the shape of your app — Osysharp.Memory a vector store, Osysharp.Storage a blob store, Osysharp.Observability audit tables — and the manifest is where an app's shape is declared.

Version pins live on use#

A version belongs on the dependency, never on the import. use Osysharp.Ui@3; pins the kit; a @version written on a using is an error that points you back to the use.

Importing static members and naming an alias#

using static System.Math; makes Math's members callable by their bare names in that file — Abs(-3), Max(a, b), PI — and a function the file declares with the same name still wins, as in C#. using Sb = System.Text.StringBuilder; names a type alias (any type since C# 12: using Point = (int X, int Y);). Both are FILE-scoped, as in C#.

using static System.Math;
using Sb = System.Text.StringBuilder;

int Spread(int a, int b) => Abs(a - b) + Max(a, b);
string Twice(string s) => new Sb().Append(s).Append(s).ToString();

Examples#

// app.osy — the manifest declares the app's dependencies with `use`.
app Shop {
  model "model/**/*.osy";
  use Osysharp.Ui@3;
  use Osysharp.Memory;
}
// model/catalog.osy — a file imports what it references with `using`.
using Osysharp.Ui;
using Osysharp.Memory;

entity Product {
  [Required] string Name;
  [Searchable] string Description;
}

See also#

Related

namespace

Declares the namespace a file's types belong to, written once at the top of the file. It is optional — a file without…

Osysharp.Ui (the UI kit)

The bundled UI kit — ready-made styled controls like `Button`, the shared design-system vocabularies (`Tone`, `Size`)…

Pinning a kit version (using Ui@3)

A kit like `Ui` is versioned independently of the platform, so you pin the major you build against with `using Ui@3;`…