npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@tiledev/sdk-apptile-live-selling-native

v0.1.1

Published

The native half of Apptile live selling: the LivePip Expo module (system picture-in-picture over a Zego stream) and the config plugin that writes the native entries prebuild regenerates. Split out of @tiledev/sdk-apptile-live-selling so a JS-only release

Readme

@tiledev/sdk-apptile-live-selling-native

The native half of Apptile live selling: the LivePip Expo module — system picture-in-picture fed from a Zego stream — and the config plugin that writes the native entries expo prebuild regenerates.

You do not talk to this package directly — you use @tiledev/sdk-apptile-live-selling, which depends on it and re-exports the two things it exposes. But you do have to install it, and name its plugin in app.json.

npm i @tiledev/sdk-apptile-live-selling @tiledev/sdk-apptile-live-selling-native

Why list it when the JS package already depends on it. In a tree that contains expo and react-native, npm nests this package at node_modules/@tiledev/sdk-apptile-live-selling/node_modules/… rather than hoisting it. Expo's autolinking finds it there fine — but its config-plugin resolver resolves plugin names from the project root only, so expo prebuild fails with PluginError: Failed to resolve plugin for module "@tiledev/sdk-apptile-live-selling-native". A direct entry is what hoists it.

Pin it to exactly the version the JS package's dependencies names — never a different one, or npm keeps two copies of this Expo module and the identical pod and module names collide at link time:

"@tiledev/sdk-apptile-live-selling": "^0.3.0",
"@tiledev/sdk-apptile-live-selling-native": "0.1.0"

Why this is a package of its own

Everything in here lands in the OTA fingerprint, and nothing in the JS package does.

Expo autolinks any package carrying an expo-module.config.json and records its packageVersion in expoAutolinkingConfig:ios / :android — one of the content sources fingerprint.json hashes. So any version bump of an autolinked package moves the fingerprint and needs a fresh binary in the stores, even a release that touched nothing but JavaScript. Before the split that applied to the whole SDK: a one-line JS fix meant a new build, a review and a staged rollout.

Now the line is drawn where it actually is. This package moves when the Swift, the Kotlin, the podspec or the plugin change — and then a new binary is the honest answer anyway. The JS package is not autolinked, so its version is not hashed and a release of it ships over the air.

The JS package pins this one exactly, so its own version is the only thing that can move this one. A patch of it is JavaScript alone and ships over the air; a minor means this package moved with it, a new binary is required, and the pin above wants updating in the same commit. That is the whole contract — the release procedure maintaining it is in the JS package's README.

The config plugin

Every native entry live selling needs lives in a file expo prebuild regenerates, so it has to be a plugin: an edit by hand works on the machine that made it and silently stops working in CI.

{
  "expo": {
    "plugins": [
      ["@tiledev/sdk-apptile-live-selling-native", {
        "cameraPermission": "Used to appear on camera when you co-host a live show."
      }]
    ]
  }
}

| Prop | Default | What it writes | |---|---|---| | pip | true | android:supportsPictureInPicture, the configChanges a PIP resize needs, UIBackgroundModes: ["audio"] | | cameraPermission / microphonePermission | generic copy | NSCameraUsageDescription / NSMicrophoneUsageDescription — never overwrites strings your app already sets | | capturePermissions | true | Android CAMERA + RECORD_AUDIO |

Zego's own Maven repo is added unconditionally: im.zego:express-video lives only there, and a clean Android checkout fails at configuration time without it.

Then npx expo prebuild and run the app. The LivePip module autolinks itself.

If your app already vendors a live-pip module, delete it — identical module and pod names collide at link time.

The marker the plugin writes into android/build.gradle still reads @generated by @tiledev/sdk-apptile-live-selling, and it has to. The plugin reads that string back to stay idempotent, so a project prebuilt before the split carries the old one; renaming it would make the plugin fail to recognise its own block and append a second allprojects clause.

What it exports

import { livePip, isLivePipSupported } from '@tiledev/sdk-apptile-live-selling-native';

isLivePipSupported says the module is in the binary — not that the device will grant a window. An Android handset can ship without the picture-in-picture feature and the user can revoke the permission in settings; both surface as onPipError, because neither can be known until a window is asked for.

livePip is the boundary itself: configure, setStream, setArmed, start, stop, addListener. The live session drives all of it, so an app rarely calls it directly.

Two files, and Metro picks by platform: pip.native.ts is the real module, pip.ts is a no-op with isLivePipSupported: false. TypeScript resolves the non-native one, which is why a consumer's tsc --noEmit never needs expo installed.

Picture-in-picture, in two stages

actions.enterPip() on the live session shrinks to a surface your app draws. The session arms the OS handover in advance, so minimising the app opens a real system window with no JavaScript involved at that moment — which is the only way it can work, since JS is suspended by then. Coming back raises onPipRestore.

On iOS the window is an AVPictureInPictureController fed Zego's custom-render frames, which is why UIBackgroundModes: ["audio"] is load-bearing: without it iOS suspends the app and the window freezes on its last frame within seconds. On Android there is no frame copy — the activity itself enters PIP, which is why android:configChanges must include smallestScreenSize. Entering PIP is exactly a change of smallest width, and without it the activity is recreated rather than resized: the React host restarts on the way in, the stream drops, and the window shows a fresh launch.

Scripts

| Command | What it does | |---|---| | npm run build | Cleans, compiles src → dist and plugin/src → plugin/build. Both are needed: app.plugin.js loads the compiled plugin so consumers never need TypeScript at prebuild | | npm run lint | Typechecks both projects, emitting nothing | | npm run clean | Removes dist and plugin/build | | npm pack | The publish tarball — use it to verify dist, ios/, android/, expo-module.config.json, app.plugin.js and plugin/build all ship |