Build · package interoperability
Third-party packages
Presolve applications install and import ordinary npm packages. What the compiler needs to understand depends on each use site—not the package name. A CSS plugin can remain Vite-owned, an analytics export can be a terminal Action call, and a returned value can require a dedicated capability contract, all from the same package.
Presolve never marks an entire dependency “framework safe.” TypeScript proves the exact symbol and signature; Presolve admits one documented semantic shape; Vite bundles only the selected browser export.
Choose the integration class
| Use | Authority | Presolve meaning |
|---|---|---|
| Types, CSS tooling, media, and build plugins | TypeScript or Vite | No component, reactive, capability, or resume identity. |
| Pure value in an admitted compiler value contract | TypeScript + Presolve | The value joins that exact contract; the package gains no blanket meaning. |
| Result-discarded browser call from an Action | Presolve + TypeScript + Vite | Exact named import, parameter codecs, completion, cancellation, and resume policy. |
| Server capability implementation | Capability + server adapter | The declared capability owns transport, validation, failure, and lifecycle. |
| Arbitrary package implementation behavior | The package | Never assumed to be compiler-understood. |
Synchronous package Action
Import one named export and make its call the Action body’s complete behavior. Exact string, number, boolean, and null parameters may be forwarded once and in order.
import { recordEvent } from "@acme/analytics";import { action, Component } from "presolve";export class Checkout extends Component {record = action((category: string,value: number,enabled: boolean,metadata: null,) => {recordEvent(category, value, enabled, metadata);});render() {return <button onClick={() => this.record("checkout", 2, true, null)}>Record checkout</button>;}}The package declaration must contain the same parameters in the same order. The result is discarded. Objects, arrays, optionals, rest parameters, reordered or duplicated values, default/namespace imports, dynamic imports, computed calls, and additional statements fail closed.
Promise package Action
For cancellable async work, make the handler async, add one final signal: AbortSignal, and make the package call the sole awaited statement. The package must return exact Promise<void>.
import { recordEventAsync } from "@acme/analytics";import { action, Component } from "presolve";export class Search extends Component {record = action(async (query: string, signal: AbortSignal) => {await recordEventAsync(query, signal);});render() {return <button onClick={() => this.record("compiler framework")}>Record search</button>;}}The public action() overload removes the injected final signal from the event-call signature. Presolve creates and owns the AbortController at runtime.
Promise lifecycle
pagehide aborts pending work; cancellation is not reported as package failure.PSR_PACKAGE_INVOCATION_FAILURE.Server package capabilities
A package can also provide an executable Node loader or server action. These are not ordinary Action calls: the package must publish an integrity-qualified capability, and application source must select it through the corresponding canonical loader() or defineForm() shape.
resource + route_loaderExact (RouteParameters, AbortSignal) -> Promise<RouteLoaderResult>, server/shared boundary, reload resume, typed failure, result codecs, and explicit cache scope.server_actionExact (FormData, AbortSignal) -> Promise<ServerActionResult>, cold fallback, typed failure, and one JSON or redirect response family.For these uses, TypeScript proves the named export and exact signature, Presolve proves the component/Form/Resource/route ownership and publishes the closed execution plan, Vite bundles only that export for Node, and the generated host verifies the registry digest before import. Read loaders and server actions for the complete request, cache, cancellation, and bootstrap lifecycle.
What the build publishes
package-invocations.runtime.jsonExact argument codecs, completion, signal injection, concurrency, cancellation, execution, provenance, and restore-without-replay policy./presolve.package-invocations.jsVite-generated callable registry containing only authority-proven named exports.file-routes.manifest.jsonDigest-bound inventory for the invocation artifact and registry.Who diagnoses what?
| Question | Authority |
|---|---|
| Does the module exist, and what symbol/signature does this import mean? | TypeScript |
| Can the selected export bundle for the browser target? | Vite |
| Is the call shape admitted, and are its arguments and lifecycle exact? | Presolve |
| What does the implementation do internally? | The package; Presolve does not infer it. |
| Did an admitted invocation throw or reject? | Presolve records failure while retaining the package error. |
Historical package declarations
Earlier package declaration forms are documented only in the migration reference. Current applications use the Action forms above; integrations that return values, define codecs, render package components, or cross a server boundary require their own admitted capability product.
Verify an integration
pnpm checkpnpm buildpnpm exec presolve explain app/routes/index.tsxpnpm exec presolve explain --capabilities --format humanInspect the invocation artifact and registry, test fulfillment, failure, replacement, teardown, and resume in a real browser, and include the exact package/version plus diagnostic when reporting a bug.