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 🙏

© 2024 – Pkg Stats / Ryan Hefner

nikki-snack-sdk

v3.0.0-rc.0

Published

The Expo Snack SDK

Downloads

5

Readme

Snack SDK

The Expo Snack SDK. Use this to create a custom web interface for https://snack.expo.io/.

If you have problems with the code in this repository, please file issues & bug reports at https://github.com/expo/expo. Thanks!

Documentation

User Guide

Creating a new session

import { SnackSession } from 'snack-sdk';

let session = new SnackSession({
  files?: ExpoSnackFiles,
  sdkVersion?: SDKVersion,
  sessionId?: string,
  verbose?: boolean,
});

await session.startAsync();

files is a map of all of the files included in the project. The filenames should be the full path from the project root.

sdkVersion determines what version of React Native is used on the mobile client. Defaults to 15.0.0 which maps to React Native 0.42.0. If you specify a different version, make sure to save that version along with the code. Code from one SDK version is not guaranteed to work on others. To use multiple files, you must use SDK 21 or above.

sessionId can be specified if you want a consistent url. This is a global namespace so make sure to use a UUID or scope it somehow if you use this.

Getting the URL for the mobile client

let url = await session.getUrlAsync();

This url will open the current Snack Session in the Expo client when opened on a phone. You can create a QR code from this link or send it to the phone in another way. See example/ for how to turn this into a QR code.

Updating the code

const files = {
	'app.js': { contents: 'code here, this is entry point', type: 'CODE'},
	'folder/file.js': { contents: 'this file is in /folder', type: 'CODE'},
	'image.png': { content: 'remote location of asset', type: 'ASSET'},
}
await session.sendCodeAsync(files: Object);

This will push the new code to each connected mobile client. Any new clients that connect will also get the new code.

For SDK 21 and above, you can have multiple files in a Snack. This includes support for folders and relative path imports. See the example above on sending data. The entry point for running a Snack is app.js, which is required to be included in any project provided to the SnackSession constructor or sendCodeAsync calls.

You'll also be able to send Assets (images, fonts, etc.). To do this include the asset in the files object, with key being file name and value being the remote location where this asset is stored.

Uploading assets

const remoteAddressOfAssetFile = await session.uploadAssetAsync(file);

where file is a Javascript File object.

Arbitary NPM Modules

When using Expo SDK 19 and above, you'll be able to use arbitary NPM modules with your app. Simply import or require them just like you will on desktop and we'll handle the rest (installing the modules and bundling it with project).

SnackSession will append a comment to each line inticating the version that will be used, or an error message if the requested import could not be found. You are encouraged to make this information available to your users in the interface.

Example:

import lodash from 'lodash';

Saving the code to Expo's servers

let saveResult = await session.saveAsync();

console.log(saveResult);
// This will print: `{"id":"abc123","url":"https://expo.io/@snack/abc123"}`

This will upload the current code to Expo's servers and return a url that points to that version of the code.

Downloading Code

const downloadURL = await session.downloadAsync();

console.log(downloadURL);
// This will print: { url: "https://expo.io/--/api/v2/snack/download/snackIDHere" }

This will return a link to our server with a .zip of your Snack project. You'll be able to run this exported project using exp or XDE.

Listening for events

Here are the Flow types for the error, log, and presence listeners:

type SnackSession = {
  addErrorListener: (listener: ExpoErrorListener) => ExpoSubscription,
  addLogListener: (listener: ExpoLogListener) => ExpoSubscription,
  addPresenceListener: (listener: ExpoPresenceListener) => ExpoSubscription,
};

type ExpoSubscription = {
  remove: () => void,
};

// Called with empty array if errors have been resolved
type ExpoErrorListener = (errors: Array<ExpoError>) => void;

type ExpoLogListener = (log: ExpoDeviceLog) => void;

type ExpoPresenceListener = (event: ExpoPresenceEvent) => void;

type ExpoError = {
  device?: ExpoDevice,
  startLine?: number,
  endLine?: number,
  startColumn?: number,
  endColumn?: number,
  message: string,
  stack?: string,
};

// `console.log`, `console.warn`, `console.error`
type ExpoDeviceLog = {
  device: ExpoDevice,
  method: 'log' | 'warn' | 'error',
  message: string,
  arguments: any, // the raw fields that were passed to the console.* call
};

type ExpoDevice = {
  name: string,
  id: string,
};

type ExpoPresenceStatus = 'join' | 'leave';

type ExpoPresenceEvent = {
  device: ExpoDevice,
  status: ExpoPresenceStatus,
};

Each of these listeners is optional. Here's an example of using a log listener:

let logSubscription = session.addLogListener((log) => {
  console.log(JSON.stringify(log));

  // This will print: `{"device":{"id":"b9384faf-504f-4c41-a7ab-6344f0102456","name":"SM-G930U"},"method":"log","message":"hello!","arguments":["hello!"]}`
  // on the web if `console.log('hello!')` is run from the code on the phone.
});

// later on...
logSubscription.remove();
// future `console.log`s on the phone will not trigger the listener

An error listener:

let errorSubscription = session.addErrorListener((error) => {
  console.log(JSON.stringify(error));

  // This will print:
  // `[]`
  // when there is no error and
  // `[{"message":"unknown: Unexpected token (7:7)...","endLine":7,"startLine":7,"endColumn":7,"startColumn":7}]`
  // when there is an error. The `message` field is truncated in this document.
});

// later on...
errorSubscription.remove();

A presence listener:

let presenceSubscription = session.addPresenceListener((presence) => {
  console.log(JSON.stringify(presence));

  // This will print:
  // `{"device":{"id":"b9384faf-504f-4c41-a7ab-6344f0102456","name":"SM-G930U"},"status":"join"}`
  // when a device is connected and
  // `{"device":{"id":"b9384faf-504f-4c41-a7ab-6344f0102456","name":"SM-G930U"},"status":"leave"}`
  // when a device disconnects.
});

// later on...
presenceSubscription.remove();

Please read the Flow types above for all possible fields returned in these listeners.

Stopping the session

await session.stopAsync();

This will shut down the PunNub connection.