Package contract
Package structure
Package identity
A Voyzu package must have a scoped npm name in the form @publisher/package-name. The publisher and package name must be valid, stable directory names. This npm name as it appears in package.json is the package's authoritative identity.
Example:
@acme/warehousingSource location
A package must reside at packages/@publisher/package-name within its Git repository. Its directory path must exactly match the name in its package.json.
Example:
packages/
└─ @acme/
└─ warehousing/
└─ package.json # "name": "@acme/warehousing"Package boundary
Package source, installation files, scripts and permanent configuration must remain inside the package directory. A package must not depend on generated files beneath .run or write permanent source into the Voyzu Platform runtime.
Example:
package.json entries
Package metadata
A package must contain package.json, use ES modules and declare itself as a Voyzu package. voyzu.allowInstall must be true before Voyzu will install the package; it does not represent runtime status.
Dependencies are the voyzu packages this package depends on.
Example:
Required exports
A package must export its package definition through the standard export name. Each additional declared export must resolve to the corresponding package-owned source file.
Example:
Public exports
Code intended for use by another package must be exposed explicitly through package.json exports. A consuming package must not import another package's private file paths.
Example:
npm dependencies
A package must declare ordinary runtime requirements in dependencies and host-provided requirements in peerDependencies. Development-only file: paths must not be used as distributable package dependencies. See Managing dependencies.
Example:
Voyzu package dependencies
The voyzu metadata in package.json must contain a dependencies array, even when the package has no package-level dependencies. A dependency must use the depended-on package's scoped npm name. Voyzu itself is an implicit dependency and must not be listed.
Example:
Page and API root paths
A package must separately declare the page and API URL namespaces it owns. Root paths reserve namespaces; they do not create routes. Actual page and API routes are registered by the package's modules.
Page root paths
voyzu.pageRootPaths contains the package's browser-facing page namespaces. Every page route registered by the package must equal one of these roots or be a child of one.
For example, a page root of /warehousing permits module page routes such as:
It does not permit a page route beneath /purchasing unless /purchasing is also declared as a page root.
Page-route visibility is managed independently after installation. Hiding a package's page routes prevents direct access to its registered pages. Hiding its top-navigation items is a separate setting and does not hide its pages.
API root paths
voyzu.apiRootPaths contains the package's API namespaces relative to Voyzu's shared /api prefix. Every API route registered by the package must equal one of these roots or be a child of one.
For example, this declaration:
permits module API paths such as /warehousing/stock and /warehousing/stock/{code}. Callers use the external URLs /api/warehousing/stock and /api/warehousing/stock/{code}.
API routes have no package visibility setting. Hiding top navigation or page routes does not disable a package's APIs.
Uniqueness and overlap
Page and API roots are separate routing spaces and may use the same value within one package. Across packages, roots in the same routing space must not overlap. Installation and development linking reject both exact duplicates and nested collisions such as /warehousing and /warehousing/reports. A package with no routes of a given kind must declare an empty array.
Example:
Package settings
A package that supplies page help must declare its documentation base URL at voyzu.settings.helpBaseUrl in package.json. Page routes supply only their package-relative helpPath; Voyzu combines the two values when rendering the Help action. The base may use GitBook or any other HTTP or HTTPS documentation provider.
Example:
See Documentation and help for the documentation source and contextual Help pattern.
voyzu.package.ts entries
Package definition
A package must contain voyzu.package.ts and default-export an object conforming to VoyzuPackageDefinition. The definition must provide modules. A normal package must register at least one module. An install-only package may use an empty modules array when it declares at least one database installation file. Package identity, version and description belong only in package.json.
Example:
Module registration
A package that provides application functionality must register at least one module in voyzu.package.ts. Only modules present in the modules collection are composed into the page and API registries. Every registered module must satisfy the module contract. An install-only package may declare modules: [] and contributes no page or API routes.
Example:
Install-only example:
Database installation
A package that owns database objects may declare ordered sql and seedSql files. Paths must be relative to the package and must not escape its directory. Voyzu executes sql first and seedSql second, in declared order. Installation SQL must be safe to run again when a package is updated.
Example:
Database uninstallation
A package may declare ordered uninstall.sql files that reverse its database installation. Voyzu executes the files in one transaction before removing the installed package copy. Package uninstall SQL must leave platform-owned audit records intact.
Package scripts
A package may expose callable methods through the scripts object in voyzu.package.ts. Script entries must be functions, not command strings. Standard package scripts include sampleData. Uninstallation is a dedicated package lifecycle rather than a general-purpose script.
Example:
Navigation
Top navigation
A single-domain package may export one or more top-navigation definition. When present, its routeId must identify one page route belonging to a registered module. That route becomes the package's default surface route. A server-only package may omit top navigation.
Example:
Multiple navigation domains
A package that provides more than one top-navigation domain must export ./navigation/domains instead of the single-domain top- and left-navigation exports. Each domain must declare its label, default routeId, complete routeIds collection and left navigation. A domain may include a route owned by a preinstalled Voyzu package when that route is deliberately presented within the domain.
Example:
Left navigation
A single-domain package may export a left-navigation array. A multi-domain package must declare a separate left-navigation array for each domain in its domain collection. Every navigation item must refer to a page route by routeId; it must not duplicate the route path. A package without a user interface may omit left navigation.
Example:
Static assets
Public assets
A package may provide static web assets in a package-root public-assets directory. Composition copies the directory contents into the Next.js public directory beneath a path named after the full scoped package name. Package assets must be referenced using that package-owned URL namespace.
The example asset is served at /@acme/warehousing/warehouse-logo.svg. Composition replaces the package's complete published asset directory so renamed and deleted files do not remain in the runtime. Uninstall composition removes the uninstalled package's published assets.
See Static assets for the complete lifecycle and usage pattern.
Installation and composition
Installation mode
A deployed package must be copied from a downloaded Git repository into .run/packages. A package under local development may be linked from the root packages workspace. The package contract must be identical in either mode.
Example:
Composition
An installed package must be composable without manual edits to the Voyzu Platform. Voyzu derives workspace dependencies, Next.js transpilation, page routes, API routes and navigation from the installed package contract. Generated composition files must not be edited by the package.
Example:
Documentation
Documentation layout
A package must keep its overview in a root README.md. All other package documentation should reside in a package-root docs directory. Documentation intended for users or publication as online help should reside in docs/public. See Documentation and help for more information.
Voyzu patterns
A package should follow the established Voyzu patterns for data, APIs, application surfaces, validation, auditing, integration and testing unless the package documents a deliberate exception.
Example:
See the patterns for data, APIs, application surfaces, validation, auditing, and testing.
Reference package
The Voyzu Ice Creams package conforms to this contract and demonstrates many of the established package and application patterns in use.
Last updated