npm.io
0.24.1 • Published 2 weeks ago

@lwrjs/gate-module-provider

Licence
MIT
Version
0.24.1
Deps
2
Size
24 kB
Vulns
0
Weekly
0

@lwrjs/gate-module-provider

A module provider for LWR that exposes @salesforce/gate for feature gating. Use it to control feature rollouts, experiment toggles, and gradual releases within your LWC modules.

Overview

The gate module provider resolves imports like @salesforce/gate/<gateName> into virtual modules that expose a standard API: isOpen(map) and hasError(). Each gate is resolved at build/runtime from a configurable source—by default, a gates.json file in your project.

Installation

The provider is included in the default LWR config. To customize it, add it to moduleProviders in your lwr.config.json:

{
    "moduleProviders": [
        [
            "@lwrjs/gate-module-provider",
            {
                "gateConfigPath": "$rootDir/src/gates.json"
            }
        ]
    ]
}
Options
Option Type Default Description
gateConfigPath string $rootDir/src/gates.json Path to your gates config file. Supports $rootDir placeholder.
resolver GateResolver — Custom resolver function. Overrides gateConfigPath when provided. Use for container-specific resolution (e.g., Core, metadata).

gates.json Format

Create a gates.json file (typically in src/) with an array of gate entries:

[
    {
        "name": "myFeatureGate",
        "enabled": true,
        "description": "Controls access to the new feature"
    },
    {
        "name": "experimentPreview",
        "enabled": false,
        "description": "Preview mode for A/B test"
    }
]
Gate Entry Fields
Field Type Required Description
name string Yes Gate identifier. Must match the specifier (e.g. myFeatureGate → @salesforce/gate/myFeatureGate).
enabled boolean Yes Open/closed state.
description string No Human-readable description.

Gate names may use alphanumeric characters, dots, underscores, and hyphens (e.g. myFeatureGate, namespace.gateName).

Unknown Gates

If a gate name is not found in gates.json, the resolver returns { isOpen: false, hasError: false }. Unknown gates are indistinguishable from known closed gates—both resolve as closed with no error. Ensure gate names in your imports match the name field in gates.json exactly.

Client API

Each gate module exports two functions:

isOpen(map)

Returns whether the gate is open.

  • Resolved: Returns true or false based on the gate config.
  • Error: Returns map.fallback when hasError() is true. If map is undefined or lacks fallback, returns false.
  • Defensive: Safe to call isOpen() with no args; returns false when resolution failed and no fallback was provided.
isOpen({ fallback: false }); // Use false when resolution fails
isOpen({ fallback: true }); // Use true when resolution fails (opt-in to feature on error)
isOpen(); // Safe: returns false when hasError() and no fallback provided
hasError()

Returns true when gate resolution failed (e.g. config missing, network error). Use this to handle error states explicitly.

Usage in LWC Modules

Basic Gating
// myComponent.ts
import { LightningElement } from 'lwc';
import { isOpen, hasError } from '@salesforce/gate/myFeatureGate';

export default class MyComponent extends LightningElement {
    get featureEnabled(): boolean {
        return isOpen({ fallback: false });
    }

    get showError(): boolean {
        return hasError();
    }
}
<!-- myComponent.html -->
<template>
    <template lwc:if="{showError}">
        <p class="error">Unable to check feature availability.</p>
    </template>
    <template lwc:elseif="{featureEnabled}">
        <p>New feature content</p>
    </template>
    <template lwc:else>
        <p>Feature not available</p>
    </template>
</template>
Conditional Rendering
import { isOpen } from '@salesforce/gate/experimentPreview';

export default class Dashboard extends LightningElement {
    get showNewDashboard(): boolean {
        return isOpen({ fallback: false });
    }
}
Safe Defaults

When resolution fails, isOpen returns your fallback value. Choose based on your use case:

  • fallback: false — Feature off when resolution fails (safer for new features).
  • fallback: true — Feature on when resolution fails (use when the gate protects removal of legacy behavior).

TypeScript Support

Add a declaration file (e.g. src/types/scoped-modules.d.ts) so TypeScript recognizes the gate imports:

declare module '@salesforce/gate/*' {
    export function isOpen(map: { fallback?: boolean }): boolean;
    export function hasError(): boolean;
    const gate: { isOpen: (map: { fallback?: boolean }) => boolean; hasError: () => boolean };
    export default gate;
}

Custom Resolver

For container-specific resolution (e.g. Core Gater, metadata), provide a custom resolver:

import type { GateResolver } from '@lwrjs/gate-module-provider';

const myResolver: GateResolver = async (gateName, runtimeParams) => {
    // Resolve from Core, metadata API, etc.
    const enabled = await fetchGateState(gateName);
    return { isOpen: enabled, hasError: false };
};

// In lwr.config.json moduleProviders:
// ["@lwrjs/gate-module-provider", { resolver: myResolver }]

The resolver receives (gateName: string, runtimeParams: RuntimeParams) and returns { isOpen: boolean, hasError?: boolean } (or a Promise of that).

Static Builds (MRT)

Gate modules are compiled into static bundles at build time. The gate provider and gates.json are not required in the SSR lambda runtime; resolution happens during the build.

gates.json Caching (Dev Mode)

The JSON resolver caches the parsed gates.json for the lifetime of the process. When editing gates.json during development, restart the dev server for changes to take effect. Resolution is effectively build-time for both dev and production.