@expo/cli 0.2.11 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bin/cli +2 -2
- package/build/src/start/interface/interactiveActions.js +9 -4
- package/build/src/start/interface/interactiveActions.js.map +1 -1
- package/build/src/start/platforms/PlatformManager.js +29 -4
- package/build/src/start/platforms/PlatformManager.js.map +1 -1
- package/build/src/start/platforms/android/AndroidPlatformManager.js.map +1 -1
- package/build/src/start/platforms/ios/ApplePlatformManager.js.map +1 -1
- package/build/src/start/server/BundlerDevServer.js +17 -16
- package/build/src/start/server/BundlerDevServer.js.map +1 -1
- package/build/src/start/server/UrlCreator.js +12 -3
- package/build/src/start/server/UrlCreator.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +7 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +5 -0
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/metro/router.js +35 -0
- package/build/src/start/server/metro/router.js.map +1 -0
- package/build/src/start/server/metro/withMetroMultiPlatform.js +2 -1
- package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
- package/build/src/start/server/middleware/ClassicManifestMiddleware.js +1 -1
- package/build/src/start/server/middleware/CreateFileMiddleware.js +103 -0
- package/build/src/start/server/middleware/CreateFileMiddleware.js.map +1 -0
- package/build/src/start/server/middleware/InterstitialPageMiddleware.js +25 -16
- package/build/src/start/server/middleware/InterstitialPageMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/RuntimeRedirectMiddleware.js +2 -1
- package/build/src/start/server/middleware/RuntimeRedirectMiddleware.js.map +1 -1
- package/build/src/start/server/middleware/resolvePlatform.js +14 -0
- package/build/src/start/server/middleware/resolvePlatform.js.map +1 -1
- package/build/src/utils/analytics/rudderstackClient.js +2 -2
- package/build/src/utils/env.js +2 -2
- package/build/src/utils/env.js.map +1 -1
- package/package.json +3 -3
- package/static/loading-page/index.html +99 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/metro/MetroBundlerDevServer.ts"],"sourcesContent":["import { prependMiddleware } from '@expo/dev-server';\n\nimport { getFreePortAsync } from '../../../utils/port';\nimport { BundlerDevServer, BundlerStartOptions, DevServerInstance } from '../BundlerDevServer';\nimport { HistoryFallbackMiddleware } from '../middleware/HistoryFallbackMiddleware';\nimport { InterstitialPageMiddleware } from '../middleware/InterstitialPageMiddleware';\nimport { RuntimeRedirectMiddleware } from '../middleware/RuntimeRedirectMiddleware';\nimport { ServeStaticMiddleware } from '../middleware/ServeStaticMiddleware';\nimport { instantiateMetroAsync } from './instantiateMetro';\n\n/** Default port to use for apps running in Expo Go. */\nconst EXPO_GO_METRO_PORT = 19000;\n\n/** Default port to use for apps that run in standard React Native projects or Expo Dev Clients. */\nconst DEV_CLIENT_METRO_PORT = 8081;\n\nexport class MetroBundlerDevServer extends BundlerDevServer {\n get name(): string {\n return 'metro';\n }\n\n async resolvePortAsync(options: Partial<BundlerStartOptions> = {}): Promise<number> {\n const port =\n // If the manually defined port is busy then an error should be thrown...\n options.port ??\n // Otherwise use the default port based on the runtime target.\n (options.devClient\n ? // Don't check if the port is busy if we're using the dev client since most clients are hardcoded to 8081.\n Number(process.env.RCT_METRO_PORT) || DEV_CLIENT_METRO_PORT\n : // Otherwise (running in Expo Go) use a free port that falls back on the classic 19000 port.\n await getFreePortAsync(EXPO_GO_METRO_PORT));\n\n return port;\n }\n\n protected async startImplementationAsync(\n options: BundlerStartOptions\n ): Promise<DevServerInstance> {\n options.port = await this.resolvePortAsync(options);\n this.urlCreator = this.getUrlCreator(options);\n\n const parsedOptions = {\n port: options.port,\n maxWorkers: options.maxWorkers,\n resetCache: options.resetDevServer,\n\n // Use the unversioned metro config.\n // TODO: Deprecate this property when expo-cli goes away.\n unversioned: false,\n };\n\n const { server, middleware, messageSocket } = await instantiateMetroAsync(\n this.projectRoot,\n parsedOptions\n );\n\n const manifestMiddleware = await this.getManifestMiddlewareAsync(options);\n\n // We need the manifest handler to be the first middleware to run so our\n // routes take precedence over static files. For example, the manifest is\n // served from '/' and if the user has an index.html file in their project\n // then the manifest handler will never run, the static middleware will run\n // and serve index.html instead of the manifest.\n // https://github.com/expo/expo/issues/13114\n prependMiddleware(middleware, manifestMiddleware);\n\n middleware.use(new InterstitialPageMiddleware(this.projectRoot).getHandler());\n\n const deepLinkMiddleware = new RuntimeRedirectMiddleware(this.projectRoot, {\n onDeepLink: ({ runtime }) => {\n // eslint-disable-next-line no-useless-return\n if (runtime === 'expo') return;\n // TODO: Some heavy analytics...\n },\n getLocation: ({ runtime }) => {\n if (runtime === 'custom') {\n return this.urlCreator?.constructDevClientUrl();\n } else {\n return this.urlCreator?.constructUrl({\n scheme: 'exp',\n });\n }\n },\n });\n middleware.use(deepLinkMiddleware.getHandler());\n\n // Append support for redirecting unhandled requests to the index.html page on web.\n if (this.isTargetingWeb()) {\n // This MUST be after the manifest middleware so it doesn't have a chance to serve the template `public/index.html`.\n middleware.use(new ServeStaticMiddleware(this.projectRoot).getHandler());\n\n // This MUST run last since it's the fallback.\n middleware.use(new HistoryFallbackMiddleware(manifestMiddleware.internal).getHandler());\n }\n // Extend the close method to ensure that we clean up the local info.\n const originalClose = server.close.bind(server);\n\n server.close = (callback?: (err?: Error) => void) => {\n return originalClose((err?: Error) => {\n this.instance = null;\n callback?.(err);\n });\n };\n\n return {\n server,\n location: {\n // The port is the main thing we want to send back.\n port: options.port,\n // localhost isn't always correct.\n host: 'localhost',\n // http is the only supported protocol on native.\n url: `http://localhost:${options.port}`,\n protocol: 'http',\n },\n middleware,\n messageSocket,\n };\n }\n\n protected getConfigModuleIds(): string[] {\n return ['./metro.config.js', './metro.config.json', './rn-cli.config.js'];\n }\n}\n"],"names":["EXPO_GO_METRO_PORT","DEV_CLIENT_METRO_PORT","MetroBundlerDevServer","BundlerDevServer","name","resolvePortAsync","options","port","devClient","Number","process","env","RCT_METRO_PORT","getFreePortAsync","startImplementationAsync","urlCreator","getUrlCreator","parsedOptions","maxWorkers","resetCache","resetDevServer","unversioned","server","middleware","messageSocket","instantiateMetroAsync","projectRoot","manifestMiddleware","getManifestMiddlewareAsync","prependMiddleware","use","InterstitialPageMiddleware","getHandler","deepLinkMiddleware","RuntimeRedirectMiddleware","onDeepLink","runtime","getLocation","constructDevClientUrl","constructUrl","
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/metro/MetroBundlerDevServer.ts"],"sourcesContent":["import { prependMiddleware } from '@expo/dev-server';\n\nimport { getFreePortAsync } from '../../../utils/port';\nimport { BundlerDevServer, BundlerStartOptions, DevServerInstance } from '../BundlerDevServer';\nimport { CreateFileMiddleware } from '../middleware/CreateFileMiddleware';\nimport { HistoryFallbackMiddleware } from '../middleware/HistoryFallbackMiddleware';\nimport { InterstitialPageMiddleware } from '../middleware/InterstitialPageMiddleware';\nimport { RuntimeRedirectMiddleware } from '../middleware/RuntimeRedirectMiddleware';\nimport { ServeStaticMiddleware } from '../middleware/ServeStaticMiddleware';\nimport { instantiateMetroAsync } from './instantiateMetro';\n\n/** Default port to use for apps running in Expo Go. */\nconst EXPO_GO_METRO_PORT = 19000;\n\n/** Default port to use for apps that run in standard React Native projects or Expo Dev Clients. */\nconst DEV_CLIENT_METRO_PORT = 8081;\n\nexport class MetroBundlerDevServer extends BundlerDevServer {\n get name(): string {\n return 'metro';\n }\n\n async resolvePortAsync(options: Partial<BundlerStartOptions> = {}): Promise<number> {\n const port =\n // If the manually defined port is busy then an error should be thrown...\n options.port ??\n // Otherwise use the default port based on the runtime target.\n (options.devClient\n ? // Don't check if the port is busy if we're using the dev client since most clients are hardcoded to 8081.\n Number(process.env.RCT_METRO_PORT) || DEV_CLIENT_METRO_PORT\n : // Otherwise (running in Expo Go) use a free port that falls back on the classic 19000 port.\n await getFreePortAsync(EXPO_GO_METRO_PORT));\n\n return port;\n }\n\n protected async startImplementationAsync(\n options: BundlerStartOptions\n ): Promise<DevServerInstance> {\n options.port = await this.resolvePortAsync(options);\n this.urlCreator = this.getUrlCreator(options);\n\n const parsedOptions = {\n port: options.port,\n maxWorkers: options.maxWorkers,\n resetCache: options.resetDevServer,\n\n // Use the unversioned metro config.\n // TODO: Deprecate this property when expo-cli goes away.\n unversioned: false,\n };\n\n const { server, middleware, messageSocket } = await instantiateMetroAsync(\n this.projectRoot,\n parsedOptions\n );\n\n const manifestMiddleware = await this.getManifestMiddlewareAsync(options);\n\n // We need the manifest handler to be the first middleware to run so our\n // routes take precedence over static files. For example, the manifest is\n // served from '/' and if the user has an index.html file in their project\n // then the manifest handler will never run, the static middleware will run\n // and serve index.html instead of the manifest.\n // https://github.com/expo/expo/issues/13114\n prependMiddleware(middleware, manifestMiddleware);\n\n middleware.use(\n new InterstitialPageMiddleware(this.projectRoot, {\n // TODO: Prevent this from becoming stale.\n scheme: options.location.scheme ?? null,\n }).getHandler()\n );\n\n const deepLinkMiddleware = new RuntimeRedirectMiddleware(this.projectRoot, {\n onDeepLink: ({ runtime }) => {\n // eslint-disable-next-line no-useless-return\n if (runtime === 'expo') return;\n // TODO: Some heavy analytics...\n },\n getLocation: ({ runtime }) => {\n if (runtime === 'custom') {\n return this.urlCreator?.constructDevClientUrl();\n } else {\n return this.urlCreator?.constructUrl({\n scheme: 'exp',\n });\n }\n },\n });\n middleware.use(deepLinkMiddleware.getHandler());\n\n middleware.use(new CreateFileMiddleware(this.projectRoot).getHandler());\n\n // Append support for redirecting unhandled requests to the index.html page on web.\n if (this.isTargetingWeb()) {\n // This MUST be after the manifest middleware so it doesn't have a chance to serve the template `public/index.html`.\n middleware.use(new ServeStaticMiddleware(this.projectRoot).getHandler());\n\n // This MUST run last since it's the fallback.\n middleware.use(new HistoryFallbackMiddleware(manifestMiddleware.internal).getHandler());\n }\n // Extend the close method to ensure that we clean up the local info.\n const originalClose = server.close.bind(server);\n\n server.close = (callback?: (err?: Error) => void) => {\n return originalClose((err?: Error) => {\n this.instance = null;\n callback?.(err);\n });\n };\n\n return {\n server,\n location: {\n // The port is the main thing we want to send back.\n port: options.port,\n // localhost isn't always correct.\n host: 'localhost',\n // http is the only supported protocol on native.\n url: `http://localhost:${options.port}`,\n protocol: 'http',\n },\n middleware,\n messageSocket,\n };\n }\n\n protected getConfigModuleIds(): string[] {\n return ['./metro.config.js', './metro.config.json', './rn-cli.config.js'];\n }\n}\n"],"names":["EXPO_GO_METRO_PORT","DEV_CLIENT_METRO_PORT","MetroBundlerDevServer","BundlerDevServer","name","resolvePortAsync","options","port","devClient","Number","process","env","RCT_METRO_PORT","getFreePortAsync","startImplementationAsync","urlCreator","getUrlCreator","parsedOptions","maxWorkers","resetCache","resetDevServer","unversioned","server","middleware","messageSocket","instantiateMetroAsync","projectRoot","manifestMiddleware","getManifestMiddlewareAsync","prependMiddleware","use","InterstitialPageMiddleware","scheme","location","getHandler","deepLinkMiddleware","RuntimeRedirectMiddleware","onDeepLink","runtime","getLocation","constructDevClientUrl","constructUrl","CreateFileMiddleware","isTargetingWeb","ServeStaticMiddleware","HistoryFallbackMiddleware","internal","originalClose","close","bind","callback","err","instance","host","url","protocol","getConfigModuleIds"],"mappings":"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"}
|
|
@@ -9,6 +9,7 @@ var _createDevServerMiddleware = require("../middleware/createDevServerMiddlewar
|
|
|
9
9
|
var _platformBundlers = require("../platformBundlers");
|
|
10
10
|
var _metroTerminalReporter = require("./MetroTerminalReporter");
|
|
11
11
|
var _resolveFromProject = require("./resolveFromProject");
|
|
12
|
+
var _router = require("./router");
|
|
12
13
|
var _withMetroMultiPlatform = require("./withMetroMultiPlatform");
|
|
13
14
|
async function instantiateMetroAsync(projectRoot, options) {
|
|
14
15
|
let reportEvent;
|
|
@@ -35,6 +36,10 @@ async function instantiateMetroAsync(projectRoot, options) {
|
|
|
35
36
|
});
|
|
36
37
|
const platformBundlers = (0, _platformBundlers).getPlatformBundlers(exp);
|
|
37
38
|
metroConfig = (0, _withMetroMultiPlatform).withMetroMultiPlatform(projectRoot, metroConfig, platformBundlers);
|
|
39
|
+
// Auto pick App entry: this is injected with Babel.
|
|
40
|
+
process.env.EXPO_ROUTER_APP_ROOT = (0, _router).getAppRouterRelativeEntryPath(projectRoot);
|
|
41
|
+
var _EXPO_PROJECT_ROOT;
|
|
42
|
+
process.env.EXPO_PROJECT_ROOT = (_EXPO_PROJECT_ROOT = process.env.EXPO_PROJECT_ROOT) != null ? _EXPO_PROJECT_ROOT : projectRoot;
|
|
38
43
|
const { middleware , attachToServer , // New
|
|
39
44
|
websocketEndpoints , eventsSocketEndpoint , messageSocketEndpoint , } = (0, _createDevServerMiddleware).createDevServerMiddleware(projectRoot, {
|
|
40
45
|
port: metroConfig.server.port,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/metro/instantiateMetro.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport { MetroDevServerOptions } from '@expo/dev-server';\nimport http from 'http';\nimport Metro from 'metro';\nimport { Terminal } from 'metro-core';\n\nimport { createDevServerMiddleware } from '../middleware/createDevServerMiddleware';\nimport { getPlatformBundlers } from '../platformBundlers';\nimport { MetroTerminalReporter } from './MetroTerminalReporter';\nimport { importExpoMetroConfigFromProject, importMetroFromProject } from './resolveFromProject';\nimport { withMetroMultiPlatform } from './withMetroMultiPlatform';\n\n// From expo/dev-server but with ability to use custom logger.\ntype MessageSocket = {\n broadcast: (method: string, params?: Record<string, any> | undefined) => void;\n};\n\n/** The most generic possible setup for Metro bundler. */\nexport async function instantiateMetroAsync(\n projectRoot: string,\n options: Omit<MetroDevServerOptions, 'logger'>\n): Promise<{\n server: http.Server;\n middleware: any;\n messageSocket: MessageSocket;\n}> {\n let reportEvent: ((event: any) => void) | undefined;\n\n const Metro = importMetroFromProject(projectRoot);\n const ExpoMetroConfig = importExpoMetroConfigFromProject(projectRoot);\n\n const terminal = new Terminal(process.stdout);\n const terminalReporter = new MetroTerminalReporter(projectRoot, terminal);\n\n const reporter = {\n update(event: any) {\n terminalReporter.update(event);\n if (reportEvent) {\n reportEvent(event);\n }\n },\n };\n\n let metroConfig = await ExpoMetroConfig.loadAsync(projectRoot, { reporter, ...options });\n\n // TODO: When we bring expo/metro-config into the expo/expo repo, then we can upstream this.\n const { exp } = getConfig(projectRoot, {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/metro/instantiateMetro.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport { MetroDevServerOptions } from '@expo/dev-server';\nimport http from 'http';\nimport Metro from 'metro';\nimport { Terminal } from 'metro-core';\n\nimport { createDevServerMiddleware } from '../middleware/createDevServerMiddleware';\nimport { getPlatformBundlers } from '../platformBundlers';\nimport { MetroTerminalReporter } from './MetroTerminalReporter';\nimport { importExpoMetroConfigFromProject, importMetroFromProject } from './resolveFromProject';\nimport { getAppRouterRelativeEntryPath } from './router';\nimport { withMetroMultiPlatform } from './withMetroMultiPlatform';\n\n// From expo/dev-server but with ability to use custom logger.\ntype MessageSocket = {\n broadcast: (method: string, params?: Record<string, any> | undefined) => void;\n};\n\n/** The most generic possible setup for Metro bundler. */\nexport async function instantiateMetroAsync(\n projectRoot: string,\n options: Omit<MetroDevServerOptions, 'logger'>\n): Promise<{\n server: http.Server;\n middleware: any;\n messageSocket: MessageSocket;\n}> {\n let reportEvent: ((event: any) => void) | undefined;\n\n const Metro = importMetroFromProject(projectRoot);\n const ExpoMetroConfig = importExpoMetroConfigFromProject(projectRoot);\n\n const terminal = new Terminal(process.stdout);\n const terminalReporter = new MetroTerminalReporter(projectRoot, terminal);\n\n const reporter = {\n update(event: any) {\n terminalReporter.update(event);\n if (reportEvent) {\n reportEvent(event);\n }\n },\n };\n\n let metroConfig = await ExpoMetroConfig.loadAsync(projectRoot, { reporter, ...options });\n\n // TODO: When we bring expo/metro-config into the expo/expo repo, then we can upstream this.\n const { exp } = getConfig(projectRoot, {\n skipSDKVersionRequirement: true,\n skipPlugins: true,\n });\n const platformBundlers = getPlatformBundlers(exp);\n metroConfig = withMetroMultiPlatform(projectRoot, metroConfig, platformBundlers);\n\n // Auto pick App entry: this is injected with Babel.\n process.env.EXPO_ROUTER_APP_ROOT = getAppRouterRelativeEntryPath(projectRoot);\n process.env.EXPO_PROJECT_ROOT = process.env.EXPO_PROJECT_ROOT ?? projectRoot;\n\n const {\n middleware,\n attachToServer,\n\n // New\n websocketEndpoints,\n eventsSocketEndpoint,\n messageSocketEndpoint,\n } = createDevServerMiddleware(projectRoot, {\n port: metroConfig.server.port,\n watchFolders: metroConfig.watchFolders,\n });\n\n const customEnhanceMiddleware = metroConfig.server.enhanceMiddleware;\n // @ts-ignore can't mutate readonly config\n metroConfig.server.enhanceMiddleware = (metroMiddleware: any, server: Metro.Server) => {\n if (customEnhanceMiddleware) {\n metroMiddleware = customEnhanceMiddleware(metroMiddleware, server);\n }\n return middleware.use(metroMiddleware);\n };\n\n const server = await Metro.runServer(metroConfig, {\n hmrEnabled: true,\n websocketEndpoints,\n });\n\n if (attachToServer) {\n // Expo SDK 44 and lower\n const { messageSocket, eventsSocket } = attachToServer(server);\n reportEvent = eventsSocket.reportEvent;\n\n return {\n server,\n middleware,\n messageSocket,\n };\n } else {\n // RN +68 -- Expo SDK +45\n reportEvent = eventsSocketEndpoint.reportEvent;\n\n return {\n server,\n middleware,\n messageSocket: messageSocketEndpoint,\n };\n }\n}\n"],"names":["instantiateMetroAsync","projectRoot","options","reportEvent","Metro","importMetroFromProject","ExpoMetroConfig","importExpoMetroConfigFromProject","terminal","Terminal","process","stdout","terminalReporter","MetroTerminalReporter","reporter","update","event","metroConfig","loadAsync","exp","getConfig","skipSDKVersionRequirement","skipPlugins","platformBundlers","getPlatformBundlers","withMetroMultiPlatform","env","EXPO_ROUTER_APP_ROOT","getAppRouterRelativeEntryPath","EXPO_PROJECT_ROOT","middleware","attachToServer","websocketEndpoints","eventsSocketEndpoint","messageSocketEndpoint","createDevServerMiddleware","port","server","watchFolders","customEnhanceMiddleware","enhanceMiddleware","metroMiddleware","use","runServer","hmrEnabled","messageSocket","eventsSocket"],"mappings":"AAAA;;;;QAmBsBA,qBAAqB,GAArBA,qBAAqB;AAnBjB,IAAA,OAAc,WAAd,cAAc,CAAA;AAIf,IAAA,UAAY,WAAZ,YAAY,CAAA;AAEK,IAAA,0BAAyC,WAAzC,yCAAyC,CAAA;AAC/C,IAAA,iBAAqB,WAArB,qBAAqB,CAAA;AACnB,IAAA,sBAAyB,WAAzB,yBAAyB,CAAA;AACU,IAAA,mBAAsB,WAAtB,sBAAsB,CAAA;AACjD,IAAA,OAAU,WAAV,UAAU,CAAA;AACjB,IAAA,uBAA0B,WAA1B,0BAA0B,CAAA;AAQ1D,eAAeA,qBAAqB,CACzCC,WAAmB,EACnBC,OAA8C,EAK7C;IACD,IAAIC,WAAW,AAAoC,AAAC;IAEpD,MAAMC,KAAK,GAAGC,CAAAA,GAAAA,mBAAsB,AAAa,CAAA,uBAAb,CAACJ,WAAW,CAAC,AAAC;IAClD,MAAMK,eAAe,GAAGC,CAAAA,GAAAA,mBAAgC,AAAa,CAAA,iCAAb,CAACN,WAAW,CAAC,AAAC;IAEtE,MAAMO,QAAQ,GAAG,IAAIC,UAAQ,SAAA,CAACC,OAAO,CAACC,MAAM,CAAC,AAAC;IAC9C,MAAMC,gBAAgB,GAAG,IAAIC,sBAAqB,sBAAA,CAACZ,WAAW,EAAEO,QAAQ,CAAC,AAAC;IAE1E,MAAMM,QAAQ,GAAG;QACfC,MAAM,EAACC,KAAU,EAAE;YACjBJ,gBAAgB,CAACG,MAAM,CAACC,KAAK,CAAC,CAAC;YAC/B,IAAIb,WAAW,EAAE;gBACfA,WAAW,CAACa,KAAK,CAAC,CAAC;aACpB;SACF;KACF,AAAC;IAEF,IAAIC,WAAW,GAAG,MAAMX,eAAe,CAACY,SAAS,CAACjB,WAAW,EAAE;QAAEa,QAAQ;QAAE,GAAGZ,OAAO;KAAE,CAAC,AAAC;IAEzF,4FAA4F;IAC5F,MAAM,EAAEiB,GAAG,CAAA,EAAE,GAAGC,CAAAA,GAAAA,OAAS,AAGvB,CAAA,UAHuB,CAACnB,WAAW,EAAE;QACrCoB,yBAAyB,EAAE,IAAI;QAC/BC,WAAW,EAAE,IAAI;KAClB,CAAC,AAAC;IACH,MAAMC,gBAAgB,GAAGC,CAAAA,GAAAA,iBAAmB,AAAK,CAAA,oBAAL,CAACL,GAAG,CAAC,AAAC;IAClDF,WAAW,GAAGQ,CAAAA,GAAAA,uBAAsB,AAA4C,CAAA,uBAA5C,CAACxB,WAAW,EAAEgB,WAAW,EAAEM,gBAAgB,CAAC,CAAC;IAEjF,oDAAoD;IACpDb,OAAO,CAACgB,GAAG,CAACC,oBAAoB,GAAGC,CAAAA,GAAAA,OAA6B,AAAa,CAAA,8BAAb,CAAC3B,WAAW,CAAC,CAAC;QAC9CS,kBAA6B;IAA7DA,OAAO,CAACgB,GAAG,CAACG,iBAAiB,GAAGnB,CAAAA,kBAA6B,GAA7BA,OAAO,CAACgB,GAAG,CAACG,iBAAiB,YAA7BnB,kBAA6B,GAAIT,WAAW,CAAC;IAE7E,MAAM,EACJ6B,UAAU,CAAA,EACVC,cAAc,CAAA,EAEd,MAAM;IACNC,kBAAkB,CAAA,EAClBC,oBAAoB,CAAA,EACpBC,qBAAqB,CAAA,IACtB,GAAGC,CAAAA,GAAAA,0BAAyB,AAG3B,CAAA,0BAH2B,CAAClC,WAAW,EAAE;QACzCmC,IAAI,EAAEnB,WAAW,CAACoB,MAAM,CAACD,IAAI;QAC7BE,YAAY,EAAErB,WAAW,CAACqB,YAAY;KACvC,CAAC,AAAC;IAEH,MAAMC,uBAAuB,GAAGtB,WAAW,CAACoB,MAAM,CAACG,iBAAiB,AAAC;IACrE,0CAA0C;IAC1CvB,WAAW,CAACoB,MAAM,CAACG,iBAAiB,GAAG,CAACC,eAAoB,EAAEJ,MAAoB,GAAK;QACrF,IAAIE,uBAAuB,EAAE;YAC3BE,eAAe,GAAGF,uBAAuB,CAACE,eAAe,EAAEJ,MAAM,CAAC,CAAC;SACpE;QACD,OAAOP,UAAU,CAACY,GAAG,CAACD,eAAe,CAAC,CAAC;KACxC,CAAC;IAEF,MAAMJ,OAAM,GAAG,MAAMjC,KAAK,CAACuC,SAAS,CAAC1B,WAAW,EAAE;QAChD2B,UAAU,EAAE,IAAI;QAChBZ,kBAAkB;KACnB,CAAC,AAAC;IAEH,IAAID,cAAc,EAAE;QAClB,wBAAwB;QACxB,MAAM,EAAEc,aAAa,CAAA,EAAEC,YAAY,CAAA,EAAE,GAAGf,cAAc,CAACM,OAAM,CAAC,AAAC;QAC/DlC,WAAW,GAAG2C,YAAY,CAAC3C,WAAW,CAAC;QAEvC,OAAO;YACLkC,MAAM,EAANA,OAAM;YACNP,UAAU;YACVe,aAAa;SACd,CAAC;KACH,MAAM;QACL,yBAAyB;QACzB1C,WAAW,GAAG8B,oBAAoB,CAAC9B,WAAW,CAAC;QAE/C,OAAO;YACLkC,MAAM,EAANA,OAAM;YACNP,UAAU;YACVe,aAAa,EAAEX,qBAAqB;SACrC,CAAC;KACH;CACF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
exports.getAppRouterRelativeEntryPath = getAppRouterRelativeEntryPath;
|
|
6
|
+
var _path = _interopRequireDefault(require("path"));
|
|
7
|
+
var _resolveFrom = _interopRequireDefault(require("resolve-from"));
|
|
8
|
+
function _interopRequireDefault(obj) {
|
|
9
|
+
return obj && obj.__esModule ? obj : {
|
|
10
|
+
default: obj
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const debug = require("debug")("expo:start:server:metro:router");
|
|
14
|
+
function getAppRouterRelativeEntryPath(projectRoot) {
|
|
15
|
+
var ref;
|
|
16
|
+
// Auto pick App entry
|
|
17
|
+
const routerEntry = (ref = _resolveFrom.default.silent(projectRoot, "expo-router/entry")) != null ? ref : getFallbackEntryRoot(projectRoot);
|
|
18
|
+
if (!routerEntry) {
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
// It doesn't matter if the app folder exists.
|
|
22
|
+
const appFolder = _path.default.join(projectRoot, "app");
|
|
23
|
+
const appRoot = _path.default.relative(_path.default.dirname(routerEntry), appFolder);
|
|
24
|
+
debug("routerEntry", routerEntry, appFolder, appRoot);
|
|
25
|
+
return appRoot;
|
|
26
|
+
}
|
|
27
|
+
/** If the `expo-router` package is not installed, then use the `expo` package to determine where the node modules are relative to the project. */ function getFallbackEntryRoot(projectRoot) {
|
|
28
|
+
const expoRoot = _resolveFrom.default.silent(projectRoot, "expo/package.json");
|
|
29
|
+
if (expoRoot) {
|
|
30
|
+
return _path.default.join(_path.default.dirname(_path.default.dirname(expoRoot)), "expo-router/entry");
|
|
31
|
+
}
|
|
32
|
+
return _path.default.join(projectRoot, "node_modules/expo-router/entry");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//# sourceMappingURL=router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/metro/router.ts"],"sourcesContent":["import path from 'path';\nimport resolveFrom from 'resolve-from';\n\nconst debug = require('debug')('expo:start:server:metro:router') as typeof console.log;\n\n/**\n * Get the relative path for requiring the `/app` folder relative to the `expo-router/entry` file.\n * This mechanism does require the server to restart after the `expo-router` package is installed.\n */\nexport function getAppRouterRelativeEntryPath(projectRoot: string): string | undefined {\n // Auto pick App entry\n const routerEntry =\n resolveFrom.silent(projectRoot, 'expo-router/entry') ?? getFallbackEntryRoot(projectRoot);\n if (!routerEntry) {\n return undefined;\n }\n // It doesn't matter if the app folder exists.\n const appFolder = path.join(projectRoot, 'app');\n const appRoot = path.relative(path.dirname(routerEntry), appFolder);\n debug('routerEntry', routerEntry, appFolder, appRoot);\n return appRoot;\n}\n\n/** If the `expo-router` package is not installed, then use the `expo` package to determine where the node modules are relative to the project. */\nfunction getFallbackEntryRoot(projectRoot: string): string {\n const expoRoot = resolveFrom.silent(projectRoot, 'expo/package.json');\n if (expoRoot) {\n return path.join(path.dirname(path.dirname(expoRoot)), 'expo-router/entry');\n }\n return path.join(projectRoot, 'node_modules/expo-router/entry');\n}\n"],"names":["getAppRouterRelativeEntryPath","debug","require","projectRoot","resolveFrom","routerEntry","silent","getFallbackEntryRoot","undefined","appFolder","path","join","appRoot","relative","dirname","expoRoot"],"mappings":"AAAA;;;;QASgBA,6BAA6B,GAA7BA,6BAA6B;AAT5B,IAAA,KAAM,kCAAN,MAAM,EAAA;AACC,IAAA,YAAc,kCAAd,cAAc,EAAA;;;;;;AAEtC,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,gCAAgC,CAAC,AAAsB,AAAC;AAMhF,SAASF,6BAA6B,CAACG,WAAmB,EAAsB;QAGnFC,GAAoD;IAFtD,sBAAsB;IACtB,MAAMC,WAAW,GACfD,CAAAA,GAAoD,GAApDA,YAAW,QAAA,CAACE,MAAM,CAACH,WAAW,EAAE,mBAAmB,CAAC,YAApDC,GAAoD,GAAIG,oBAAoB,CAACJ,WAAW,CAAC,AAAC;IAC5F,IAAI,CAACE,WAAW,EAAE;QAChB,OAAOG,SAAS,CAAC;KAClB;IACD,8CAA8C;IAC9C,MAAMC,SAAS,GAAGC,KAAI,QAAA,CAACC,IAAI,CAACR,WAAW,EAAE,KAAK,CAAC,AAAC;IAChD,MAAMS,OAAO,GAAGF,KAAI,QAAA,CAACG,QAAQ,CAACH,KAAI,QAAA,CAACI,OAAO,CAACT,WAAW,CAAC,EAAEI,SAAS,CAAC,AAAC;IACpER,KAAK,CAAC,aAAa,EAAEI,WAAW,EAAEI,SAAS,EAAEG,OAAO,CAAC,CAAC;IACtD,OAAOA,OAAO,CAAC;CAChB;AAED,kJAAkJ,CAClJ,SAASL,oBAAoB,CAACJ,WAAmB,EAAU;IACzD,MAAMY,QAAQ,GAAGX,YAAW,QAAA,CAACE,MAAM,CAACH,WAAW,EAAE,mBAAmB,CAAC,AAAC;IACtE,IAAIY,QAAQ,EAAE;QACZ,OAAOL,KAAI,QAAA,CAACC,IAAI,CAACD,KAAI,QAAA,CAACI,OAAO,CAACJ,KAAI,QAAA,CAACI,OAAO,CAACC,QAAQ,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;KAC7E;IACD,OAAOL,KAAI,QAAA,CAACC,IAAI,CAACR,WAAW,EAAE,gCAAgC,CAAC,CAAC;CACjE"}
|
|
@@ -59,7 +59,8 @@ function withWebResolvers(config, projectRoot) {
|
|
|
59
59
|
// Get the `transformer.assetRegistryPath`
|
|
60
60
|
// this needs to be unified since you can't dynamically
|
|
61
61
|
// swap out the transformer based on platform.
|
|
62
|
-
const assetRegistryPath = _fs.default.realpathSync(
|
|
62
|
+
const assetRegistryPath = _fs.default.realpathSync(// This is the native asset registry alias for native.
|
|
63
|
+
_path.default.resolve((0, _resolveFrom).default(projectRoot, "react-native/Libraries/Image/AssetRegistry")));
|
|
63
64
|
// Create a resolver which dynamically disables support for
|
|
64
65
|
// `*.native.*` extensions on web.
|
|
65
66
|
const { resolve } = (0, _resolveFromProject).importMetroResolverFromProject(projectRoot);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/metro/withMetroMultiPlatform.ts"],"sourcesContent":["/**\n * Copyright © 2022 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport fs from 'fs';\nimport { ConfigT } from 'metro-config';\nimport { ResolutionContext } from 'metro-resolver';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { PlatformBundlers } from '../platformBundlers';\nimport { importMetroResolverFromProject } from './resolveFromProject';\n\nfunction withWebPolyfills(config: ConfigT): ConfigT {\n const originalGetPolyfills = config.serializer.getPolyfills\n ? config.serializer.getPolyfills.bind(config.serializer)\n : () => [];\n\n const getPolyfills = (ctx: { platform: string | null | undefined }): readonly string[] => {\n if (ctx.platform === 'web') {\n return [\n // TODO: runtime polyfills, i.e. Fast Refresh, error overlay, React Dev Tools...\n ];\n }\n // Generally uses `rn-get-polyfills`\n return originalGetPolyfills(ctx);\n };\n\n return {\n ...config,\n serializer: {\n ...config.serializer,\n getPolyfills,\n },\n };\n}\n\nfunction getDefaultResolveRequest(projectRoot: string) {\n const { resolve } = importMetroResolverFromProject(projectRoot);\n return (context: ResolutionContext, moduleName: string, platform: string | null) => {\n return resolve(context, moduleName, platform);\n };\n}\n\nexport type ExpoCustomMetroResolver = (\n ...args: Parameters<import('metro-resolver').CustomResolver>\n) => import('metro-resolver').Resolution | null;\n\n/** Extend the `resolver.resolveRequest` method with custom methods that can exit early by returning a `Resolution`. */\nfunction withCustomResolvers(\n config: ConfigT,\n projectRoot: string,\n resolvers: ExpoCustomMetroResolver[]\n): ConfigT {\n const originalResolveRequest =\n config.resolver.resolveRequest || getDefaultResolveRequest(projectRoot);\n\n return {\n ...config,\n resolver: {\n ...config.resolver,\n resolveRequest(...args: Parameters<import('metro-resolver').CustomResolver>) {\n for (const resolver of resolvers) {\n const resolution = resolver(...args);\n if (resolution) {\n return resolution;\n }\n }\n return originalResolveRequest(...args);\n },\n },\n };\n}\n\n/**\n * Apply custom resolvers to do the following:\n * - Disable `.native.js` extensions on web.\n * - Alias `react-native` to `react-native-web` on web.\n * - Redirect `react-native-web/dist/modules/AssetRegistry/index.js` to `@react-native/assets/registry.js` on web.\n */\nexport function withWebResolvers(config: ConfigT, projectRoot: string) {\n // Get the `transformer.assetRegistryPath`\n // this needs to be unified since you can't dynamically\n // swap out the transformer based on platform.\n const assetRegistryPath = fs.realpathSync(\n path.resolve(resolveFrom(projectRoot, '@react-native/assets/registry.js'))\n );\n\n // Create a resolver which dynamically disables support for\n // `*.native.*` extensions on web.\n\n const { resolve } = importMetroResolverFromProject(projectRoot);\n\n const extraNodeModules: { [key: string]: Record<string, string> } = {\n web: {\n 'react-native': path.resolve(require.resolve('react-native-web/package.json'), '..'),\n },\n };\n\n return withCustomResolvers(config, projectRoot, [\n // Add a resolver to alias the web asset resolver.\n (immutableContext: ResolutionContext, moduleName: string, platform: string | null) => {\n const context = { ...immutableContext };\n\n // Conditionally remap `react-native` to `react-native-web`\n if (platform && platform in extraNodeModules) {\n context.extraNodeModules = extraNodeModules[platform];\n }\n\n const result = resolve(\n {\n ...context,\n preferNativePlatform: platform !== 'web',\n resolveRequest: undefined,\n },\n moduleName,\n platform\n );\n\n // Replace the web resolver with the original one.\n // This is basically an alias for web-only.\n if (\n platform === 'web' &&\n result?.type === 'sourceFile' &&\n typeof result?.filePath === 'string' &&\n result.filePath.endsWith('react-native-web/dist/modules/AssetRegistry/index.js')\n ) {\n // @ts-expect-error: `readonly` for some reason.\n result.filePath = assetRegistryPath;\n }\n\n return result;\n },\n ]);\n}\n\n/** Add support for `react-native-web` and the Web platform. */\nexport function withMetroMultiPlatform(\n projectRoot: string,\n config: ConfigT,\n platformBundlers: PlatformBundlers\n) {\n // Bail out early for performance enhancements if web is not enabled.\n if (platformBundlers.web !== 'metro') {\n return config;\n }\n\n let expoConfigPlatforms = Object.entries(platformBundlers)\n .filter(([, bundler]) => bundler === 'metro')\n .map(([platform]) => platform);\n\n if (Array.isArray(config.resolver.platforms)) {\n expoConfigPlatforms = [...new Set(expoConfigPlatforms.concat(config.resolver.platforms))];\n }\n\n // @ts-expect-error: typed as `readonly`.\n config.resolver.platforms = expoConfigPlatforms;\n\n config = withWebPolyfills(config);\n\n return withWebResolvers(config, projectRoot);\n}\n"],"names":["withWebResolvers","withMetroMultiPlatform","withWebPolyfills","config","originalGetPolyfills","serializer","getPolyfills","bind","ctx","platform","getDefaultResolveRequest","projectRoot","resolve","importMetroResolverFromProject","context","moduleName","withCustomResolvers","resolvers","originalResolveRequest","resolver","resolveRequest","args","resolution","assetRegistryPath","fs","realpathSync","path","resolveFrom","extraNodeModules","web","require","immutableContext","result","preferNativePlatform","undefined","type","filePath","endsWith","platformBundlers","expoConfigPlatforms","Object","entries","filter","bundler","map","Array","isArray","platforms","Set","concat"],"mappings":"AAMA;;;;QA4EgBA,gBAAgB,GAAhBA,gBAAgB;
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/metro/withMetroMultiPlatform.ts"],"sourcesContent":["/**\n * Copyright © 2022 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport fs from 'fs';\nimport { ConfigT } from 'metro-config';\nimport { ResolutionContext } from 'metro-resolver';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { PlatformBundlers } from '../platformBundlers';\nimport { importMetroResolverFromProject } from './resolveFromProject';\n\nfunction withWebPolyfills(config: ConfigT): ConfigT {\n const originalGetPolyfills = config.serializer.getPolyfills\n ? config.serializer.getPolyfills.bind(config.serializer)\n : () => [];\n\n const getPolyfills = (ctx: { platform: string | null | undefined }): readonly string[] => {\n if (ctx.platform === 'web') {\n return [\n // TODO: runtime polyfills, i.e. Fast Refresh, error overlay, React Dev Tools...\n ];\n }\n // Generally uses `rn-get-polyfills`\n return originalGetPolyfills(ctx);\n };\n\n return {\n ...config,\n serializer: {\n ...config.serializer,\n getPolyfills,\n },\n };\n}\n\nfunction getDefaultResolveRequest(projectRoot: string) {\n const { resolve } = importMetroResolverFromProject(projectRoot);\n return (context: ResolutionContext, moduleName: string, platform: string | null) => {\n return resolve(context, moduleName, platform);\n };\n}\n\nexport type ExpoCustomMetroResolver = (\n ...args: Parameters<import('metro-resolver').CustomResolver>\n) => import('metro-resolver').Resolution | null;\n\n/** Extend the `resolver.resolveRequest` method with custom methods that can exit early by returning a `Resolution`. */\nfunction withCustomResolvers(\n config: ConfigT,\n projectRoot: string,\n resolvers: ExpoCustomMetroResolver[]\n): ConfigT {\n const originalResolveRequest =\n config.resolver.resolveRequest || getDefaultResolveRequest(projectRoot);\n\n return {\n ...config,\n resolver: {\n ...config.resolver,\n resolveRequest(...args: Parameters<import('metro-resolver').CustomResolver>) {\n for (const resolver of resolvers) {\n const resolution = resolver(...args);\n if (resolution) {\n return resolution;\n }\n }\n return originalResolveRequest(...args);\n },\n },\n };\n}\n\n/**\n * Apply custom resolvers to do the following:\n * - Disable `.native.js` extensions on web.\n * - Alias `react-native` to `react-native-web` on web.\n * - Redirect `react-native-web/dist/modules/AssetRegistry/index.js` to `@react-native/assets/registry.js` on web.\n */\nexport function withWebResolvers(config: ConfigT, projectRoot: string) {\n // Get the `transformer.assetRegistryPath`\n // this needs to be unified since you can't dynamically\n // swap out the transformer based on platform.\n const assetRegistryPath = fs.realpathSync(\n // This is the native asset registry alias for native.\n path.resolve(resolveFrom(projectRoot, 'react-native/Libraries/Image/AssetRegistry'))\n // NOTE(EvanBacon): This is the newer import but it doesn't work in the expo/expo monorepo.\n // path.resolve(resolveFrom(projectRoot, '@react-native/assets/registry.js'))\n );\n\n // Create a resolver which dynamically disables support for\n // `*.native.*` extensions on web.\n\n const { resolve } = importMetroResolverFromProject(projectRoot);\n\n const extraNodeModules: { [key: string]: Record<string, string> } = {\n web: {\n 'react-native': path.resolve(require.resolve('react-native-web/package.json'), '..'),\n },\n };\n\n return withCustomResolvers(config, projectRoot, [\n // Add a resolver to alias the web asset resolver.\n (immutableContext: ResolutionContext, moduleName: string, platform: string | null) => {\n const context = { ...immutableContext };\n\n // Conditionally remap `react-native` to `react-native-web`\n if (platform && platform in extraNodeModules) {\n context.extraNodeModules = extraNodeModules[platform];\n }\n\n const result = resolve(\n {\n ...context,\n preferNativePlatform: platform !== 'web',\n resolveRequest: undefined,\n },\n moduleName,\n platform\n );\n\n // Replace the web resolver with the original one.\n // This is basically an alias for web-only.\n if (\n platform === 'web' &&\n result?.type === 'sourceFile' &&\n typeof result?.filePath === 'string' &&\n result.filePath.endsWith('react-native-web/dist/modules/AssetRegistry/index.js')\n ) {\n // @ts-expect-error: `readonly` for some reason.\n result.filePath = assetRegistryPath;\n }\n\n return result;\n },\n ]);\n}\n\n/** Add support for `react-native-web` and the Web platform. */\nexport function withMetroMultiPlatform(\n projectRoot: string,\n config: ConfigT,\n platformBundlers: PlatformBundlers\n) {\n // Bail out early for performance enhancements if web is not enabled.\n if (platformBundlers.web !== 'metro') {\n return config;\n }\n\n let expoConfigPlatforms = Object.entries(platformBundlers)\n .filter(([, bundler]) => bundler === 'metro')\n .map(([platform]) => platform);\n\n if (Array.isArray(config.resolver.platforms)) {\n expoConfigPlatforms = [...new Set(expoConfigPlatforms.concat(config.resolver.platforms))];\n }\n\n // @ts-expect-error: typed as `readonly`.\n config.resolver.platforms = expoConfigPlatforms;\n\n config = withWebPolyfills(config);\n\n return withWebResolvers(config, projectRoot);\n}\n"],"names":["withWebResolvers","withMetroMultiPlatform","withWebPolyfills","config","originalGetPolyfills","serializer","getPolyfills","bind","ctx","platform","getDefaultResolveRequest","projectRoot","resolve","importMetroResolverFromProject","context","moduleName","withCustomResolvers","resolvers","originalResolveRequest","resolver","resolveRequest","args","resolution","assetRegistryPath","fs","realpathSync","path","resolveFrom","extraNodeModules","web","require","immutableContext","result","preferNativePlatform","undefined","type","filePath","endsWith","platformBundlers","expoConfigPlatforms","Object","entries","filter","bundler","map","Array","isArray","platforms","Set","concat"],"mappings":"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"}
|
|
@@ -128,7 +128,7 @@ async function createHostInfoAsync() {
|
|
|
128
128
|
host: await _userSettings.default.getAnonymousIdentifierAsync(),
|
|
129
129
|
server: "expo",
|
|
130
130
|
// Defined in the build step
|
|
131
|
-
serverVersion: "0.
|
|
131
|
+
serverVersion: "0.3.0",
|
|
132
132
|
serverDriver: _manifestMiddleware.DEVELOPER_TOOL,
|
|
133
133
|
serverOS: _os.default.platform(),
|
|
134
134
|
serverOSVersion: _os.default.release()
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", {
|
|
3
|
+
value: true
|
|
4
|
+
});
|
|
5
|
+
var _fs = _interopRequireDefault(require("fs"));
|
|
6
|
+
var _path = _interopRequireDefault(require("path"));
|
|
7
|
+
var _expoMiddleware = require("./ExpoMiddleware");
|
|
8
|
+
function _interopRequireDefault(obj) {
|
|
9
|
+
return obj && obj.__esModule ? obj : {
|
|
10
|
+
default: obj
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
const debug = require("debug")("expo:start:server:middleware:createFile");
|
|
14
|
+
class CreateFileMiddleware extends _expoMiddleware.ExpoMiddleware {
|
|
15
|
+
constructor(projectRoot){
|
|
16
|
+
super(projectRoot, [
|
|
17
|
+
"/_expo/touch"
|
|
18
|
+
]);
|
|
19
|
+
this.projectRoot = projectRoot;
|
|
20
|
+
}
|
|
21
|
+
resolvePath(inputPath) {
|
|
22
|
+
let resolvedPath = _path.default.join(this.projectRoot, inputPath);
|
|
23
|
+
const extension = _path.default.extname(resolvedPath);
|
|
24
|
+
if (extension === ".js") {
|
|
25
|
+
// Automatically convert JS files to TS files when added to a project
|
|
26
|
+
// with TypeScript.
|
|
27
|
+
const tsconfigPath = _path.default.join(this.projectRoot, "tsconfig.json");
|
|
28
|
+
if (_fs.default.existsSync(tsconfigPath)) {
|
|
29
|
+
resolvedPath = resolvedPath.replace(/\.js$/, ".tsx");
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return resolvedPath;
|
|
33
|
+
}
|
|
34
|
+
async parseRawBody(req) {
|
|
35
|
+
const rawBody = await new Promise((resolve, reject)=>{
|
|
36
|
+
let body = "";
|
|
37
|
+
req.on("data", (chunk)=>{
|
|
38
|
+
body += chunk.toString();
|
|
39
|
+
});
|
|
40
|
+
req.on("end", ()=>{
|
|
41
|
+
resolve(body);
|
|
42
|
+
});
|
|
43
|
+
req.on("error", (err)=>{
|
|
44
|
+
reject(err);
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
const properties = JSON.parse(rawBody);
|
|
48
|
+
this.assertTouchFileBody(properties);
|
|
49
|
+
return properties;
|
|
50
|
+
}
|
|
51
|
+
assertTouchFileBody(body) {
|
|
52
|
+
if (typeof body !== "object" || body == null) {
|
|
53
|
+
throw new Error("Expected object");
|
|
54
|
+
}
|
|
55
|
+
if (typeof body.path !== "string") {
|
|
56
|
+
throw new Error('Expected "path" in body to be string');
|
|
57
|
+
}
|
|
58
|
+
if (typeof body.contents !== "string") {
|
|
59
|
+
throw new Error('Expected "contents" in body to be string');
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async handleRequestAsync(req, res) {
|
|
63
|
+
if (req.method !== "POST") {
|
|
64
|
+
res.statusCode = 405;
|
|
65
|
+
res.end("Method Not Allowed");
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
let properties;
|
|
69
|
+
try {
|
|
70
|
+
properties = await this.parseRawBody(req);
|
|
71
|
+
} catch (e) {
|
|
72
|
+
debug("Error parsing request body", e);
|
|
73
|
+
res.statusCode = 400;
|
|
74
|
+
res.end("Bad Request");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
debug(`Requested: %O`, properties);
|
|
78
|
+
const resolvedPath = this.resolvePath(properties.path);
|
|
79
|
+
if (_fs.default.existsSync(resolvedPath)) {
|
|
80
|
+
res.statusCode = 409;
|
|
81
|
+
res.end("File already exists.");
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
debug(`Resolved path:`, resolvedPath);
|
|
85
|
+
try {
|
|
86
|
+
await _fs.default.promises.mkdir(_path.default.dirname(resolvedPath), {
|
|
87
|
+
recursive: true
|
|
88
|
+
});
|
|
89
|
+
await _fs.default.promises.writeFile(resolvedPath, properties.contents, "utf8");
|
|
90
|
+
} catch (e1) {
|
|
91
|
+
debug("Error writing file", e1);
|
|
92
|
+
res.statusCode = 500;
|
|
93
|
+
res.end("Error writing file.");
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
debug(`File created`);
|
|
97
|
+
res.statusCode = 200;
|
|
98
|
+
res.end("OK");
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.CreateFileMiddleware = CreateFileMiddleware;
|
|
102
|
+
|
|
103
|
+
//# sourceMappingURL=CreateFileMiddleware.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/middleware/CreateFileMiddleware.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\n\nimport { ExpoMiddleware } from './ExpoMiddleware';\nimport { ServerRequest, ServerResponse } from './server.types';\n\nconst debug = require('debug')('expo:start:server:middleware:createFile') as typeof console.log;\n\nexport type TouchFileBody = { path: string; contents: string };\n\n/**\n * Middleware for creating a file given a `POST` request with\n * `{ contents: string, path: string }` in the body.\n */\nexport class CreateFileMiddleware extends ExpoMiddleware {\n constructor(protected projectRoot: string) {\n super(projectRoot, ['/_expo/touch']);\n }\n\n protected resolvePath(inputPath: string): string {\n let resolvedPath = path.join(this.projectRoot, inputPath);\n const extension = path.extname(resolvedPath);\n if (extension === '.js') {\n // Automatically convert JS files to TS files when added to a project\n // with TypeScript.\n const tsconfigPath = path.join(this.projectRoot, 'tsconfig.json');\n if (fs.existsSync(tsconfigPath)) {\n resolvedPath = resolvedPath.replace(/\\.js$/, '.tsx');\n }\n }\n\n return resolvedPath;\n }\n\n protected async parseRawBody(req: ServerRequest): Promise<TouchFileBody> {\n const rawBody = await new Promise<string>((resolve, reject) => {\n let body = '';\n req.on('data', (chunk) => {\n body += chunk.toString();\n });\n req.on('end', () => {\n resolve(body);\n });\n req.on('error', (err) => {\n reject(err);\n });\n });\n\n const properties = JSON.parse(rawBody);\n this.assertTouchFileBody(properties);\n\n return properties;\n }\n\n private assertTouchFileBody(body: any): asserts body is TouchFileBody {\n if (typeof body !== 'object' || body == null) {\n throw new Error('Expected object');\n }\n if (typeof body.path !== 'string') {\n throw new Error('Expected \"path\" in body to be string');\n }\n if (typeof body.contents !== 'string') {\n throw new Error('Expected \"contents\" in body to be string');\n }\n }\n\n async handleRequestAsync(req: ServerRequest, res: ServerResponse): Promise<void> {\n if (req.method !== 'POST') {\n res.statusCode = 405;\n res.end('Method Not Allowed');\n return;\n }\n\n let properties: TouchFileBody;\n\n try {\n properties = await this.parseRawBody(req);\n } catch (e) {\n debug('Error parsing request body', e);\n res.statusCode = 400;\n res.end('Bad Request');\n return;\n }\n\n debug(`Requested: %O`, properties);\n\n const resolvedPath = this.resolvePath(properties.path);\n\n if (fs.existsSync(resolvedPath)) {\n res.statusCode = 409;\n res.end('File already exists.');\n return;\n }\n\n debug(`Resolved path:`, resolvedPath);\n\n try {\n await fs.promises.mkdir(path.dirname(resolvedPath), { recursive: true });\n await fs.promises.writeFile(resolvedPath, properties.contents, 'utf8');\n } catch (e) {\n debug('Error writing file', e);\n res.statusCode = 500;\n res.end('Error writing file.');\n return;\n }\n\n debug(`File created`);\n res.statusCode = 200;\n res.end('OK');\n }\n}\n"],"names":["debug","require","CreateFileMiddleware","ExpoMiddleware","constructor","projectRoot","resolvePath","inputPath","resolvedPath","path","join","extension","extname","tsconfigPath","fs","existsSync","replace","parseRawBody","req","rawBody","Promise","resolve","reject","body","on","chunk","toString","err","properties","JSON","parse","assertTouchFileBody","Error","contents","handleRequestAsync","res","method","statusCode","end","e","promises","mkdir","dirname","recursive","writeFile"],"mappings":"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"}
|
|
@@ -18,51 +18,60 @@ function _interopRequireDefault(obj) {
|
|
|
18
18
|
const debug = require("debug")("expo:start:server:middleware:interstitialPage");
|
|
19
19
|
const LoadingEndpoint = "/_expo/loading";
|
|
20
20
|
exports.LoadingEndpoint = LoadingEndpoint;
|
|
21
|
-
function getRuntimeVersion(exp, platform) {
|
|
22
|
-
if (!platform) {
|
|
23
|
-
return "Undetected";
|
|
24
|
-
}
|
|
25
|
-
var ref;
|
|
26
|
-
return (ref = (0, _updates).getRuntimeVersionNullable(exp, platform)) != null ? ref : "Undetected";
|
|
27
|
-
}
|
|
28
21
|
class InterstitialPageMiddleware extends _expoMiddleware.ExpoMiddleware {
|
|
29
|
-
constructor(projectRoot
|
|
22
|
+
constructor(projectRoot, options = {
|
|
23
|
+
scheme: null
|
|
24
|
+
}){
|
|
30
25
|
super(projectRoot, [
|
|
31
26
|
LoadingEndpoint
|
|
32
27
|
]);
|
|
28
|
+
this.options = options;
|
|
33
29
|
}
|
|
34
|
-
/** Get the template HTML page and inject values. */ async _getPageAsync({ appName ,
|
|
30
|
+
/** Get the template HTML page and inject values. */ async _getPageAsync({ appName , projectVersion }) {
|
|
35
31
|
var // Production: This will resolve when installed in the project.
|
|
36
32
|
ref;
|
|
37
33
|
const templatePath = (ref = _resolveFrom.default.silent(this.projectRoot, "expo/static/loading-page/index.html")) != null ? ref : // Development: This will resolve when testing locally.
|
|
38
34
|
_path.default.resolve(__dirname, "../../../../../static/loading-page/index.html");
|
|
39
35
|
let content = (await (0, _promises).readFile(templatePath)).toString("utf-8");
|
|
40
36
|
content = content.replace(/{{\s*AppName\s*}}/, appName);
|
|
41
|
-
content = content.replace(/{{\s*RuntimeVersion\s*}}/, runtimeVersion != null ? runtimeVersion : "");
|
|
42
37
|
content = content.replace(/{{\s*Path\s*}}/, this.projectRoot);
|
|
38
|
+
var _scheme;
|
|
39
|
+
content = content.replace(/{{\s*Scheme\s*}}/, (_scheme = this.options.scheme) != null ? _scheme : "Unknown");
|
|
40
|
+
content = content.replace(/{{\s*ProjectVersionType\s*}}/, `${projectVersion.type === "sdk" ? "SDK" : "Runtime"} version`);
|
|
41
|
+
var _version;
|
|
42
|
+
content = content.replace(/{{\s*ProjectVersion\s*}}/, (_version = projectVersion.version) != null ? _version : "Undetected");
|
|
43
43
|
return content;
|
|
44
44
|
}
|
|
45
45
|
/** Get settings for the page from the project config. */ _getProjectOptions(platform) {
|
|
46
46
|
(0, _resolvePlatform).assertRuntimePlatform(platform);
|
|
47
47
|
const { exp } = (0, _config).getConfig(this.projectRoot);
|
|
48
48
|
const { appName } = (0, _config).getNameFromConfig(exp);
|
|
49
|
-
const runtimeVersion =
|
|
49
|
+
const runtimeVersion = (0, _updates).getRuntimeVersionNullable(exp, platform);
|
|
50
|
+
var _sdkVersion;
|
|
51
|
+
const sdkVersion = (_sdkVersion = exp.sdkVersion) != null ? _sdkVersion : null;
|
|
50
52
|
return {
|
|
51
53
|
appName: appName != null ? appName : "App",
|
|
52
|
-
runtimeVersion
|
|
54
|
+
projectVersion: sdkVersion && !runtimeVersion ? {
|
|
55
|
+
type: "sdk",
|
|
56
|
+
version: sdkVersion
|
|
57
|
+
} : {
|
|
58
|
+
type: "runtime",
|
|
59
|
+
version: runtimeVersion
|
|
60
|
+
}
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
63
|
async handleRequestAsync(req, res) {
|
|
56
64
|
res = (0, _expoMiddleware).disableResponseCache(res);
|
|
57
65
|
res.setHeader("Content-Type", "text/html");
|
|
58
|
-
|
|
66
|
+
var ref;
|
|
67
|
+
const platform = (ref = (0, _resolvePlatform).parsePlatformHeader(req)) != null ? ref : (0, _resolvePlatform).resolvePlatformFromUserAgentHeader(req);
|
|
59
68
|
(0, _resolvePlatform).assertMissingRuntimePlatform(platform);
|
|
60
69
|
(0, _resolvePlatform).assertRuntimePlatform(platform);
|
|
61
|
-
const { appName ,
|
|
62
|
-
debug(`Create loading page. (platform: ${platform}, appName: ${appName},
|
|
70
|
+
const { appName , projectVersion } = this._getProjectOptions(platform);
|
|
71
|
+
debug(`Create loading page. (platform: ${platform}, appName: ${appName}, projectVersion: ${projectVersion.version}, type: ${projectVersion.type})`);
|
|
63
72
|
const content = await this._getPageAsync({
|
|
64
73
|
appName,
|
|
65
|
-
|
|
74
|
+
projectVersion
|
|
66
75
|
});
|
|
67
76
|
res.end(content);
|
|
68
77
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/middleware/InterstitialPageMiddleware.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/middleware/InterstitialPageMiddleware.ts"],"sourcesContent":["import { getConfig, getNameFromConfig } from '@expo/config';\nimport { getRuntimeVersionNullable } from '@expo/config-plugins/build/utils/Updates';\nimport { readFile } from 'fs/promises';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { disableResponseCache, ExpoMiddleware } from './ExpoMiddleware';\nimport {\n assertMissingRuntimePlatform,\n assertRuntimePlatform,\n parsePlatformHeader,\n resolvePlatformFromUserAgentHeader,\n RuntimePlatform,\n} from './resolvePlatform';\nimport { ServerRequest, ServerResponse } from './server.types';\n\ntype ProjectVersion = {\n type: 'sdk' | 'runtime';\n version: string | null;\n};\n\nconst debug = require('debug')(\n 'expo:start:server:middleware:interstitialPage'\n) as typeof console.log;\n\nexport const LoadingEndpoint = '/_expo/loading';\n\nexport class InterstitialPageMiddleware extends ExpoMiddleware {\n constructor(\n projectRoot: string,\n protected options: { scheme: string | null } = { scheme: null }\n ) {\n super(projectRoot, [LoadingEndpoint]);\n }\n\n /** Get the template HTML page and inject values. */\n async _getPageAsync({\n appName,\n projectVersion,\n }: {\n appName: string;\n projectVersion: ProjectVersion;\n }): Promise<string> {\n const templatePath =\n // Production: This will resolve when installed in the project.\n resolveFrom.silent(this.projectRoot, 'expo/static/loading-page/index.html') ??\n // Development: This will resolve when testing locally.\n path.resolve(__dirname, '../../../../../static/loading-page/index.html');\n let content = (await readFile(templatePath)).toString('utf-8');\n\n content = content.replace(/{{\\s*AppName\\s*}}/, appName);\n content = content.replace(/{{\\s*Path\\s*}}/, this.projectRoot);\n content = content.replace(/{{\\s*Scheme\\s*}}/, this.options.scheme ?? 'Unknown');\n content = content.replace(\n /{{\\s*ProjectVersionType\\s*}}/,\n `${projectVersion.type === 'sdk' ? 'SDK' : 'Runtime'} version`\n );\n content = content.replace(/{{\\s*ProjectVersion\\s*}}/, projectVersion.version ?? 'Undetected');\n\n return content;\n }\n\n /** Get settings for the page from the project config. */\n _getProjectOptions(platform: RuntimePlatform): {\n appName: string;\n projectVersion: ProjectVersion;\n } {\n assertRuntimePlatform(platform);\n\n const { exp } = getConfig(this.projectRoot);\n const { appName } = getNameFromConfig(exp);\n const runtimeVersion = getRuntimeVersionNullable(exp, platform);\n const sdkVersion = exp.sdkVersion ?? null;\n\n return {\n appName: appName ?? 'App',\n projectVersion:\n sdkVersion && !runtimeVersion\n ? { type: 'sdk', version: sdkVersion }\n : { type: 'runtime', version: runtimeVersion },\n };\n }\n\n async handleRequestAsync(req: ServerRequest, res: ServerResponse): Promise<void> {\n res = disableResponseCache(res);\n res.setHeader('Content-Type', 'text/html');\n\n const platform = parsePlatformHeader(req) ?? resolvePlatformFromUserAgentHeader(req);\n assertMissingRuntimePlatform(platform);\n assertRuntimePlatform(platform);\n\n const { appName, projectVersion } = this._getProjectOptions(platform);\n debug(\n `Create loading page. (platform: ${platform}, appName: ${appName}, projectVersion: ${projectVersion.version}, type: ${projectVersion.type})`\n );\n const content = await this._getPageAsync({ appName, projectVersion });\n res.end(content);\n }\n}\n"],"names":["debug","require","LoadingEndpoint","InterstitialPageMiddleware","ExpoMiddleware","constructor","projectRoot","options","scheme","_getPageAsync","appName","projectVersion","resolveFrom","templatePath","silent","path","resolve","__dirname","content","readFile","toString","replace","type","version","_getProjectOptions","platform","assertRuntimePlatform","exp","getConfig","getNameFromConfig","runtimeVersion","getRuntimeVersionNullable","sdkVersion","handleRequestAsync","req","res","disableResponseCache","setHeader","parsePlatformHeader","resolvePlatformFromUserAgentHeader","assertMissingRuntimePlatform","end"],"mappings":"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"}
|
|
@@ -39,7 +39,8 @@ class RuntimeRedirectMiddleware extends _expoMiddleware.ExpoMiddleware {
|
|
|
39
39
|
async handleRequestAsync(req, res) {
|
|
40
40
|
const { query } = (0, _url).parse(req.url, true);
|
|
41
41
|
const isDevClient = query["choice"] === "expo-dev-client";
|
|
42
|
-
|
|
42
|
+
var ref;
|
|
43
|
+
const platform = (ref = (0, _resolvePlatform).parsePlatformHeader(req)) != null ? ref : (0, _resolvePlatform).resolvePlatformFromUserAgentHeader(req);
|
|
43
44
|
(0, _resolvePlatform).assertMissingRuntimePlatform(platform);
|
|
44
45
|
(0, _resolvePlatform).assertRuntimePlatform(platform);
|
|
45
46
|
const runtime = isDevClient ? "custom" : "expo";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/middleware/RuntimeRedirectMiddleware.ts"],"sourcesContent":["import { parse } from 'url';\n\nimport * as Log from '../../../log';\nimport { disableResponseCache, ExpoMiddleware } from './ExpoMiddleware';\nimport {\n assertMissingRuntimePlatform,\n assertRuntimePlatform,\n parsePlatformHeader,\n RuntimePlatform,\n} from './resolvePlatform';\nimport { ServerRequest, ServerResponse } from './server.types';\n\nconst debug = require('debug')(\n 'expo:start:server:middleware:runtimeRedirect'\n) as typeof console.log;\n\n/** Runtime to target: expo = Expo Go, custom = Dev Client. */\ntype RuntimeTarget = 'expo' | 'custom';\n\nexport class RuntimeRedirectMiddleware extends ExpoMiddleware {\n constructor(\n protected projectRoot: string,\n protected options: {\n onDeepLink: (props: {\n runtime: RuntimeTarget;\n platform: RuntimePlatform;\n }) => void | Promise<void>;\n getLocation: (props: { runtime: RuntimeTarget }) => string | null | undefined;\n }\n ) {\n super(projectRoot, ['/_expo/link']);\n }\n\n async handleRequestAsync(req: ServerRequest, res: ServerResponse): Promise<void> {\n const { query } = parse(req.url!, true);\n const isDevClient = query['choice'] === 'expo-dev-client';\n const platform = parsePlatformHeader(req);\n assertMissingRuntimePlatform(platform);\n assertRuntimePlatform(platform);\n const runtime = isDevClient ? 'custom' : 'expo';\n\n debug(`props:`, { platform, runtime });\n\n this.options.onDeepLink({ runtime, platform });\n\n const redirect = this.options.getLocation({ runtime });\n if (!redirect) {\n Log.warn(\n `[redirect middleware]: Unable to determine redirect location for runtime '${runtime}' and platform '${platform}'`\n );\n res.statusCode = 404;\n res.end();\n return;\n }\n debug('Redirect ->', redirect);\n res.setHeader('Location', redirect);\n\n // Disable caching\n disableResponseCache(res);\n\n // 'Temporary Redirect'\n res.statusCode = 307;\n res.end();\n }\n}\n"],"names":["Log","debug","require","RuntimeRedirectMiddleware","ExpoMiddleware","constructor","projectRoot","options","handleRequestAsync","req","res","query","parse","url","isDevClient","platform","
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/middleware/RuntimeRedirectMiddleware.ts"],"sourcesContent":["import { parse } from 'url';\n\nimport * as Log from '../../../log';\nimport { disableResponseCache, ExpoMiddleware } from './ExpoMiddleware';\nimport {\n assertMissingRuntimePlatform,\n assertRuntimePlatform,\n parsePlatformHeader,\n resolvePlatformFromUserAgentHeader,\n RuntimePlatform,\n} from './resolvePlatform';\nimport { ServerRequest, ServerResponse } from './server.types';\n\nconst debug = require('debug')(\n 'expo:start:server:middleware:runtimeRedirect'\n) as typeof console.log;\n\n/** Runtime to target: expo = Expo Go, custom = Dev Client. */\ntype RuntimeTarget = 'expo' | 'custom';\n\nexport class RuntimeRedirectMiddleware extends ExpoMiddleware {\n constructor(\n protected projectRoot: string,\n protected options: {\n onDeepLink: (props: {\n runtime: RuntimeTarget;\n platform: RuntimePlatform;\n }) => void | Promise<void>;\n getLocation: (props: { runtime: RuntimeTarget }) => string | null | undefined;\n }\n ) {\n super(projectRoot, ['/_expo/link']);\n }\n\n async handleRequestAsync(req: ServerRequest, res: ServerResponse): Promise<void> {\n const { query } = parse(req.url!, true);\n const isDevClient = query['choice'] === 'expo-dev-client';\n const platform = parsePlatformHeader(req) ?? resolvePlatformFromUserAgentHeader(req);\n assertMissingRuntimePlatform(platform);\n assertRuntimePlatform(platform);\n const runtime = isDevClient ? 'custom' : 'expo';\n\n debug(`props:`, { platform, runtime });\n\n this.options.onDeepLink({ runtime, platform });\n\n const redirect = this.options.getLocation({ runtime });\n if (!redirect) {\n Log.warn(\n `[redirect middleware]: Unable to determine redirect location for runtime '${runtime}' and platform '${platform}'`\n );\n res.statusCode = 404;\n res.end();\n return;\n }\n debug('Redirect ->', redirect);\n res.setHeader('Location', redirect);\n\n // Disable caching\n disableResponseCache(res);\n\n // 'Temporary Redirect'\n res.statusCode = 307;\n res.end();\n }\n}\n"],"names":["Log","debug","require","RuntimeRedirectMiddleware","ExpoMiddleware","constructor","projectRoot","options","handleRequestAsync","req","res","query","parse","url","isDevClient","parsePlatformHeader","platform","resolvePlatformFromUserAgentHeader","assertMissingRuntimePlatform","assertRuntimePlatform","runtime","onDeepLink","redirect","getLocation","warn","statusCode","end","setHeader","disableResponseCache"],"mappings":"AAAA;;;;AAAsB,IAAA,IAAK,WAAL,KAAK,CAAA;AAEfA,IAAAA,GAAG,mCAAM,cAAc,EAApB;AACsC,IAAA,eAAkB,WAAlB,kBAAkB,CAAA;AAOhE,IAAA,gBAAmB,WAAnB,mBAAmB,CAAA;;;;;;;;;;;;;;;;;;;;;;AAG1B,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAC5B,8CAA8C,CAC/C,AAAsB,AAAC;AAKjB,MAAMC,yBAAyB,SAASC,eAAc,eAAA;IAC3DC,YACYC,WAAmB,EACnBC,OAMT,CACD;QACA,KAAK,CAACD,WAAW,EAAE;YAAC,aAAa;SAAC,CAAC,CAAC;aAT1BA,WAAmB,GAAnBA,WAAmB;aACnBC,OAMT,GANSA,OAMT;KAGF;IAED,MAAMC,kBAAkB,CAACC,GAAkB,EAAEC,GAAmB,EAAiB;QAC/E,MAAM,EAAEC,KAAK,CAAA,EAAE,GAAGC,CAAAA,GAAAA,IAAK,AAAgB,CAAA,MAAhB,CAACH,GAAG,CAACI,GAAG,EAAG,IAAI,CAAC,AAAC;QACxC,MAAMC,WAAW,GAAGH,KAAK,CAAC,QAAQ,CAAC,KAAK,iBAAiB,AAAC;YACzCI,GAAwB;QAAzC,MAAMC,QAAQ,GAAGD,CAAAA,GAAwB,GAAxBA,CAAAA,GAAAA,gBAAmB,AAAK,CAAA,oBAAL,CAACN,GAAG,CAAC,YAAxBM,GAAwB,GAAIE,CAAAA,GAAAA,gBAAkC,AAAK,CAAA,mCAAL,CAACR,GAAG,CAAC,AAAC;QACrFS,CAAAA,GAAAA,gBAA4B,AAAU,CAAA,6BAAV,CAACF,QAAQ,CAAC,CAAC;QACvCG,CAAAA,GAAAA,gBAAqB,AAAU,CAAA,sBAAV,CAACH,QAAQ,CAAC,CAAC;QAChC,MAAMI,OAAO,GAAGN,WAAW,GAAG,QAAQ,GAAG,MAAM,AAAC;QAEhDb,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE;YAAEe,QAAQ;YAAEI,OAAO;SAAE,CAAC,CAAC;QAEvC,IAAI,CAACb,OAAO,CAACc,UAAU,CAAC;YAAED,OAAO;YAAEJ,QAAQ;SAAE,CAAC,CAAC;QAE/C,MAAMM,QAAQ,GAAG,IAAI,CAACf,OAAO,CAACgB,WAAW,CAAC;YAAEH,OAAO;SAAE,CAAC,AAAC;QACvD,IAAI,CAACE,QAAQ,EAAE;YACbtB,GAAG,CAACwB,IAAI,CACN,CAAC,0EAA0E,EAAEJ,OAAO,CAAC,gBAAgB,EAAEJ,QAAQ,CAAC,CAAC,CAAC,CACnH,CAAC;YACFN,GAAG,CAACe,UAAU,GAAG,GAAG,CAAC;YACrBf,GAAG,CAACgB,GAAG,EAAE,CAAC;YACV,OAAO;SACR;QACDzB,KAAK,CAAC,aAAa,EAAEqB,QAAQ,CAAC,CAAC;QAC/BZ,GAAG,CAACiB,SAAS,CAAC,UAAU,EAAEL,QAAQ,CAAC,CAAC;QAEpC,kBAAkB;QAClBM,CAAAA,GAAAA,eAAoB,AAAK,CAAA,qBAAL,CAAClB,GAAG,CAAC,CAAC;QAE1B,uBAAuB;QACvBA,GAAG,CAACe,UAAU,GAAG,GAAG,CAAC;QACrBf,GAAG,CAACgB,GAAG,EAAE,CAAC;KACX;CACF;QA7CYvB,yBAAyB,GAAzBA,yBAAyB"}
|
|
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
3
3
|
value: true
|
|
4
4
|
});
|
|
5
5
|
exports.parsePlatformHeader = parsePlatformHeader;
|
|
6
|
+
exports.resolvePlatformFromUserAgentHeader = resolvePlatformFromUserAgentHeader;
|
|
6
7
|
exports.assertMissingRuntimePlatform = assertMissingRuntimePlatform;
|
|
7
8
|
exports.assertRuntimePlatform = assertRuntimePlatform;
|
|
8
9
|
var _url = require("url");
|
|
9
10
|
var _errors = require("../../../utils/errors");
|
|
11
|
+
const debug = require("debug")("expo:start:server:middleware:resolvePlatform");
|
|
10
12
|
function parsePlatformHeader(req) {
|
|
11
13
|
var ref;
|
|
12
14
|
const url = (0, _url).parse(req.url, /* parseQueryString */ true);
|
|
@@ -14,6 +16,18 @@ function parsePlatformHeader(req) {
|
|
|
14
16
|
var ref1;
|
|
15
17
|
return (ref1 = Array.isArray(platform) ? platform[0] : platform) != null ? ref1 : null;
|
|
16
18
|
}
|
|
19
|
+
function resolvePlatformFromUserAgentHeader(req) {
|
|
20
|
+
let platform = null;
|
|
21
|
+
const userAgent = req.headers["user-agent"];
|
|
22
|
+
if (userAgent == null ? void 0 : userAgent.match(/Android/i)) {
|
|
23
|
+
platform = "android";
|
|
24
|
+
}
|
|
25
|
+
if (userAgent == null ? void 0 : userAgent.match(/iPhone|iPad/i)) {
|
|
26
|
+
platform = "ios";
|
|
27
|
+
}
|
|
28
|
+
debug(`Resolved platform ${platform} from user-agent header: ${userAgent}`);
|
|
29
|
+
return platform;
|
|
30
|
+
}
|
|
17
31
|
function assertMissingRuntimePlatform(platform) {
|
|
18
32
|
if (!platform) {
|
|
19
33
|
throw new _errors.CommandError("PLATFORM_HEADER", `Must specify "expo-platform" header or "platform" query parameter`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/middleware/resolvePlatform.ts"],"sourcesContent":["import { parse } from 'url';\n\nimport { CommandError } from '../../../utils/errors';\nimport { ServerRequest } from './server.types';\n\n/** Supported platforms */\nexport type RuntimePlatform = 'ios' | 'android';\n\n/**\n * Extract the runtime platform from the server request.\n * 1. Query param `platform`: `?platform=ios`\n * 2. Header `expo-platform`: `'expo-platform': ios`\n *
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/middleware/resolvePlatform.ts"],"sourcesContent":["import { parse } from 'url';\n\nimport { CommandError } from '../../../utils/errors';\nimport { ServerRequest } from './server.types';\n\nconst debug = require('debug')(\n 'expo:start:server:middleware:resolvePlatform'\n) as typeof console.log;\n\n/** Supported platforms */\nexport type RuntimePlatform = 'ios' | 'android';\n\n/**\n * Extract the runtime platform from the server request.\n * 1. Query param `platform`: `?platform=ios`\n * 2. Header `expo-platform`: `'expo-platform': ios`\n * 3. Legacy header `exponent-platform`: `'exponent-platform': ios`\n *\n * Returns first item in the case of an array.\n */\nexport function parsePlatformHeader(req: ServerRequest): string | null {\n const url = parse(req.url!, /* parseQueryString */ true);\n const platform =\n url.query?.platform || req.headers['expo-platform'] || req.headers['exponent-platform'];\n return (Array.isArray(platform) ? platform[0] : platform) ?? null;\n}\n\n/** Guess the platform from the user-agent header. */\nexport function resolvePlatformFromUserAgentHeader(req: ServerRequest): string | null {\n let platform = null;\n const userAgent = req.headers['user-agent'];\n if (userAgent?.match(/Android/i)) {\n platform = 'android';\n }\n if (userAgent?.match(/iPhone|iPad/i)) {\n platform = 'ios';\n }\n debug(`Resolved platform ${platform} from user-agent header: ${userAgent}`);\n return platform;\n}\n\n/** Assert if the runtime platform is not included. */\nexport function assertMissingRuntimePlatform(platform?: any): asserts platform {\n if (!platform) {\n throw new CommandError(\n 'PLATFORM_HEADER',\n `Must specify \"expo-platform\" header or \"platform\" query parameter`\n );\n }\n}\n\n/** Assert if the runtime platform is not correct. */\nexport function assertRuntimePlatform(platform: string): asserts platform is RuntimePlatform {\n const stringifiedPlatform = String(platform);\n if (!['android', 'ios'].includes(stringifiedPlatform)) {\n throw new CommandError(\n 'PLATFORM_HEADER',\n `platform must be \"android\" or \"ios\". Received: \"${platform}\"`\n );\n }\n}\n"],"names":["parsePlatformHeader","resolvePlatformFromUserAgentHeader","assertMissingRuntimePlatform","assertRuntimePlatform","debug","require","req","url","parse","platform","query","headers","Array","isArray","userAgent","match","CommandError","stringifiedPlatform","String","includes"],"mappings":"AAAA;;;;QAoBgBA,mBAAmB,GAAnBA,mBAAmB;QAQnBC,kCAAkC,GAAlCA,kCAAkC;QAclCC,4BAA4B,GAA5BA,4BAA4B;QAU5BC,qBAAqB,GAArBA,qBAAqB;AApDf,IAAA,IAAK,WAAL,KAAK,CAAA;AAEE,IAAA,OAAuB,WAAvB,uBAAuB,CAAA;AAGpD,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAC5B,8CAA8C,CAC/C,AAAsB,AAAC;AAajB,SAASL,mBAAmB,CAACM,GAAkB,EAAiB;QAGnEC,GAAS;IAFX,MAAMA,GAAG,GAAGC,CAAAA,GAAAA,IAAK,AAAuC,CAAA,MAAvC,CAACF,GAAG,CAACC,GAAG,EAAG,sBAAsB,CAAC,IAAI,CAAC,AAAC;IACzD,MAAME,QAAQ,GACZF,CAAAA,CAAAA,GAAS,GAATA,GAAG,CAACG,KAAK,SAAU,GAAnBH,KAAAA,CAAmB,GAAnBA,GAAS,CAAEE,QAAQ,CAAA,IAAIH,GAAG,CAACK,OAAO,CAAC,eAAe,CAAC,IAAIL,GAAG,CAACK,OAAO,CAAC,mBAAmB,CAAC,AAAC;QACnF,IAAkD;IAAzD,OAAO,CAAA,IAAkD,GAAjDC,KAAK,CAACC,OAAO,CAACJ,QAAQ,CAAC,GAAGA,QAAQ,CAAC,CAAC,CAAC,GAAGA,QAAQ,YAAjD,IAAkD,GAAI,IAAI,CAAC;CACnE;AAGM,SAASR,kCAAkC,CAACK,GAAkB,EAAiB;IACpF,IAAIG,QAAQ,GAAG,IAAI,AAAC;IACpB,MAAMK,SAAS,GAAGR,GAAG,CAACK,OAAO,CAAC,YAAY,CAAC,AAAC;IAC5C,IAAIG,SAAS,QAAO,GAAhBA,KAAAA,CAAgB,GAAhBA,SAAS,CAAEC,KAAK,YAAY,EAAE;QAChCN,QAAQ,GAAG,SAAS,CAAC;KACtB;IACD,IAAIK,SAAS,QAAO,GAAhBA,KAAAA,CAAgB,GAAhBA,SAAS,CAAEC,KAAK,gBAAgB,EAAE;QACpCN,QAAQ,GAAG,KAAK,CAAC;KAClB;IACDL,KAAK,CAAC,CAAC,kBAAkB,EAAEK,QAAQ,CAAC,yBAAyB,EAAEK,SAAS,CAAC,CAAC,CAAC,CAAC;IAC5E,OAAOL,QAAQ,CAAC;CACjB;AAGM,SAASP,4BAA4B,CAACO,QAAc,EAAoB;IAC7E,IAAI,CAACA,QAAQ,EAAE;QACb,MAAM,IAAIO,OAAY,aAAA,CACpB,iBAAiB,EACjB,CAAC,iEAAiE,CAAC,CACpE,CAAC;KACH;CACF;AAGM,SAASb,qBAAqB,CAACM,QAAgB,EAAuC;IAC3F,MAAMQ,mBAAmB,GAAGC,MAAM,CAACT,QAAQ,CAAC,AAAC;IAC7C,IAAI,CAAC;QAAC,SAAS;QAAE,KAAK;KAAC,CAACU,QAAQ,CAACF,mBAAmB,CAAC,EAAE;QACrD,MAAM,IAAID,OAAY,aAAA,CACpB,iBAAiB,EACjB,CAAC,gDAAgD,EAAEP,QAAQ,CAAC,CAAC,CAAC,CAC/D,CAAC;KACH;CACF"}
|
|
@@ -94,7 +94,7 @@ async function logEventAsync(event, properties = {}) {
|
|
|
94
94
|
}
|
|
95
95
|
const { userId , deviceId } = identifyData;
|
|
96
96
|
const commonEventProperties = {
|
|
97
|
-
source_version: "0.
|
|
97
|
+
source_version: "0.3.0",
|
|
98
98
|
source: "expo"
|
|
99
99
|
};
|
|
100
100
|
const identity = {
|
|
@@ -135,7 +135,7 @@ function getContext() {
|
|
|
135
135
|
},
|
|
136
136
|
app: {
|
|
137
137
|
name: "expo",
|
|
138
|
-
version: "0.
|
|
138
|
+
version: "0.3.0"
|
|
139
139
|
},
|
|
140
140
|
ci: ciInfo.isCI ? {
|
|
141
141
|
name: ciInfo.name,
|
package/build/src/utils/env.js
CHANGED
|
@@ -46,8 +46,8 @@ class Env {
|
|
|
46
46
|
/** Disable all API caches. Does not disable bundler caches. */ get EXPO_NO_CACHE() {
|
|
47
47
|
return (0, _getenv).boolish("EXPO_NO_CACHE", false);
|
|
48
48
|
}
|
|
49
|
-
/**
|
|
50
|
-
return (0, _getenv).boolish("
|
|
49
|
+
/** Disable the app select redirect page. */ get EXPO_NO_REDIRECT_PAGE() {
|
|
50
|
+
return (0, _getenv).boolish("EXPO_NO_REDIRECT_PAGE", false);
|
|
51
51
|
}
|
|
52
52
|
/** The React Metro port that's baked into react-native scripts and tools. */ get RCT_METRO_PORT() {
|
|
53
53
|
return (0, _getenv).int("RCT_METRO_PORT", 0);
|