defineDevstackWith
Callback-form composer that threads a resolved-narrow NetworkConfig through a BuildCtx so mode-narrowed plugin factories type-check at the call site.
defineDevstackWith is the callback-form devstack composer. Use it instead of defineDevstack when
one or more plugin factories need mode-narrowing — sui() in live mode, walrusFor(...),
sealFor(...), and similar mode-narrowed namespaces only expose their per-mode call shape when the
resolved network is known at composition time.
import { chainId, defineDevstackWith, suiFor } from '@mysten-incubation/devstack';
export default defineDevstackWith(
{
network: { mode: 'live', chain: chainId('sui:testnet') },
stackName: 'main',
},
({ network }) => {
const liveSui = suiFor(network).testnet();
return [liveSui];
},
);Signature
function defineDevstackWith<Mode extends NetworkMode, Members extends ReadonlyArray<AnyPlugin>>(
options: DevstackOptionsWith<Mode>,
build: (ctx: BuildCtx<Mode>) => Members,
): Stack<ComposedMembers<Members>>;options— the same options bagdefineDevstackaccepts, plus a requirednetworkfield carrying the resolved-narrowNetworkConfig<Mode>.build— a callback that receives aBuildCtx<Mode>and returns the member tuple.
The stateDir field on this options bag is now honored as of 0.1.0 — runStack resolves it as the
state-directory source when no runtimeRoot and no --state-dir flag are supplied. In earlier
releases it was declared but silently ignored.
BuildCtx
interface BuildCtx<Mode extends NetworkMode> {
readonly network: NetworkConfig<Mode>;
}The Mode generic is inferred from options.network.mode and carried through BuildCtx. Plugin
factories that accept (network) recover the discriminator structurally — the compiler refuses
illegal-mode factory access at the call site, before the stack runs.
Validation
defineDevstackWith runs the same composition-time checks as defineDevstack:
- The returned member array is recursively expanded so plugin-valued dependencies are included before missing-provider checks. Bare resource dependencies still require an explicit provider in the returned tuple.
- A
MissingProviders<...>branded error surfaces at the call site if any plugin'sdependsOnreference is not provided by the tuple. - A defensive runtime check verifies every element returned by the builder carries the plugin brand.
If you reach for
as unknown as AnyPluginand skipdefinePlugin, the composer throws immediately with a clear message.
When to use which composer
defineDevstack({ members: [...] })— flat form. No mode-narrowed factories; the simplest path for localnet-only stacks.defineDevstackWith({ network, ... }, ({ network }) => [...])— callback form. The canonical surface when one or more plugins narrow on the resolved network mode (live, fork).
The two return the same Stack<...> shape and are consumed identically by runStack,
devstack up, and the build-integration subpaths.