Define a package with Package.json
Package.json lives at the root of an application or package. It describes
the project's sources, required packages, and, for a published package, its
identity and any native files it uses.
| Intention | Fields |
|---|---|
| Identify and present the package | name, version, description, authors, repository, requires |
| Select sources | sources |
| Build the package graph | dependencies, devDependencies |
| Share a namespace | extensions, catalogs |
| Prepare a native integration | boundary, artifacts |
An application may need only sources and its dependencies. Fields that grant
a namespace, open catalogs, or declare a native boundary belong to a named
package.
Identify and present the package
A package intended for sharing declares at least its name, version, and Silex compatibility:
{
"name": "MyPackage",
"version": "1.0.0",
"description": {
"en": "Reusable utilities for Silex applications.",
"fr": "Outils réutilisables pour les applications Silex."
},
"authors": ["Matanek"],
"requires": {
"silex": ">=0.44.0"
}
}
name is the identity used by dependencies and imports. A local package folder
has the same name. version uses MAJOR.MINOR.PATCH. Once published, its bytes
cannot be replaced.
requires.silex begins with an inclusive minimum. Prefer an open range such
as ">=0.44.0": it allows the package to be used with later Silex releases
for as long as no incompatibility is known. In particular, it avoids blocking
each new minor release as a precaution.
An exclusive maximum is also supported, for example
">=0.44.0 <0.45.0". This bounded range is less common: reserve it for a
known incompatibility or a contract that must actually stop before that
release. An installed package must declare its compatibility; a local package
under development may still omit requires.silex.
Describe the package in one or more languages
A plain string applies to every language:
{
"description": "Reusable utilities for Silex applications."
}
A localized object maps each language tag to its description, as in the first
example. It must contain en. Silex checks the exact language, then its primary
language — fr for fr-FR — and finally en.
Each text must be one non-empty line with no surrounding whitespace. Language tags are compared case-insensitively and cannot be repeated.
authors is an optional array of unique, non-empty names. Their order is
preserved. This field attributes the work; it grants no right over the
registry, namespace, or sources.
repository is an optional HTTPS GitHub URL for the package's development.
It helps contributors find the source repository. The registry stores the files
sent from the local directory; this URL neither supplies those files nor
proves ownership of a package name.
Select sources
sources selects the portable source folder relative to the manifest:
{
"sources": "Sources"
}
The default is Module. The value "." selects the project root. A manifest
accepts exactly one folder, with no absolute path, backslash, glob, array,
empty segment, or internal . or .. segment.
The same value is reused below the Platform/<OS>/ and Target/<target>/
roots. The mapping from these physical files to logical modules is explained
in the language's package boundaries.
Declare dependencies
dependencies contains packages required by distributed code.
devDependencies contains only tools used to develop, test, demonstrate, or
measure the package:
{
"dependencies": {
"STD": "^0.20.0"
},
"devDependencies": {
"GFX.Viewer": "^0.3.0"
}
}
^1.4.0 accepts the requested version and newer releases with the same major
number. =1.4.0 selects exactly that version. This rule also applies during
the 0.x series: ^0.7.0 accepts 0.8.0, but not 1.0.0.
A package cannot appear in both objects. Consumers see only dependencies and
must still directly declare every package they import. devDependencies join
only the root package's development graph; they do not propagate recursively.
The command that prepares this graph is documented in Install and select packages.
Authorize composition between packages
extensions authorizes separately distributed child packages. catalogs
opens facade modules to contribute blocks. This is the relevant excerpt from
the GFX manifest:
{
"extensions": {
"GFX.Physics": {
"friend": true
},
"GFX.UI": {
"suite": true
},
"GFX.GPU": {
"friend": true,
"suite": true
}
},
"catalogs": ["GFX.Components", "GFX.Plugins", "GFX.Resources"]
}
An empty entry such as "GFX.UI": {} authorizes only the child's identity. An
exact entry may add three independent permissions:
friendopens the parent'spackagedeclarations to the child;suitemakes the child selectable by the parent's--suiteinstallation;mergeallows additive public composition of the exact primary module.
The Parent.* wildcard covers direct children only. It may carry friend, but
not suite or merge.
catalogs is independent from these permissions: only that field opens named
modules to contributions. Any named package may contribute, whether it is a
child or external package, provided it declares the catalog owner as a direct
dependency. Participation grants no friend, suite, or merge permission
and no part of the owner's namespace. The visibility and composition effects
are detailed in package boundaries and
re-exports.
Declare a native boundary
boundary describes private native inputs that the compiler may link for one
target. Each branch contains named providers:
{
"boundary": {
"macos-arm64": {
"providers": {
"Native": {
"archive": "Boundary/macos-arm64/libNative.a",
"frameworks": ["CoreFoundation"]
}
}
},
"linux-x64": {
"providers": {
"Native": {
"archive": "Boundary/linux-x64/libNative.a",
"libraries": ["m", "pthread"]
}
}
}
}
}
| Provider field | Role |
|---|---|
archive |
Static archive relative to the package and compatible with the target |
frameworks |
Named Apple frameworks, on macOS only |
libraries |
Named system libraries, without paths or raw linker options |
requires |
Other providers in Package.Provider form |
A provider declares at least one of these inputs. It may contain only a system
library, framework, or another provider and then needs no dummy archive. A
requirement may target the package itself or a direct dependency, for example
"requires": ["GFX.SDL3"].
Silex selects only the active target branch. When an archive is declared, its format and architecture must match that target. The boundary remains private to the package: consumers see its public Silex API, not foreign archives, frameworks, libraries, or symbols. Source code that calls a provider is documented in Connect a package to a system API.
Prepare verified artifacts
artifacts describes large files needed for each target. An archive used by
boundary can be prepared at the expected path:
{
"artifacts": {
"macos-arm64": {
"Native": {
"path": "Boundary/macos-arm64/libNative.a",
"url": "https://example.com/releases/libNative.a",
"sha256": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
}
}
}
}
path stays inside the package, and sha256 contains the 64 hexadecimal
digits of the expected digest. url is optional; when present, it uses HTTPS
and lets a local package fetch a missing file during preparation. silex publish requires the declared file to be present and match its digest, then
uploads it as a separate registry object. silex install of a published
version reads that object from the registry without relying on the development
URL. Compilation never downloads a file.
artifacts therefore prepares a file, while boundary decides how that file
participates in native linking. The fields are independent: an archive already
included among the sources needs no artifacts entry.
Validate the manifest
Before publishing a package, validate its identity, version, and current-target contract:
silex check MyPackage
To prepare artifacts for another target, then use --target with
silex install or silex link. See
Develop with local packages and
Publish a package in the registry for the complete
workflows.
Back to tools · Install and select packages · Understand package boundaries