Skip to content

Commit

Permalink
fix(runtime): port over Constants from snack-runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
byCedric committed Jan 4, 2024
1 parent fe16a23 commit 9bd90e7
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 42 deletions.
11 changes: 2 additions & 9 deletions runtime/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import './polyfill';

import AsyncStorage from '@react-native-async-storage/async-storage';
import Constants from 'expo-constants';
import { activateKeepAwake } from 'expo-keep-awake';
import { StatusBar } from 'expo-status-bar';
import * as Updates from 'expo-updates';
Expand All @@ -19,6 +18,7 @@ import { createVirtualModulePath } from 'snack-require-context';
import { AppLoading } from './AppLoading';
import BarCodeScannerView from './BarCodeScannerView';
import * as Console from './Console';
import { SNACK_API_URL } from './Constants';
import * as Errors from './Errors';
import * as Files from './Files';
import LoadingView from './LoadingView';
Expand All @@ -34,9 +34,6 @@ import * as Profiling from './Profiling';
import UpdateIndicator from './UpdateIndicator';
import { parseExperienceURL } from './UrlUtils';

const API_SERVER_URL_STAGING = 'https://staging.exp.host';
const API_SERVER_URL_PROD = 'https://exp.host';

type State = {
initialLoad: boolean;
initialURL: string;
Expand Down Expand Up @@ -316,11 +313,7 @@ export default class App extends React.Component<object, State> {
};

_uploadPreviewToS3 = async (asset: string, height: number, width: number) => {
const url = `${
Constants.manifest?.extra?.cloudEnv !== 'production'
? API_SERVER_URL_STAGING
: API_SERVER_URL_PROD
}/--/api/v2/snack/uploadPreview`;
const url = `${SNACK_API_URL}/--/api/v2/snack/uploadPreview`;
const body = JSON.stringify({ asset, height, width });
try {
Logger.info('Uploading preview...', 'width', width, 'height', height);
Expand Down
47 changes: 47 additions & 0 deletions runtime/src/Constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Constants from 'expo-constants';

/**
* The detected Snack environment based on the `manifest.extra.cloudEnv` setting.
* This defaults to `production` if not set.
*/
export const SNACK_ENVIRONMENT: 'staging' | 'production' =
(Constants.manifest as any)?.extra?.cloudEnv ?? 'production';

// Ensure the environment is valid
if (!['staging', 'production'].includes(SNACK_ENVIRONMENT)) {
throw new Error(
`Invalid Snack environment set through "manifest.extra.cloudEnv", must be "staging" or "production", received "${SNACK_ENVIRONMENT}".`,
);
}

/** Get the value based on the detected Snack environment. */
export function getSnackEnvironmentValue<T extends any>(
values: Record<typeof SNACK_ENVIRONMENT, T>,
): T {
return values[SNACK_ENVIRONMENT];
}

/** The Snack or Expo API endpoint. */
export const SNACK_API_URL = getSnackEnvironmentValue({
production: 'https://exp.host',
staging: 'https://staging.exp.host',
});

/**
* The Snackager Cloudfront endpoints to try before failing.
* Note, staging may fail randomly due to reduced capacity or general development work.
* Because of that, we try both staging and production before failing.
*/
export const SNACKAGER_API_URLS = getSnackEnvironmentValue({
production: ['https://d37p21p3n8r8ug.cloudfront.net'],
staging: [
'https://ductmb1crhe2d.cloudfront.net', // staging
'https://d37p21p3n8r8ug.cloudfront.net', // production
],
});

/** The SnackPub endpoint, used to establish socket connections with the Snack Website. */
export const SNACKPUB_URL = getSnackEnvironmentValue({
production: 'https://snackpub.expo.dev',
staging: 'https://staging-snackpub.expo.dev',
});
25 changes: 13 additions & 12 deletions runtime/src/LoadingView.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,18 @@ const styles = StyleSheet.create({
height: 100,
resizeMode: 'contain',
opacity: 0,
animationDelay: '2s',
animationDuration: '2s',
transitionTimingFunction: 'ease-out',
animationIterationCount: 'infinite',
animationKeyframes: [
{
'0%': { opacity: 0.1 },
'48%': { opacity: 0.5 },
'52%': { opacity: 0.5 },
'100%': { opacity: 0.1 },
},
],
// TODO: clean up unused animation properties
// animationDelay: '2s',
// animationDuration: '2s',
// transitionTimingFunction: 'ease-out',
// animationIterationCount: 'infinite',
// animationKeyframes: [
// {
// '0%': { opacity: 0.1 },
// '48%': { opacity: 0.5 },
// '52%': { opacity: 0.5 },
// '100%': { opacity: 0.1 },
// },
// ],
},
});
15 changes: 4 additions & 11 deletions runtime/src/Modules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import * as context from 'snack-require-context';
// web-assembly which is not yet supported on react-native.
import { SourceMapConsumer, RawSourceMap } from 'source-map';

import { SNACKAGER_API_URLS } from './Constants';
import * as Files from './Files';
import * as Logger from './Logger';
import AssetRegistry from './NativeModules/AssetRegistry';
Expand All @@ -43,9 +44,6 @@ type Load = {
};
};

const SNACKAGER_CDN_STAGING = 'https://ductmb1crhe2d.cloudfront.net';
const SNACKAGER_CDN_PROD = 'https://d37p21p3n8r8ug.cloudfront.net';

// This is super hacky
// This avoids a bug where for some reason `react` is `undefined` in a dependency
// Adding the __esModule property basically bypasses the extra defineProperty stuff that webpack does
Expand Down Expand Up @@ -78,7 +76,7 @@ global['__DEV__'] = false;
// See https://github.com/expo/universe/blob/64a2eab474d11614c5b403f09747fdb112769a39/libraries/snack-sdk/src/types.js#L114-L126.

const manifest = Constants.manifest;
let projectDependencies: Dependencies = manifest?.extra?.dependencies ?? {};
let projectDependencies: Dependencies = (manifest as any)?.extra?.dependencies ?? {};

// This keeps track of all generated virutal modules, and the files it includes.
// Unfortunately, asking SystemJS seems to return no loaded modules.
Expand Down Expand Up @@ -311,12 +309,7 @@ const fetchPipeline = async (load: Load) => {
`from cache ${bundle ? bundle.length : undefined} bytes`,
);
} else {
// In development, try fetching from staging cloudfront first
const cloudFrontUrls =
Constants.manifest?.extra?.cloudEnv !== 'production'
? [SNACKAGER_CDN_STAGING, SNACKAGER_CDN_PROD]
: [SNACKAGER_CDN_PROD];
for (const url of cloudFrontUrls) {
for (const [urlIndex, url] of SNACKAGER_API_URLS.entries()) {
const fetchFrom = `${url}/${handle}-${Platform.OS}/bundle.js`;

try {
Expand All @@ -330,7 +323,7 @@ const fetchPipeline = async (load: Load) => {
throw new Error(`Request failed with status ${res.status}: ${res.statusText}`);
}
} catch (e) {
if (url !== SNACKAGER_CDN_STAGING) {
if (urlIndex < SNACKAGER_API_URLS.length - 1) {
Logger.error('Error fetching bundle', fetchFrom, e);
throw e;
} else {
Expand Down
1 change: 0 additions & 1 deletion runtime/src/NativeModules/ExpoRouterEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ type ExpoRouterAppProps = {
*/
export function ExpoRouterApp({ ctx }: ExpoRouterAppProps) {
return (
// @ts-expect-error Property 'context' is missing in type '{ children: Element; }' but required in type '{ children?: ReactNode; context: any; }'.
<Head.Provider>
<ExpoRoot context={ctx} />
</Head.Provider>
Expand Down
11 changes: 2 additions & 9 deletions runtime/src/transports/RuntimeTransportImplSocketIO.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import Constants from 'expo-constants';
import { io } from 'socket.io-client';
import type { Socket } from 'socket.io-client';

import type { Device, RuntimeMessagePayload, RuntimeTransport } from './RuntimeTransport';
import { SNACKPUB_URL } from '../Constants';
import * as Logger from '../Logger';

const SNACKPUB_URL_STAGING = 'https://staging-snackpub.expo.dev';
const SNACKPUB_URL_PRODUCTION = 'https://snackpub.expo.dev';

interface ServerToClientEvents {
message: (data: { channel: string; sender: string } & RuntimeMessagePayload) => void;
joinChannel: (data: { channel: string; sender: string }) => void;
Expand All @@ -30,11 +27,7 @@ export default class RuntimeTransportImplSocketIO implements RuntimeTransport {
constructor(device: Device) {
this.device = device;
this.sender = JSON.stringify(device);
const snackpubURL =
Constants.manifest?.extra?.cloudEnv !== 'production'
? SNACKPUB_URL_STAGING
: SNACKPUB_URL_PRODUCTION;
this.socket = io(snackpubURL, { transports: ['websocket'] });
this.socket = io(SNACKPUB_URL, { transports: ['websocket'] });
this.socket.on('terminate', (reason) => {
Logger.comm(`Terminating connection: ${reason}`);
this.socket.disconnect();
Expand Down

0 comments on commit 9bd90e7

Please sign in to comment.