Skip to content

Latest commit

 

History

History
109 lines (88 loc) · 3.94 KB

README.md

File metadata and controls

109 lines (88 loc) · 3.94 KB

Bundle Pilot

Bundle Pilot SDK

Client packages that run each visitor on the frontend bundle the Bundle Pilot gateway picks,
on the web and in native apps.

@bundle-pilot/core on npm @bundle-pilot/angular on npm @bundle-pilot/capacitor on npm TypeScript


Packages

Package For Size (min+gzip)
@bundle-pilot/angular Angular 18 to 22: one provideBundlePilot() guards every route 0.5 kB + core
@bundle-pilot/core Any framework or none: createPilot().check(facts) 1.1 kB, no dependencies
@bundle-pilot/capacitor Capacitor 8 apps: signed over-the-air updates with Capgo 1.9 kB + core

Which one do I need?

flowchart LR
    A{Where does the app run?} -->|browser| B{Angular?}
    A -->|Capacitor app| C["@bundle-pilot/capacitor<br>+ @bundle-pilot/angular, or core"]
    B -->|yes| D["@bundle-pilot/angular"]
    B -->|no| E["@bundle-pilot/core"]
Loading
  • An Angular web app: @bundle-pilot/angular. That is one provider and nothing else.
  • React, Vue, Svelte or plain JavaScript: @bundle-pilot/core. Call check from your router's guard or hook.
  • A Capacitor app: @bundle-pilot/capacitor. With Angular, pass its pilot to provideBundlePilot, so the web build and the native app share the same code.

In 30 seconds

// Angular, web
provideBundlePilot({
  facts: () => {
    const store = inject(StoreService);
    return store.id ? { storeID: store.id, backend: store.posVersion } : null;
  },
});
// Angular, Capacitor: the same provider, with the over-the-air pilot
provideBundlePilot({
  facts,
  pilot: () => createOtaPilot({ gateway: 'https://ota.example.com', publicKey, version }),
});
// Any framework
const pilot = createPilot();
router.beforeEach((to) => pilot.check(currentFacts(), router.resolve(to).href));

How it fits together

sequenceDiagram
    participant App as App (any package)
    participant GW as Bundle Pilot gateway
    App->>GW: POST /__gateway/data { storeID, backend, native? }
    GW-->>App: { bundle: "4.80.0", via: "rule:pilot-stores" }
    alt bundle is the one running
        App->>App: go on (and answer at once next time)
    else web: another bundle
        App->>GW: location.replace(url?ngsw-bypass=4.80.0)
        GW-->>App: index.html of 4.80.0
    else native: another bundle
        App->>GW: GET bundle.sha256 + .sig, then the files
        App->>App: verify Ed25519, install with Capgo, restart
    end
Loading

Your app sends facts, and the gateway's rules decide. You pilot a build with some stores, raise a percentage, or back out of a release from the admin UI, with no new deploy of the app.

Versioning

All packages are released together with the gateway, from one vX.Y.Z tag, so @bundle-pilot/* 1.4.0 goes with gateway 1.4.0. The 0.0.0 in each package.json is a placeholder that the release replaces: don't bump it by hand.

Development

pnpm install
pnpm build   # tsc, every package (core first)
pnpm test    # node --test

Each package's README is the page npm shows. Keep its links and images absolute.