@palgroup/simstream
v0.8.0
Published
Start and drive remote iOS simulator sessions.
Maintainers
Readme
@palgroup/simstream
Start and drive remote iOS simulator sessions.
npm install @palgroup/simstreamimport { SimStream, SimStreamError } from '@palgroup/simstream';
const sim = new SimStream({
baseUrl: process.env.SIMSTREAM_URL!, // the coordinator
apiKey: process.env.SIMSTREAM_KEY!, // your customer key
});
// A simulator, and your app installed onto it in parallel. The answer comes back before the
// download starts: the device is already booted and waiting, and making somebody watch a
// download undoes the reason it was.
const session = await sim.startSession({
app: 'https://your-bucket/App.zip', // a .app, zipped. Simulator builds, not .ipa.
wait: true, // queue instead of failing when the fleet is busy
onQueue: (position) => console.log(`waiting, ${position} ahead`),
});
// Open it. That is the whole client — a page that streams the simulator and sends touches
// back. Treat the URL like a password: it carries a grant scoped to one device.
console.log(session.url);A new build lands
Somebody is already looking at a simulator and their app should be replaced under them, without reconnecting:
await sim.pushBuild('https://your-bucket/App.zip');It goes only to hosts holding your sessions.
When there is nothing free
startSession() throws a SimStreamError. The code says what to do about it:
| code | meaning | what to do |
|---|---|---|
| quota | you are at your own concurrent limit | wait, or raise the limit |
| capacity | the whole fleet is busy | pass wait: true |
| unauthorized | the key is not recognised | check apiKey |
| timeout | timeoutMs elapsed while queued | the ticket is gone; ask again |
| gone | the ticket was already collected, or abandoned | ask again |
With wait: true the client keeps its place and honours the server's own retry-after
rather than choosing an interval — the server is the one that knows how fast the queue is
moving. pollTicket() is there if you would rather drive the waiting yourself.
What you used
await sim.usage();
// [{ customer: 'palcore', sessions: 12, seconds: 4210, live: 2 }]Sessions running right now are counted at their length so far. It is a measurement, not an invoice: what a second is worth is not a decision this system makes.
Notes
Needs fetch — Node 18+, or pass your own in the options. No other dependencies.
The full HTTP surface is in docs/api.md; this package is only the part that is easy to get
subtly wrong: waiting without hammering, telling "still waiting" apart from "gone", and not
mistaking a viewer link for something you can log.
