@expo/cli 0.19.13 → 0.19.14
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 +1 -1
- package/build/src/api/graphql/client.js +0 -1
- package/build/src/api/graphql/client.js.map +1 -1
- package/build/src/api/graphql/queries/AppQuery.js +6 -17
- package/build/src/api/graphql/queries/AppQuery.js.map +1 -1
- package/build/src/api/graphql/queries/UserQuery.js +4 -9
- package/build/src/api/graphql/queries/UserQuery.js.map +1 -1
- package/build/src/api/graphql/types/App.js +4 -9
- package/build/src/api/graphql/types/App.js.map +1 -1
- package/build/src/api/user/user.js +7 -12
- package/build/src/api/user/user.js.map +1 -1
- package/build/src/export/embed/exportEmbedAsync.js +4 -1
- package/build/src/export/embed/exportEmbedAsync.js.map +1 -1
- package/build/src/start/server/metro/instantiateMetro.js +2 -2
- package/build/src/start/server/metro/instantiateMetro.js.map +1 -1
- package/build/src/start/server/type-generation/routes.js +20 -5
- package/build/src/start/server/type-generation/routes.js.map +1 -1
- package/build/src/start/server/type-generation/startTypescriptTypeGeneration.js +3 -1
- package/build/src/start/server/type-generation/startTypescriptTypeGeneration.js.map +1 -1
- package/build/src/utils/codesigning.js +8 -8
- package/build/src/utils/codesigning.js.map +1 -1
- package/build/src/utils/exit.js +59 -2
- package/build/src/utils/exit.js.map +1 -1
- package/build/src/utils/ip.js +89 -1
- package/build/src/utils/ip.js.map +1 -1
- package/build/src/utils/telemetry/clients/FetchClient.js +1 -1
- package/build/src/utils/telemetry/utils/context.js +1 -1
- package/package.json +5 -6
|
@@ -64,17 +64,22 @@ const ARRAY_GROUP_REGEX = /\(\s*\w[\w\s]*?,.*?\)/g;
|
|
|
64
64
|
const CAPTURE_GROUP_REGEX = /[\\(,]\s*(\w[\w\s]*?)\s*(?=[,\\)])/g;
|
|
65
65
|
const TYPED_ROUTES_EXCLUSION_REGEX = /(_layout|[^/]*?\+[^/]*?)\.[tj]sx?$/;
|
|
66
66
|
async function setupTypedRoutes(options) {
|
|
67
|
-
|
|
67
|
+
/*
|
|
68
|
+
* In SDK 51, TypedRoutes was moved out of cli and into expo-router. For now we need to support both
|
|
69
|
+
* the legacy and new versions of TypedRoutes.
|
|
70
|
+
*
|
|
71
|
+
* TODO (@marklawlor): Remove this check in SDK 53, only support Expo Router v4 and above.
|
|
72
|
+
*/ const typedRoutesModule = _resolveFrom().default.silent(options.projectRoot, "expo-router/build/typed-routes");
|
|
68
73
|
return typedRoutesModule ? typedRoutes(typedRoutesModule, options) : legacyTypedRoutes(options);
|
|
69
74
|
}
|
|
70
|
-
async function typedRoutes(typedRoutesModulePath, { server , metro , typesDirectory , projectRoot , routerDirectory }) {
|
|
71
|
-
|
|
75
|
+
async function typedRoutes(typedRoutesModulePath, { server , metro , typesDirectory , projectRoot , routerDirectory , plugin }) {
|
|
76
|
+
/*
|
|
72
77
|
* Expo Router uses EXPO_ROUTER_APP_ROOT in multiple places to determine the root of the project.
|
|
73
78
|
* In apps compiled by Metro, this code is compiled away. But Typed Routes run in NodeJS with no compilation
|
|
74
79
|
* so we need to explicitly set it.
|
|
75
80
|
*/ process.env.EXPO_ROUTER_APP_ROOT = routerDirectory;
|
|
76
81
|
const typedRoutesModule = require(typedRoutesModulePath);
|
|
77
|
-
|
|
82
|
+
/*
|
|
78
83
|
* Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`
|
|
79
84
|
*/ if (metro && server) {
|
|
80
85
|
// Setup out watcher first
|
|
@@ -90,7 +95,17 @@ async function typedRoutes(typedRoutesModulePath, { server , metro , typesDirect
|
|
|
90
95
|
callback: typedRoutesModule.getWatchHandler(typesDirectory)
|
|
91
96
|
});
|
|
92
97
|
}
|
|
93
|
-
|
|
98
|
+
/*
|
|
99
|
+
* In SDK 52, the `regenerateDeclarations` was changed to accept plugin options.
|
|
100
|
+
* This function has an optional parameter that we cannot override, so we need to ensure the user
|
|
101
|
+
* is using a compatible version of `expo-router`. Otherwise, we will fallback to the old method.
|
|
102
|
+
*
|
|
103
|
+
* TODO(@marklawlor): In SDK53+ we should remove this check and always use the new method.
|
|
104
|
+
*/ if ("version" in typedRoutesModule && typedRoutesModule.version >= 52) {
|
|
105
|
+
typedRoutesModule.regenerateDeclarations(typesDirectory, plugin);
|
|
106
|
+
} else {
|
|
107
|
+
typedRoutesModule.regenerateDeclarations(typesDirectory);
|
|
108
|
+
}
|
|
94
109
|
}
|
|
95
110
|
async function legacyTypedRoutes({ server , metro , typesDirectory , projectRoot , routerDirectory }) {
|
|
96
111
|
const { filePathToRoute , staticRoutes , dynamicRoutes , addFilePath , isRouteFile } = getTypedRoutesUtils(routerDirectory);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/type-generation/routes.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport debounce from 'lodash.debounce';\nimport { Server } from 'metro';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { directoryExistsAsync } from '../../../utils/dir';\nimport { unsafeTemplate } from '../../../utils/template';\nimport { ServerLike } from '../BundlerDevServer';\nimport { metroWatchTypeScriptFiles } from '../metro/metroWatchTypeScriptFiles';\n\n// /test/[...param1]/[param2]/[param3] - captures [\"param1\", \"param2\", \"param3\"]\nexport const CAPTURE_DYNAMIC_PARAMS = /\\[(?:\\.{3})?(\\w*?)[\\]$]/g;\n// /[...param1]/ - Match [...param1]\nexport const CATCH_ALL = /\\[\\.\\.\\..+?\\]/g;\n// /[param1] - Match [param1]\nexport const SLUG = /\\[.+?\\]/g;\n// /(group1,group2,group3)/test - match (group1,group2,group3)\nexport const ARRAY_GROUP_REGEX = /\\(\\s*\\w[\\w\\s]*?,.*?\\)/g;\n// /(group1,group2,group3)/test - captures [\"group1\", \"group2\", \"group3\"]\nexport const CAPTURE_GROUP_REGEX = /[\\\\(,]\\s*(\\w[\\w\\s]*?)\\s*(?=[,\\\\)])/g;\n/**\n * Match:\n * - _layout files, +html, +not-found, string+api, etc\n * - Routes can still use `+`, but it cannot be in the last segment.\n */\nexport const TYPED_ROUTES_EXCLUSION_REGEX = /(_layout|[^/]*?\\+[^/]*?)\\.[tj]sx?$/;\n\nexport interface SetupTypedRoutesOptions {\n server?: ServerLike;\n metro?: Server | null;\n typesDirectory: string;\n projectRoot: string;\n /** Absolute expo router routes directory. */\n routerDirectory: string;\n}\n\nexport async function setupTypedRoutes(options: SetupTypedRoutesOptions) {\n const typedRoutesModule = resolveFrom.silent(\n options.projectRoot,\n 'expo-router/build/typed-routes'\n );\n return typedRoutesModule ? typedRoutes(typedRoutesModule, options) : legacyTypedRoutes(options);\n}\n\nasync function typedRoutes(\n typedRoutesModulePath: any,\n { server, metro, typesDirectory, projectRoot, routerDirectory }: SetupTypedRoutesOptions\n) {\n /**\n * Expo Router uses EXPO_ROUTER_APP_ROOT in multiple places to determine the root of the project.\n * In apps compiled by Metro, this code is compiled away. But Typed Routes run in NodeJS with no compilation\n * so we need to explicitly set it.\n */\n process.env.EXPO_ROUTER_APP_ROOT = routerDirectory;\n\n const typedRoutesModule = require(typedRoutesModulePath);\n\n /**\n * Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n */\n if (metro && server) {\n // Setup out watcher first\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n callback: typedRoutesModule.getWatchHandler(typesDirectory),\n });\n }\n\n typedRoutesModule.regenerateDeclarations(typesDirectory);\n}\n\nasync function legacyTypedRoutes({\n server,\n metro,\n typesDirectory,\n projectRoot,\n routerDirectory,\n}: SetupTypedRoutesOptions) {\n const { filePathToRoute, staticRoutes, dynamicRoutes, addFilePath, isRouteFile } =\n getTypedRoutesUtils(routerDirectory);\n\n // Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n if (metro && server) {\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n async callback({ filePath, type }) {\n if (!isRouteFile(filePath)) {\n return;\n }\n\n let shouldRegenerate = false;\n\n if (type === 'delete') {\n const route = filePathToRoute(filePath);\n staticRoutes.delete(route);\n dynamicRoutes.delete(route);\n shouldRegenerate = true;\n } else {\n shouldRegenerate = addFilePath(filePath);\n }\n\n if (shouldRegenerate) {\n regenerateRouterDotTS(\n typesDirectory,\n new Set([...staticRoutes.values()].flatMap((v) => Array.from(v))),\n new Set([...dynamicRoutes.values()].flatMap((v) => Array.from(v))),\n new Set(dynamicRoutes.keys())\n );\n }\n },\n });\n }\n\n if (await directoryExistsAsync(routerDirectory)) {\n // Do we need to walk the entire tree on startup?\n // Idea: Store the list of files in the last write, then simply check Git for what files have changed\n await walk(routerDirectory, addFilePath);\n }\n\n regenerateRouterDotTS(\n typesDirectory,\n new Set([...staticRoutes.values()].flatMap((v) => Array.from(v))),\n new Set([...dynamicRoutes.values()].flatMap((v) => Array.from(v))),\n new Set(dynamicRoutes.keys())\n );\n}\n\n/**\n * Generate a router.d.ts file that contains all of the routes in the project.\n * Should be debounced as its very common for developers to make changes to multiple files at once (eg Save All)\n */\nconst regenerateRouterDotTS = debounce(\n async (\n typesDir: string,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n ) => {\n await fs.mkdir(typesDir, { recursive: true });\n await fs.writeFile(\n path.resolve(typesDir, './router.d.ts'),\n getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates)\n );\n },\n 100\n);\n\n/*\n * This is exported for testing purposes\n */\nexport function getTemplateString(\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n) {\n return routerDotTSTemplate({\n staticRoutes: setToUnionType(staticRoutes),\n dynamicRoutes: setToUnionType(dynamicRoutes),\n dynamicRouteParams: setToUnionType(dynamicRouteTemplates),\n });\n}\n\n/**\n * Utility functions for typed routes\n *\n * These are extracted for easier testing\n */\nexport function getTypedRoutesUtils(appRoot: string, filePathSeperator = path.sep) {\n /*\n * staticRoutes are a map where the key if the route without groups and the value\n * is another set of all group versions of the route. e.g,\n * Map([\n * [\"/\", [\"/(app)/(notes)\", \"/(app)/(profile)\"]\n * ])\n */\n const staticRoutes = new Map<string, Set<string>>([['/', new Set('/')]]);\n /*\n * dynamicRoutes are the same as staticRoutes (key if the resolved route,\n * and the value is a set of possible routes). e.g:\n *\n * /[...fruits] -> /${CatchAllRoutePart<T>}\n * /color/[color] -> /color/${SingleRoutePart<T>}\n *\n * The keys of this map are also important, as they can be used as \"static\" types\n * <Link href={{ pathname: \"/[...fruits]\",params: { fruits: [\"apple\"] } }} />\n */\n const dynamicRoutes = new Map<string, Set<string>>();\n\n function normalizedFilePath(filePath: string) {\n return filePath.replaceAll(filePathSeperator, '/');\n }\n\n const normalizedAppRoot = normalizedFilePath(appRoot);\n\n const filePathToRoute = (filePath: string) => {\n return normalizedFilePath(filePath)\n .replace(normalizedAppRoot, '')\n .replace(/index\\.[jt]sx?/, '')\n .replace(/\\.[jt]sx?$/, '');\n };\n\n const isRouteFile = (filePath: string) => {\n if (filePath.match(TYPED_ROUTES_EXCLUSION_REGEX)) {\n return false;\n }\n\n // Route files must be nested with in the appRoot\n const relative = path.relative(appRoot, filePath);\n return relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n };\n\n const addFilePath = (filePath: string): boolean => {\n if (!isRouteFile(filePath)) {\n return false;\n }\n\n const route = filePathToRoute(filePath);\n\n // We have already processed this file\n if (staticRoutes.has(route) || dynamicRoutes.has(route)) {\n return false;\n }\n\n const dynamicParams = new Set(\n [...route.matchAll(CAPTURE_DYNAMIC_PARAMS)].map((match) => match[1])\n );\n const isDynamic = dynamicParams.size > 0;\n\n const addRoute = (originalRoute: string, route: string) => {\n if (isDynamic) {\n let set = dynamicRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n dynamicRoutes.set(originalRoute, set);\n }\n\n set.add(\n route\n .replaceAll(CATCH_ALL, '${CatchAllRoutePart<T>}')\n .replaceAll(SLUG, '${SingleRoutePart<T>}')\n );\n } else {\n let set = staticRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n staticRoutes.set(originalRoute, set);\n }\n\n set.add(route);\n }\n };\n\n if (!route.match(ARRAY_GROUP_REGEX)) {\n addRoute(route, route);\n }\n\n // Does this route have a group? eg /(group)\n if (route.includes('/(')) {\n const routeWithoutGroups = route.replace(/\\/\\(.+?\\)/g, '');\n addRoute(route, routeWithoutGroups);\n\n // If there are multiple groups, we need to expand them\n // eg /(test1,test2)/page => /test1/page & /test2/page\n for (const routeWithSingleGroup of extrapolateGroupRoutes(route)) {\n addRoute(route, routeWithSingleGroup);\n }\n }\n\n return true;\n };\n\n return {\n staticRoutes,\n dynamicRoutes,\n filePathToRoute,\n addFilePath,\n isRouteFile,\n };\n}\n\nexport const setToUnionType = <T>(set: Set<T>) => {\n return set.size > 0 ? [...set].map((s) => `\\`${s}\\``).join(' | ') : 'never';\n};\n\n/**\n * Recursively walk a directory and call the callback with the file path.\n */\nasync function walk(directory: string, callback: (filePath: string) => void) {\n const files = await fs.readdir(directory);\n for (const file of files) {\n const p = path.join(directory, file);\n if ((await fs.stat(p)).isDirectory()) {\n await walk(p, callback);\n } else {\n // Normalise the paths so they are easier to convert to URLs\n const normalizedPath = p.replaceAll(path.sep, '/');\n callback(normalizedPath);\n }\n }\n}\n\n/**\n * Given a route, return all possible routes that could be generated from it.\n */\nexport function extrapolateGroupRoutes(\n route: string,\n routes: Set<string> = new Set()\n): Set<string> {\n // Create a version with no groups. We will then need to cleanup double and/or trailing slashes\n routes.add(route.replaceAll(ARRAY_GROUP_REGEX, '').replaceAll(/\\/+/g, '/').replace(/\\/$/, ''));\n\n const match = route.match(ARRAY_GROUP_REGEX);\n\n if (!match) {\n routes.add(route);\n return routes;\n }\n\n const groupsMatch = match[0];\n\n for (const group of groupsMatch.matchAll(CAPTURE_GROUP_REGEX)) {\n extrapolateGroupRoutes(route.replace(groupsMatch, `(${group[1].trim()})`), routes);\n }\n\n return routes;\n}\n\n/**\n * NOTE: This code refers to a specific version of `expo-router` and is therefore unsafe to\n * mix with arbitrary versions.\n * TODO: Version this code with `expo-router` or version expo-router with `@expo/cli`.\n */\nconst routerDotTSTemplate = unsafeTemplate`/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable import/export */\n/* eslint-disable @typescript-eslint/ban-types */\ndeclare module \"expo-router\" {\n import type { LinkProps as OriginalLinkProps } from 'expo-router/build/link/Link';\n import type { Router as OriginalRouter } from 'expo-router/build/types';\n export * from 'expo-router/build';\n\n // prettier-ignore\n type StaticRoutes = ${'staticRoutes'};\n // prettier-ignore\n type DynamicRoutes<T extends string> = ${'dynamicRoutes'};\n // prettier-ignore\n type DynamicRouteTemplate = ${'dynamicRouteParams'};\n\n type RelativePathString = \\`./\\${string}\\` | \\`../\\${string}\\` | '..';\n type AbsoluteRoute = DynamicRouteTemplate | StaticRoutes;\n type ExternalPathString = \\`\\${string}:\\${string}\\`;\n\n type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString;\n export type AllRoutes = ExpoRouterRoutes | ExternalPathString;\n\n /****************\n * Route Utils *\n ****************/\n\n type SearchOrHash = \\`?\\${string}\\` | \\`#\\${string}\\`;\n type UnknownInputParams = Record<string, string | number | (string | number)[]>;\n type UnknownOutputParams = Record<string, string | string[]>;\n\n /**\n * Return only the RoutePart of a string. If the string has multiple parts return never\n *\n * string | type\n * ---------|------\n * 123 | 123\n * /123/abc | never\n * 123?abc | never\n * ./123 | never\n * /123 | never\n * 123/../ | never\n */\n type SingleRoutePart<S extends string> = S extends \\`\\${string}/\\${string}\\`\n ? never\n : S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`(\\${string})\\`\n ? never\n : S extends \\`[\\${string}]\\`\n ? never\n : S;\n\n /**\n * Return only the CatchAll router part. If the string has search parameters or a hash return never\n */\n type CatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`\\${string}(\\${string})\\${string}\\`\n ? never\n : S extends \\`\\${string}[\\${string}]\\${string}\\`\n ? never\n : S;\n\n // type OptionalCatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\` ? never : S\n\n /**\n * Return the name of a route parameter\n * '[test]' -> 'test'\n * 'test' -> never\n * '[...test]' -> '...test'\n */\n type IsParameter<Part> = Part extends \\`[\\${infer ParamName}]\\` ? ParamName : never;\n\n /**\n * Return a union of all parameter names. If there are no names return never\n *\n * /[test] -> 'test'\n * /[abc]/[...def] -> 'abc'|'...def'\n */\n type ParameterNames<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? IsParameter<PartA> | ParameterNames<PartB>\n : IsParameter<Path>;\n\n /**\n * Returns all segements of a route.\n *\n * /(group)/123/abc/[id]/[...rest] -> ['(group)', '123', 'abc', '[id]', '[...rest]'\n */\n type RouteSegments<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? PartA extends '' | '.'\n ? [...RouteSegments<PartB>]\n : [PartA, ...RouteSegments<PartB>]\n : Path extends ''\n ? []\n : [Path];\n\n /**\n * Returns a Record of the routes parameters as strings and CatchAll parameters\n *\n * There are two versions, input and output, as you can input 'string | number' but\n * the output will always be 'string'\n *\n * /[id]/[...rest] -> { id: string, rest: string[] }\n * /no-params -> {}\n */\n type InputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? (string | number)[] : string | number;\n } & UnknownInputParams;\n\n type OutputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? string[] : string;\n } & UnknownOutputParams;\n\n /**\n * Returns the search parameters for a route.\n */\n export type SearchParams<T extends AllRoutes> = T extends DynamicRouteTemplate\n ? OutputRouteParams<T>\n : T extends StaticRoutes\n ? never\n : UnknownOutputParams;\n\n /**\n * Route is mostly used as part of Href to ensure that a valid route is provided\n *\n * Given a dynamic route, this will return never. This is helpful for conditional logic\n *\n * /test -> /test, /test2, etc\n * /test/[abc] -> never\n * /test/resolve -> /test, /test2, etc\n *\n * Note that if we provide a value for [abc] then the route is allowed\n *\n * This is named Route to prevent confusion, as users they will often see it in tooltips\n */\n export type Route<T> = T extends string\n ? T extends DynamicRouteTemplate\n ? never\n :\n | StaticRoutes\n | RelativePathString\n | ExternalPathString\n | (T extends \\`\\${infer P}\\${SearchOrHash}\\`\n ? P extends DynamicRoutes<infer _>\n ? T\n : never\n : T extends DynamicRoutes<infer _>\n ? T\n : never)\n : never;\n\n /*********\n * Href *\n *********/\n\n export type Href<T> = T extends Record<'pathname', string> ? HrefObject<T> : Route<T>;\n\n export type HrefObject<\n R extends Record<'pathname', string>,\n P = R['pathname'],\n > = P extends DynamicRouteTemplate\n ? { pathname: P; params: InputRouteParams<P> }\n : P extends Route<P>\n ? { pathname: Route<P> | DynamicRouteTemplate; params?: never | InputRouteParams<never> }\n : never;\n\n /***********************\n * Expo Router Exports *\n ***********************/\n\n export type Router = Omit<OriginalRouter, 'push' | 'replace' | 'setParams'> & {\n /** Navigate to the provided href. */\n push: <T>(href: Href<T>) => void;\n /** Navigate to route without appending to the history. */\n replace: <T>(href: Href<T>) => void;\n /** Update the current route query params. */\n setParams: <T = ''>(params?: T extends '' ? Record<string, string> : InputRouteParams<T>) => void;\n };\n\n /** The imperative router. */\n export const router: Router;\n\n /************\n * <Link /> *\n ************/\n export interface LinkProps<T> extends OriginalLinkProps {\n href: Href<T>;\n }\n\n export interface LinkComponent {\n <T>(props: React.PropsWithChildren<LinkProps<T>>): JSX.Element;\n /** Helper method to resolve an Href object into a string. */\n resolveHref: <T>(href: Href<T>) => string;\n }\n\n /**\n * Component to render link to another route using a path.\n * Uses an anchor tag on the web.\n *\n * @param props.href Absolute path to route (e.g. \\`/feeds/hot\\`).\n * @param props.replace Should replace the current route without adding to the history.\n * @param props.asChild Forward props to child component. Useful for custom buttons.\n * @param props.children Child elements to render the content.\n * @param props.className On web, this sets the HTML \\`class\\` directly. On native, this can be used with CSS interop tools like Nativewind.\n */\n export const Link: LinkComponent;\n\n /** Redirects to the href as soon as the component is mounted. */\n export const Redirect: <T>(\n props: React.PropsWithChildren<{ href: Href<T> }>\n ) => JSX.Element;\n\n /************\n * Hooks *\n ************/\n export function useRouter(): Router;\n\n export function useLocalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n /** @deprecated renamed to \\`useGlobalSearchParams\\` */\n export function useSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useGlobalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useSegments<\n T extends AbsoluteRoute | RouteSegments<AbsoluteRoute> | RelativePathString,\n >(): T extends AbsoluteRoute ? RouteSegments<T> : T extends string ? string[] : T;\n}\n`;\n"],"names":["CAPTURE_DYNAMIC_PARAMS","CATCH_ALL","SLUG","ARRAY_GROUP_REGEX","CAPTURE_GROUP_REGEX","TYPED_ROUTES_EXCLUSION_REGEX","setupTypedRoutes","getTemplateString","getTypedRoutesUtils","setToUnionType","extrapolateGroupRoutes","options","typedRoutesModule","resolveFrom","silent","projectRoot","typedRoutes","legacyTypedRoutes","typedRoutesModulePath","server","metro","typesDirectory","routerDirectory","process","env","EXPO_ROUTER_APP_ROOT","require","metroWatchTypeScriptFiles","eventTypes","callback","getWatchHandler","regenerateDeclarations","filePathToRoute","staticRoutes","dynamicRoutes","addFilePath","isRouteFile","filePath","type","shouldRegenerate","route","delete","regenerateRouterDotTS","Set","values","flatMap","v","Array","from","keys","directoryExistsAsync","walk","debounce","typesDir","dynamicRouteTemplates","fs","mkdir","recursive","writeFile","path","resolve","routerDotTSTemplate","dynamicRouteParams","appRoot","filePathSeperator","sep","Map","normalizedFilePath","replaceAll","normalizedAppRoot","replace","match","relative","startsWith","isAbsolute","has","dynamicParams","matchAll","map","isDynamic","size","addRoute","originalRoute","set","get","add","includes","routeWithoutGroups","routeWithSingleGroup","s","join","directory","files","readdir","file","p","stat","isDirectory","normalizedPath","routes","groupsMatch","group","trim","unsafeTemplate"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/type-generation/routes.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport debounce from 'lodash.debounce';\nimport { Server } from 'metro';\nimport path from 'path';\nimport resolveFrom from 'resolve-from';\n\nimport { directoryExistsAsync } from '../../../utils/dir';\nimport { unsafeTemplate } from '../../../utils/template';\nimport { ServerLike } from '../BundlerDevServer';\nimport { metroWatchTypeScriptFiles } from '../metro/metroWatchTypeScriptFiles';\n\n// /test/[...param1]/[param2]/[param3] - captures [\"param1\", \"param2\", \"param3\"]\nexport const CAPTURE_DYNAMIC_PARAMS = /\\[(?:\\.{3})?(\\w*?)[\\]$]/g;\n// /[...param1]/ - Match [...param1]\nexport const CATCH_ALL = /\\[\\.\\.\\..+?\\]/g;\n// /[param1] - Match [param1]\nexport const SLUG = /\\[.+?\\]/g;\n// /(group1,group2,group3)/test - match (group1,group2,group3)\nexport const ARRAY_GROUP_REGEX = /\\(\\s*\\w[\\w\\s]*?,.*?\\)/g;\n// /(group1,group2,group3)/test - captures [\"group1\", \"group2\", \"group3\"]\nexport const CAPTURE_GROUP_REGEX = /[\\\\(,]\\s*(\\w[\\w\\s]*?)\\s*(?=[,\\\\)])/g;\n/**\n * Match:\n * - _layout files, +html, +not-found, string+api, etc\n * - Routes can still use `+`, but it cannot be in the last segment.\n */\nexport const TYPED_ROUTES_EXCLUSION_REGEX = /(_layout|[^/]*?\\+[^/]*?)\\.[tj]sx?$/;\n\nexport interface SetupTypedRoutesOptions {\n server?: ServerLike;\n metro?: Server | null;\n typesDirectory: string;\n projectRoot: string;\n /** Absolute expo router routes directory. */\n routerDirectory: string;\n plugin?: Record<string, any>;\n}\n\nexport async function setupTypedRoutes(options: SetupTypedRoutesOptions) {\n /*\n * In SDK 51, TypedRoutes was moved out of cli and into expo-router. For now we need to support both\n * the legacy and new versions of TypedRoutes.\n *\n * TODO (@marklawlor): Remove this check in SDK 53, only support Expo Router v4 and above.\n */\n const typedRoutesModule = resolveFrom.silent(\n options.projectRoot,\n 'expo-router/build/typed-routes'\n );\n return typedRoutesModule ? typedRoutes(typedRoutesModule, options) : legacyTypedRoutes(options);\n}\n\nasync function typedRoutes(\n typedRoutesModulePath: any,\n { server, metro, typesDirectory, projectRoot, routerDirectory, plugin }: SetupTypedRoutesOptions\n) {\n /*\n * Expo Router uses EXPO_ROUTER_APP_ROOT in multiple places to determine the root of the project.\n * In apps compiled by Metro, this code is compiled away. But Typed Routes run in NodeJS with no compilation\n * so we need to explicitly set it.\n */\n process.env.EXPO_ROUTER_APP_ROOT = routerDirectory;\n\n const typedRoutesModule = require(typedRoutesModulePath);\n\n /*\n * Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n */\n if (metro && server) {\n // Setup out watcher first\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n callback: typedRoutesModule.getWatchHandler(typesDirectory),\n });\n }\n\n /*\n * In SDK 52, the `regenerateDeclarations` was changed to accept plugin options.\n * This function has an optional parameter that we cannot override, so we need to ensure the user\n * is using a compatible version of `expo-router`. Otherwise, we will fallback to the old method.\n *\n * TODO(@marklawlor): In SDK53+ we should remove this check and always use the new method.\n */\n if ('version' in typedRoutesModule && typedRoutesModule.version >= 52) {\n typedRoutesModule.regenerateDeclarations(typesDirectory, plugin);\n } else {\n typedRoutesModule.regenerateDeclarations(typesDirectory);\n }\n}\n\nasync function legacyTypedRoutes({\n server,\n metro,\n typesDirectory,\n projectRoot,\n routerDirectory,\n}: SetupTypedRoutesOptions) {\n const { filePathToRoute, staticRoutes, dynamicRoutes, addFilePath, isRouteFile } =\n getTypedRoutesUtils(routerDirectory);\n\n // Typed Routes can be run with out Metro or a Server, e.g. `expo customize tsconfig.json`\n if (metro && server) {\n metroWatchTypeScriptFiles({\n projectRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n async callback({ filePath, type }) {\n if (!isRouteFile(filePath)) {\n return;\n }\n\n let shouldRegenerate = false;\n\n if (type === 'delete') {\n const route = filePathToRoute(filePath);\n staticRoutes.delete(route);\n dynamicRoutes.delete(route);\n shouldRegenerate = true;\n } else {\n shouldRegenerate = addFilePath(filePath);\n }\n\n if (shouldRegenerate) {\n regenerateRouterDotTS(\n typesDirectory,\n new Set([...staticRoutes.values()].flatMap((v) => Array.from(v))),\n new Set([...dynamicRoutes.values()].flatMap((v) => Array.from(v))),\n new Set(dynamicRoutes.keys())\n );\n }\n },\n });\n }\n\n if (await directoryExistsAsync(routerDirectory)) {\n // Do we need to walk the entire tree on startup?\n // Idea: Store the list of files in the last write, then simply check Git for what files have changed\n await walk(routerDirectory, addFilePath);\n }\n\n regenerateRouterDotTS(\n typesDirectory,\n new Set([...staticRoutes.values()].flatMap((v) => Array.from(v))),\n new Set([...dynamicRoutes.values()].flatMap((v) => Array.from(v))),\n new Set(dynamicRoutes.keys())\n );\n}\n\n/**\n * Generate a router.d.ts file that contains all of the routes in the project.\n * Should be debounced as its very common for developers to make changes to multiple files at once (eg Save All)\n */\nconst regenerateRouterDotTS = debounce(\n async (\n typesDir: string,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n ) => {\n await fs.mkdir(typesDir, { recursive: true });\n await fs.writeFile(\n path.resolve(typesDir, './router.d.ts'),\n getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates)\n );\n },\n 100\n);\n\n/*\n * This is exported for testing purposes\n */\nexport function getTemplateString(\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n) {\n return routerDotTSTemplate({\n staticRoutes: setToUnionType(staticRoutes),\n dynamicRoutes: setToUnionType(dynamicRoutes),\n dynamicRouteParams: setToUnionType(dynamicRouteTemplates),\n });\n}\n\n/**\n * Utility functions for typed routes\n *\n * These are extracted for easier testing\n */\nexport function getTypedRoutesUtils(appRoot: string, filePathSeperator = path.sep) {\n /*\n * staticRoutes are a map where the key if the route without groups and the value\n * is another set of all group versions of the route. e.g,\n * Map([\n * [\"/\", [\"/(app)/(notes)\", \"/(app)/(profile)\"]\n * ])\n */\n const staticRoutes = new Map<string, Set<string>>([['/', new Set('/')]]);\n /*\n * dynamicRoutes are the same as staticRoutes (key if the resolved route,\n * and the value is a set of possible routes). e.g:\n *\n * /[...fruits] -> /${CatchAllRoutePart<T>}\n * /color/[color] -> /color/${SingleRoutePart<T>}\n *\n * The keys of this map are also important, as they can be used as \"static\" types\n * <Link href={{ pathname: \"/[...fruits]\",params: { fruits: [\"apple\"] } }} />\n */\n const dynamicRoutes = new Map<string, Set<string>>();\n\n function normalizedFilePath(filePath: string) {\n return filePath.replaceAll(filePathSeperator, '/');\n }\n\n const normalizedAppRoot = normalizedFilePath(appRoot);\n\n const filePathToRoute = (filePath: string) => {\n return normalizedFilePath(filePath)\n .replace(normalizedAppRoot, '')\n .replace(/index\\.[jt]sx?/, '')\n .replace(/\\.[jt]sx?$/, '');\n };\n\n const isRouteFile = (filePath: string) => {\n if (filePath.match(TYPED_ROUTES_EXCLUSION_REGEX)) {\n return false;\n }\n\n // Route files must be nested with in the appRoot\n const relative = path.relative(appRoot, filePath);\n return relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n };\n\n const addFilePath = (filePath: string): boolean => {\n if (!isRouteFile(filePath)) {\n return false;\n }\n\n const route = filePathToRoute(filePath);\n\n // We have already processed this file\n if (staticRoutes.has(route) || dynamicRoutes.has(route)) {\n return false;\n }\n\n const dynamicParams = new Set(\n [...route.matchAll(CAPTURE_DYNAMIC_PARAMS)].map((match) => match[1])\n );\n const isDynamic = dynamicParams.size > 0;\n\n const addRoute = (originalRoute: string, route: string) => {\n if (isDynamic) {\n let set = dynamicRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n dynamicRoutes.set(originalRoute, set);\n }\n\n set.add(\n route\n .replaceAll(CATCH_ALL, '${CatchAllRoutePart<T>}')\n .replaceAll(SLUG, '${SingleRoutePart<T>}')\n );\n } else {\n let set = staticRoutes.get(originalRoute);\n\n if (!set) {\n set = new Set();\n staticRoutes.set(originalRoute, set);\n }\n\n set.add(route);\n }\n };\n\n if (!route.match(ARRAY_GROUP_REGEX)) {\n addRoute(route, route);\n }\n\n // Does this route have a group? eg /(group)\n if (route.includes('/(')) {\n const routeWithoutGroups = route.replace(/\\/\\(.+?\\)/g, '');\n addRoute(route, routeWithoutGroups);\n\n // If there are multiple groups, we need to expand them\n // eg /(test1,test2)/page => /test1/page & /test2/page\n for (const routeWithSingleGroup of extrapolateGroupRoutes(route)) {\n addRoute(route, routeWithSingleGroup);\n }\n }\n\n return true;\n };\n\n return {\n staticRoutes,\n dynamicRoutes,\n filePathToRoute,\n addFilePath,\n isRouteFile,\n };\n}\n\nexport const setToUnionType = <T>(set: Set<T>) => {\n return set.size > 0 ? [...set].map((s) => `\\`${s}\\``).join(' | ') : 'never';\n};\n\n/**\n * Recursively walk a directory and call the callback with the file path.\n */\nasync function walk(directory: string, callback: (filePath: string) => void) {\n const files = await fs.readdir(directory);\n for (const file of files) {\n const p = path.join(directory, file);\n if ((await fs.stat(p)).isDirectory()) {\n await walk(p, callback);\n } else {\n // Normalise the paths so they are easier to convert to URLs\n const normalizedPath = p.replaceAll(path.sep, '/');\n callback(normalizedPath);\n }\n }\n}\n\n/**\n * Given a route, return all possible routes that could be generated from it.\n */\nexport function extrapolateGroupRoutes(\n route: string,\n routes: Set<string> = new Set()\n): Set<string> {\n // Create a version with no groups. We will then need to cleanup double and/or trailing slashes\n routes.add(route.replaceAll(ARRAY_GROUP_REGEX, '').replaceAll(/\\/+/g, '/').replace(/\\/$/, ''));\n\n const match = route.match(ARRAY_GROUP_REGEX);\n\n if (!match) {\n routes.add(route);\n return routes;\n }\n\n const groupsMatch = match[0];\n\n for (const group of groupsMatch.matchAll(CAPTURE_GROUP_REGEX)) {\n extrapolateGroupRoutes(route.replace(groupsMatch, `(${group[1].trim()})`), routes);\n }\n\n return routes;\n}\n\n/**\n * NOTE: This code refers to a specific version of `expo-router` and is therefore unsafe to\n * mix with arbitrary versions.\n * TODO: Version this code with `expo-router` or version expo-router with `@expo/cli`.\n */\nconst routerDotTSTemplate = unsafeTemplate`/* eslint-disable @typescript-eslint/no-unused-vars */\n/* eslint-disable import/export */\n/* eslint-disable @typescript-eslint/ban-types */\ndeclare module \"expo-router\" {\n import type { LinkProps as OriginalLinkProps } from 'expo-router/build/link/Link';\n import type { Router as OriginalRouter } from 'expo-router/build/types';\n export * from 'expo-router/build';\n\n // prettier-ignore\n type StaticRoutes = ${'staticRoutes'};\n // prettier-ignore\n type DynamicRoutes<T extends string> = ${'dynamicRoutes'};\n // prettier-ignore\n type DynamicRouteTemplate = ${'dynamicRouteParams'};\n\n type RelativePathString = \\`./\\${string}\\` | \\`../\\${string}\\` | '..';\n type AbsoluteRoute = DynamicRouteTemplate | StaticRoutes;\n type ExternalPathString = \\`\\${string}:\\${string}\\`;\n\n type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString;\n export type AllRoutes = ExpoRouterRoutes | ExternalPathString;\n\n /****************\n * Route Utils *\n ****************/\n\n type SearchOrHash = \\`?\\${string}\\` | \\`#\\${string}\\`;\n type UnknownInputParams = Record<string, string | number | (string | number)[]>;\n type UnknownOutputParams = Record<string, string | string[]>;\n\n /**\n * Return only the RoutePart of a string. If the string has multiple parts return never\n *\n * string | type\n * ---------|------\n * 123 | 123\n * /123/abc | never\n * 123?abc | never\n * ./123 | never\n * /123 | never\n * 123/../ | never\n */\n type SingleRoutePart<S extends string> = S extends \\`\\${string}/\\${string}\\`\n ? never\n : S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`(\\${string})\\`\n ? never\n : S extends \\`[\\${string}]\\`\n ? never\n : S;\n\n /**\n * Return only the CatchAll router part. If the string has search parameters or a hash return never\n */\n type CatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\`\n ? never\n : S extends ''\n ? never\n : S extends \\`\\${string}(\\${string})\\${string}\\`\n ? never\n : S extends \\`\\${string}[\\${string}]\\${string}\\`\n ? never\n : S;\n\n // type OptionalCatchAllRoutePart<S extends string> = S extends \\`\\${string}\\${SearchOrHash}\\` ? never : S\n\n /**\n * Return the name of a route parameter\n * '[test]' -> 'test'\n * 'test' -> never\n * '[...test]' -> '...test'\n */\n type IsParameter<Part> = Part extends \\`[\\${infer ParamName}]\\` ? ParamName : never;\n\n /**\n * Return a union of all parameter names. If there are no names return never\n *\n * /[test] -> 'test'\n * /[abc]/[...def] -> 'abc'|'...def'\n */\n type ParameterNames<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? IsParameter<PartA> | ParameterNames<PartB>\n : IsParameter<Path>;\n\n /**\n * Returns all segements of a route.\n *\n * /(group)/123/abc/[id]/[...rest] -> ['(group)', '123', 'abc', '[id]', '[...rest]'\n */\n type RouteSegments<Path> = Path extends \\`\\${infer PartA}/\\${infer PartB}\\`\n ? PartA extends '' | '.'\n ? [...RouteSegments<PartB>]\n : [PartA, ...RouteSegments<PartB>]\n : Path extends ''\n ? []\n : [Path];\n\n /**\n * Returns a Record of the routes parameters as strings and CatchAll parameters\n *\n * There are two versions, input and output, as you can input 'string | number' but\n * the output will always be 'string'\n *\n * /[id]/[...rest] -> { id: string, rest: string[] }\n * /no-params -> {}\n */\n type InputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? (string | number)[] : string | number;\n } & UnknownInputParams;\n\n type OutputRouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? string[] : string;\n } & UnknownOutputParams;\n\n /**\n * Returns the search parameters for a route.\n */\n export type SearchParams<T extends AllRoutes> = T extends DynamicRouteTemplate\n ? OutputRouteParams<T>\n : T extends StaticRoutes\n ? never\n : UnknownOutputParams;\n\n /**\n * Route is mostly used as part of Href to ensure that a valid route is provided\n *\n * Given a dynamic route, this will return never. This is helpful for conditional logic\n *\n * /test -> /test, /test2, etc\n * /test/[abc] -> never\n * /test/resolve -> /test, /test2, etc\n *\n * Note that if we provide a value for [abc] then the route is allowed\n *\n * This is named Route to prevent confusion, as users they will often see it in tooltips\n */\n export type Route<T> = T extends string\n ? T extends DynamicRouteTemplate\n ? never\n :\n | StaticRoutes\n | RelativePathString\n | ExternalPathString\n | (T extends \\`\\${infer P}\\${SearchOrHash}\\`\n ? P extends DynamicRoutes<infer _>\n ? T\n : never\n : T extends DynamicRoutes<infer _>\n ? T\n : never)\n : never;\n\n /*********\n * Href *\n *********/\n\n export type Href<T> = T extends Record<'pathname', string> ? HrefObject<T> : Route<T>;\n\n export type HrefObject<\n R extends Record<'pathname', string>,\n P = R['pathname'],\n > = P extends DynamicRouteTemplate\n ? { pathname: P; params: InputRouteParams<P> }\n : P extends Route<P>\n ? { pathname: Route<P> | DynamicRouteTemplate; params?: never | InputRouteParams<never> }\n : never;\n\n /***********************\n * Expo Router Exports *\n ***********************/\n\n export type Router = Omit<OriginalRouter, 'push' | 'replace' | 'setParams'> & {\n /** Navigate to the provided href. */\n push: <T>(href: Href<T>) => void;\n /** Navigate to route without appending to the history. */\n replace: <T>(href: Href<T>) => void;\n /** Update the current route query params. */\n setParams: <T = ''>(params?: T extends '' ? Record<string, string> : InputRouteParams<T>) => void;\n };\n\n /** The imperative router. */\n export const router: Router;\n\n /************\n * <Link /> *\n ************/\n export interface LinkProps<T> extends OriginalLinkProps {\n href: Href<T>;\n }\n\n export interface LinkComponent {\n <T>(props: React.PropsWithChildren<LinkProps<T>>): JSX.Element;\n /** Helper method to resolve an Href object into a string. */\n resolveHref: <T>(href: Href<T>) => string;\n }\n\n /**\n * Component to render link to another route using a path.\n * Uses an anchor tag on the web.\n *\n * @param props.href Absolute path to route (e.g. \\`/feeds/hot\\`).\n * @param props.replace Should replace the current route without adding to the history.\n * @param props.asChild Forward props to child component. Useful for custom buttons.\n * @param props.children Child elements to render the content.\n * @param props.className On web, this sets the HTML \\`class\\` directly. On native, this can be used with CSS interop tools like Nativewind.\n */\n export const Link: LinkComponent;\n\n /** Redirects to the href as soon as the component is mounted. */\n export const Redirect: <T>(\n props: React.PropsWithChildren<{ href: Href<T> }>\n ) => JSX.Element;\n\n /************\n * Hooks *\n ************/\n export function useRouter(): Router;\n\n export function useLocalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n /** @deprecated renamed to \\`useGlobalSearchParams\\` */\n export function useSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useGlobalSearchParams<\n T extends AllRoutes | UnknownOutputParams = UnknownOutputParams,\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useSegments<\n T extends AbsoluteRoute | RouteSegments<AbsoluteRoute> | RelativePathString,\n >(): T extends AbsoluteRoute ? RouteSegments<T> : T extends string ? string[] : T;\n}\n`;\n"],"names":["CAPTURE_DYNAMIC_PARAMS","CATCH_ALL","SLUG","ARRAY_GROUP_REGEX","CAPTURE_GROUP_REGEX","TYPED_ROUTES_EXCLUSION_REGEX","setupTypedRoutes","getTemplateString","getTypedRoutesUtils","setToUnionType","extrapolateGroupRoutes","options","typedRoutesModule","resolveFrom","silent","projectRoot","typedRoutes","legacyTypedRoutes","typedRoutesModulePath","server","metro","typesDirectory","routerDirectory","plugin","process","env","EXPO_ROUTER_APP_ROOT","require","metroWatchTypeScriptFiles","eventTypes","callback","getWatchHandler","version","regenerateDeclarations","filePathToRoute","staticRoutes","dynamicRoutes","addFilePath","isRouteFile","filePath","type","shouldRegenerate","route","delete","regenerateRouterDotTS","Set","values","flatMap","v","Array","from","keys","directoryExistsAsync","walk","debounce","typesDir","dynamicRouteTemplates","fs","mkdir","recursive","writeFile","path","resolve","routerDotTSTemplate","dynamicRouteParams","appRoot","filePathSeperator","sep","Map","normalizedFilePath","replaceAll","normalizedAppRoot","replace","match","relative","startsWith","isAbsolute","has","dynamicParams","matchAll","map","isDynamic","size","addRoute","originalRoute","set","get","add","includes","routeWithoutGroups","routeWithSingleGroup","s","join","directory","files","readdir","file","p","stat","isDirectory","normalizedPath","routes","groupsMatch","group","trim","unsafeTemplate"],"mappings":"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"}
|
|
@@ -52,6 +52,7 @@ async function startTypescriptTypeGenerationAsync({ metro , projectRoot , server
|
|
|
52
52
|
(0, _mergeGitIgnorePaths.removeFromGitIgnore)(gitIgnorePath, "expo-env.d.ts"),
|
|
53
53
|
]);
|
|
54
54
|
} else {
|
|
55
|
+
var ref1;
|
|
55
56
|
const dotExpoDir = (0, _dotExpo.ensureDotExpoProjectDirectoryInitialized)(projectRoot);
|
|
56
57
|
const typesDirectory = _path().default.resolve(dotExpoDir, "./types");
|
|
57
58
|
debug("Ensuring typed routes side-effects are setup (experiments.typedRoutes: true, typesDirectory: %s)", typesDirectory);
|
|
@@ -68,7 +69,8 @@ async function startTypescriptTypeGenerationAsync({ metro , projectRoot , server
|
|
|
68
69
|
server,
|
|
69
70
|
typesDirectory,
|
|
70
71
|
projectRoot,
|
|
71
|
-
routerDirectory: _path().default.join(projectRoot, (0, _router.getRouterDirectoryModuleIdWithManifest)(projectRoot, exp))
|
|
72
|
+
routerDirectory: _path().default.join(projectRoot, (0, _router.getRouterDirectoryModuleIdWithManifest)(projectRoot, exp)),
|
|
73
|
+
plugin: exp == null ? void 0 : (ref1 = exp.extra) == null ? void 0 : ref1.router
|
|
72
74
|
}),
|
|
73
75
|
]);
|
|
74
76
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/type-generation/startTypescriptTypeGeneration.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport fs from 'fs/promises';\nimport { Server } from 'metro';\nimport path from 'path';\n\nimport { removeExpoEnvDTS, writeExpoEnvDTS } from './expo-env';\nimport { setupTypedRoutes } from './routes';\nimport { forceRemovalTSConfig, forceUpdateTSConfig } from './tsconfig';\nimport { removeFromGitIgnore, upsertGitIgnoreContents } from '../../../utils/mergeGitIgnorePaths';\nimport { ensureDotExpoProjectDirectoryInitialized } from '../../project/dotExpo';\nimport { ServerLike } from '../BundlerDevServer';\nimport { getRouterDirectoryModuleIdWithManifest } from '../metro/router';\n\nexport interface TypeScriptTypeGenerationOptions {\n server?: ServerLike;\n metro?: Server | null;\n projectRoot: string;\n}\n\nconst debug = require('debug')('expo:typed-routes') as typeof console.log;\n\n/** Setup all requisite features for statically typed routes in Expo Router v2 / SDK +49. */\nexport async function startTypescriptTypeGenerationAsync({\n metro,\n projectRoot,\n server,\n}: TypeScriptTypeGenerationOptions) {\n const { exp } = getConfig(projectRoot);\n\n // If typed routes are disabled, remove any files that were added.\n if (!exp.experiments?.typedRoutes) {\n debug('Removing typed routes side-effects (experiments.typedRoutes: false)');\n const gitIgnorePath = path.join(projectRoot, '.gitignore');\n await Promise.all([\n forceRemovalTSConfig(projectRoot),\n removeExpoEnvDTS(projectRoot),\n removeFromGitIgnore(gitIgnorePath, 'expo-env.d.ts'),\n ]);\n } else {\n const dotExpoDir = ensureDotExpoProjectDirectoryInitialized(projectRoot);\n const typesDirectory = path.resolve(dotExpoDir, './types');\n debug(\n 'Ensuring typed routes side-effects are setup (experiments.typedRoutes: true, typesDirectory: %s)',\n typesDirectory\n );\n\n // Ensure the types directory exists.\n await fs.mkdir(typesDirectory, { recursive: true });\n\n await Promise.all([\n upsertGitIgnoreContents(path.join(projectRoot, '.gitignore'), 'expo-env.d.ts'),\n writeExpoEnvDTS(projectRoot),\n forceUpdateTSConfig(projectRoot),\n setupTypedRoutes({\n metro,\n server,\n typesDirectory,\n projectRoot,\n routerDirectory: path.join(\n projectRoot,\n getRouterDirectoryModuleIdWithManifest(projectRoot, exp)\n ),\n }),\n ]);\n }\n}\n"],"names":["startTypescriptTypeGenerationAsync","debug","require","metro","projectRoot","server","exp","getConfig","experiments","typedRoutes","gitIgnorePath","path","join","Promise","all","forceRemovalTSConfig","removeExpoEnvDTS","removeFromGitIgnore","dotExpoDir","ensureDotExpoProjectDirectoryInitialized","typesDirectory","resolve","fs","mkdir","recursive","upsertGitIgnoreContents","writeExpoEnvDTS","forceUpdateTSConfig","setupTypedRoutes","routerDirectory","getRouterDirectoryModuleIdWithManifest"],"mappings":"AAAA;;;;+BAsBsBA,oCAAkC;;aAAlCA,kCAAkC;;;yBAtB9B,cAAc;;;;;;;8DACzB,aAAa;;;;;;;8DAEX,MAAM;;;;;;yBAE2B,YAAY;wBAC7B,UAAU;0BACe,YAAY;qCACT,oCAAoC;yBACxC,uBAAuB;wBAEzB,iBAAiB;;;;;;AAQxE,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,AAAsB,AAAC;AAGnE,eAAeF,kCAAkC,CAAC,EACvDG,KAAK,CAAA,EACLC,WAAW,CAAA,EACXC,MAAM,CAAA,EAC0B,EAAE;QAI7BC,GAAe;IAHpB,MAAM,EAAEA,GAAG,CAAA,EAAE,GAAGC,IAAAA,OAAS,EAAA,UAAA,EAACH,WAAW,CAAC,AAAC;IAEvC,kEAAkE;IAClE,IAAI,CAACE,CAAAA,CAAAA,GAAe,GAAfA,GAAG,CAACE,WAAW,SAAa,GAA5BF,KAAAA,CAA4B,GAA5BA,GAAe,CAAEG,WAAW,CAAA,EAAE;QACjCR,KAAK,CAAC,qEAAqE,CAAC,CAAC;QAC7E,MAAMS,aAAa,GAAGC,KAAI,EAAA,QAAA,CAACC,IAAI,CAACR,WAAW,EAAE,YAAY,CAAC,AAAC;QAC3D,MAAMS,OAAO,CAACC,GAAG,CAAC;YAChBC,IAAAA,SAAoB,qBAAA,EAACX,WAAW,CAAC;YACjCY,IAAAA,QAAgB,iBAAA,EAACZ,WAAW,CAAC;YAC7Ba,IAAAA,oBAAmB,oBAAA,EAACP,aAAa,EAAE,eAAe,CAAC;SACpD,CAAC,CAAC;IACL,OAAO;
|
|
1
|
+
{"version":3,"sources":["../../../../../src/start/server/type-generation/startTypescriptTypeGeneration.ts"],"sourcesContent":["import { getConfig } from '@expo/config';\nimport fs from 'fs/promises';\nimport { Server } from 'metro';\nimport path from 'path';\n\nimport { removeExpoEnvDTS, writeExpoEnvDTS } from './expo-env';\nimport { setupTypedRoutes } from './routes';\nimport { forceRemovalTSConfig, forceUpdateTSConfig } from './tsconfig';\nimport { removeFromGitIgnore, upsertGitIgnoreContents } from '../../../utils/mergeGitIgnorePaths';\nimport { ensureDotExpoProjectDirectoryInitialized } from '../../project/dotExpo';\nimport { ServerLike } from '../BundlerDevServer';\nimport { getRouterDirectoryModuleIdWithManifest } from '../metro/router';\n\nexport interface TypeScriptTypeGenerationOptions {\n server?: ServerLike;\n metro?: Server | null;\n projectRoot: string;\n}\n\nconst debug = require('debug')('expo:typed-routes') as typeof console.log;\n\n/** Setup all requisite features for statically typed routes in Expo Router v2 / SDK +49. */\nexport async function startTypescriptTypeGenerationAsync({\n metro,\n projectRoot,\n server,\n}: TypeScriptTypeGenerationOptions) {\n const { exp } = getConfig(projectRoot);\n\n // If typed routes are disabled, remove any files that were added.\n if (!exp.experiments?.typedRoutes) {\n debug('Removing typed routes side-effects (experiments.typedRoutes: false)');\n const gitIgnorePath = path.join(projectRoot, '.gitignore');\n await Promise.all([\n forceRemovalTSConfig(projectRoot),\n removeExpoEnvDTS(projectRoot),\n removeFromGitIgnore(gitIgnorePath, 'expo-env.d.ts'),\n ]);\n } else {\n const dotExpoDir = ensureDotExpoProjectDirectoryInitialized(projectRoot);\n const typesDirectory = path.resolve(dotExpoDir, './types');\n debug(\n 'Ensuring typed routes side-effects are setup (experiments.typedRoutes: true, typesDirectory: %s)',\n typesDirectory\n );\n\n // Ensure the types directory exists.\n await fs.mkdir(typesDirectory, { recursive: true });\n\n await Promise.all([\n upsertGitIgnoreContents(path.join(projectRoot, '.gitignore'), 'expo-env.d.ts'),\n writeExpoEnvDTS(projectRoot),\n forceUpdateTSConfig(projectRoot),\n setupTypedRoutes({\n metro,\n server,\n typesDirectory,\n projectRoot,\n routerDirectory: path.join(\n projectRoot,\n getRouterDirectoryModuleIdWithManifest(projectRoot, exp)\n ),\n plugin: exp?.extra?.router,\n }),\n ]);\n }\n}\n"],"names":["startTypescriptTypeGenerationAsync","debug","require","metro","projectRoot","server","exp","getConfig","experiments","typedRoutes","gitIgnorePath","path","join","Promise","all","forceRemovalTSConfig","removeExpoEnvDTS","removeFromGitIgnore","dotExpoDir","ensureDotExpoProjectDirectoryInitialized","typesDirectory","resolve","fs","mkdir","recursive","upsertGitIgnoreContents","writeExpoEnvDTS","forceUpdateTSConfig","setupTypedRoutes","routerDirectory","getRouterDirectoryModuleIdWithManifest","plugin","extra","router"],"mappings":"AAAA;;;;+BAsBsBA,oCAAkC;;aAAlCA,kCAAkC;;;yBAtB9B,cAAc;;;;;;;8DACzB,aAAa;;;;;;;8DAEX,MAAM;;;;;;yBAE2B,YAAY;wBAC7B,UAAU;0BACe,YAAY;qCACT,oCAAoC;yBACxC,uBAAuB;wBAEzB,iBAAiB;;;;;;AAQxE,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,AAAsB,AAAC;AAGnE,eAAeF,kCAAkC,CAAC,EACvDG,KAAK,CAAA,EACLC,WAAW,CAAA,EACXC,MAAM,CAAA,EAC0B,EAAE;QAI7BC,GAAe;IAHpB,MAAM,EAAEA,GAAG,CAAA,EAAE,GAAGC,IAAAA,OAAS,EAAA,UAAA,EAACH,WAAW,CAAC,AAAC;IAEvC,kEAAkE;IAClE,IAAI,CAACE,CAAAA,CAAAA,GAAe,GAAfA,GAAG,CAACE,WAAW,SAAa,GAA5BF,KAAAA,CAA4B,GAA5BA,GAAe,CAAEG,WAAW,CAAA,EAAE;QACjCR,KAAK,CAAC,qEAAqE,CAAC,CAAC;QAC7E,MAAMS,aAAa,GAAGC,KAAI,EAAA,QAAA,CAACC,IAAI,CAACR,WAAW,EAAE,YAAY,CAAC,AAAC;QAC3D,MAAMS,OAAO,CAACC,GAAG,CAAC;YAChBC,IAAAA,SAAoB,qBAAA,EAACX,WAAW,CAAC;YACjCY,IAAAA,QAAgB,iBAAA,EAACZ,WAAW,CAAC;YAC7Ba,IAAAA,oBAAmB,oBAAA,EAACP,aAAa,EAAE,eAAe,CAAC;SACpD,CAAC,CAAC;IACL,OAAO;YAwBOJ,IAAU;QAvBtB,MAAMY,UAAU,GAAGC,IAAAA,QAAwC,yCAAA,EAACf,WAAW,CAAC,AAAC;QACzE,MAAMgB,cAAc,GAAGT,KAAI,EAAA,QAAA,CAACU,OAAO,CAACH,UAAU,EAAE,SAAS,CAAC,AAAC;QAC3DjB,KAAK,CACH,kGAAkG,EAClGmB,cAAc,CACf,CAAC;QAEF,qCAAqC;QACrC,MAAME,SAAE,EAAA,QAAA,CAACC,KAAK,CAACH,cAAc,EAAE;YAAEI,SAAS,EAAE,IAAI;SAAE,CAAC,CAAC;QAEpD,MAAMX,OAAO,CAACC,GAAG,CAAC;YAChBW,IAAAA,oBAAuB,wBAAA,EAACd,KAAI,EAAA,QAAA,CAACC,IAAI,CAACR,WAAW,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC;YAC9EsB,IAAAA,QAAe,gBAAA,EAACtB,WAAW,CAAC;YAC5BuB,IAAAA,SAAmB,oBAAA,EAACvB,WAAW,CAAC;YAChCwB,IAAAA,OAAgB,iBAAA,EAAC;gBACfzB,KAAK;gBACLE,MAAM;gBACNe,cAAc;gBACdhB,WAAW;gBACXyB,eAAe,EAAElB,KAAI,EAAA,QAAA,CAACC,IAAI,CACxBR,WAAW,EACX0B,IAAAA,OAAsC,uCAAA,EAAC1B,WAAW,EAAEE,GAAG,CAAC,CACzD;gBACDyB,MAAM,EAAEzB,GAAG,QAAO,GAAVA,KAAAA,CAAU,GAAVA,CAAAA,IAAU,GAAVA,GAAG,CAAE0B,KAAK,SAAA,GAAV1B,KAAAA,CAAU,GAAVA,IAAU,CAAE2B,MAAM,AAAR;aACnB,CAAC;SACH,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
|
|
@@ -14,6 +14,13 @@ _export(exports, {
|
|
|
14
14
|
getCodeSigningInfoAsync: ()=>getCodeSigningInfoAsync,
|
|
15
15
|
signManifestString: ()=>signManifestString
|
|
16
16
|
});
|
|
17
|
+
function _graphqlWeb() {
|
|
18
|
+
const data = require("@0no-co/graphql.web");
|
|
19
|
+
_graphqlWeb = function() {
|
|
20
|
+
return data;
|
|
21
|
+
};
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
17
24
|
function _codeSigningCertificates() {
|
|
18
25
|
const data = require("@expo/code-signing-certificates");
|
|
19
26
|
_codeSigningCertificates = function() {
|
|
@@ -49,13 +56,6 @@ function _fs() {
|
|
|
49
56
|
};
|
|
50
57
|
return data;
|
|
51
58
|
}
|
|
52
|
-
function _graphql() {
|
|
53
|
-
const data = require("graphql");
|
|
54
|
-
_graphql = function() {
|
|
55
|
-
return data;
|
|
56
|
-
};
|
|
57
|
-
return data;
|
|
58
|
-
}
|
|
59
59
|
function _path() {
|
|
60
60
|
const data = /*#__PURE__*/ _interopRequireDefault(require("path"));
|
|
61
61
|
_path = function() {
|
|
@@ -348,7 +348,7 @@ async function fetchAndCacheNewDevelopmentCodeSigningInfoAsync(easProjectId) {
|
|
|
348
348
|
try {
|
|
349
349
|
app = await _appQuery.AppQuery.byIdAsync(easProjectId);
|
|
350
350
|
} catch (e) {
|
|
351
|
-
if (e instanceof
|
|
351
|
+
if (e instanceof _graphqlWeb().GraphQLError || e instanceof _core().CombinedError) {
|
|
352
352
|
return null;
|
|
353
353
|
}
|
|
354
354
|
throw e;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/codesigning.ts"],"sourcesContent":["import {\n convertCertificatePEMToCertificate,\n convertKeyPairToPEM,\n convertCSRToCSRPEM,\n generateKeyPair,\n generateCSR,\n convertPrivateKeyPEMToPrivateKey,\n validateSelfSignedCertificate,\n signBufferRSASHA256AndVerify,\n} from '@expo/code-signing-certificates';\nimport { ExpoConfig } from '@expo/config';\nimport { getExpoHomeDirectory } from '@expo/config/build/getUserState';\nimport JsonFile, { JSONObject } from '@expo/json-file';\nimport { CombinedError } from '@urql/core';\nimport { promises as fs } from 'fs';\nimport { GraphQLError } from 'graphql';\nimport { pki as PKI } from 'node-forge';\nimport path from 'path';\nimport { Dictionary, parseDictionary } from 'structured-headers';\n\nimport { env } from './env';\nimport { CommandError } from './errors';\nimport { getExpoGoIntermediateCertificateAsync } from '../api/getExpoGoIntermediateCertificate';\nimport { getProjectDevelopmentCertificateAsync } from '../api/getProjectDevelopmentCertificate';\nimport { AppQuery } from '../api/graphql/queries/AppQuery';\nimport { ensureLoggedInAsync } from '../api/user/actions';\nimport { Actor } from '../api/user/user';\nimport { AppByIdQuery, Permission } from '../graphql/generated';\nimport * as Log from '../log';\nimport { learnMore } from '../utils/link';\n\nconst debug = require('debug')('expo:codesigning') as typeof console.log;\n\nexport type CodeSigningInfo = {\n keyId: string;\n privateKey: string;\n certificateForPrivateKey: string;\n /**\n * Chain of certificates to serve in the manifest multipart body \"certificate_chain\" part.\n * The leaf certificate must be the 0th element of the array, followed by any intermediate certificates\n * necessary to evaluate the chain of trust ending in the implicitly trusted root certificate embedded in\n * the client.\n *\n * An empty array indicates that there is no need to serve the certificate chain in the multipart response.\n */\n certificateChainForResponse: string[];\n /**\n * Scope key cached for the project when certificate is development Expo Go code signing.\n * For project-specific code signing (keyId == the project's generated keyId) this is undefined.\n */\n scopeKey: string | null;\n};\n\ntype StoredDevelopmentExpoRootCodeSigningInfo = {\n easProjectId: string | null;\n scopeKey: string | null;\n privateKey: string | null;\n certificateChain: string[] | null;\n};\nconst DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME = 'development-code-signing-settings-2.json';\n\nexport function getDevelopmentCodeSigningDirectory(): string {\n return path.join(getExpoHomeDirectory(), 'codesigning');\n}\n\nfunction getProjectDevelopmentCodeSigningInfoFile<T extends JSONObject>(defaults: T) {\n function getFile(easProjectId: string): JsonFile<T> {\n const filePath = path.join(\n getDevelopmentCodeSigningDirectory(),\n easProjectId,\n DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME\n );\n return new JsonFile<T>(filePath);\n }\n\n async function readAsync(easProjectId: string): Promise<T> {\n let projectSettings;\n try {\n projectSettings = await getFile(easProjectId).readAsync();\n } catch {\n projectSettings = await getFile(easProjectId).writeAsync(defaults, { ensureDir: true });\n }\n // Set defaults for any missing fields\n return { ...defaults, ...projectSettings };\n }\n\n async function setAsync(easProjectId: string, json: Partial<T>): Promise<T> {\n try {\n return await getFile(easProjectId).mergeAsync(json, {\n cantReadFileDefault: defaults,\n });\n } catch {\n return await getFile(easProjectId).writeAsync(\n {\n ...defaults,\n ...json,\n },\n { ensureDir: true }\n );\n }\n }\n\n return {\n getFile,\n readAsync,\n setAsync,\n };\n}\n\nexport const DevelopmentCodeSigningInfoFile =\n getProjectDevelopmentCodeSigningInfoFile<StoredDevelopmentExpoRootCodeSigningInfo>({\n easProjectId: null,\n scopeKey: null,\n privateKey: null,\n certificateChain: null,\n });\n\n/**\n * Get info necessary to generate a response `expo-signature` header given a project and incoming request `expo-expect-signature` header.\n * This only knows how to serve two code signing keyids:\n * - `expo-root` indicates that it should use a development certificate in the `expo-root` chain. See {@link getExpoRootDevelopmentCodeSigningInfoAsync}\n * - <developer's expo-updates keyid> indicates that it should sign with the configured certificate. See {@link getProjectCodeSigningCertificateAsync}\n */\nexport async function getCodeSigningInfoAsync(\n exp: ExpoConfig,\n expectSignatureHeader: string | null,\n privateKeyPath: string | undefined\n): Promise<CodeSigningInfo | null> {\n if (!expectSignatureHeader) {\n return null;\n }\n\n let parsedExpectSignature: Dictionary;\n try {\n parsedExpectSignature = parseDictionary(expectSignatureHeader);\n } catch {\n throw new CommandError('Invalid value for expo-expect-signature header');\n }\n\n const expectedKeyIdOuter = parsedExpectSignature.get('keyid');\n if (!expectedKeyIdOuter) {\n throw new CommandError('keyid not present in expo-expect-signature header');\n }\n\n const expectedKeyId = expectedKeyIdOuter[0];\n if (typeof expectedKeyId !== 'string') {\n throw new CommandError(\n `Invalid value for keyid in expo-expect-signature header: ${expectedKeyId}`\n );\n }\n\n let expectedAlg: string | null = null;\n const expectedAlgOuter = parsedExpectSignature.get('alg');\n if (expectedAlgOuter) {\n const expectedAlgTemp = expectedAlgOuter[0];\n if (typeof expectedAlgTemp !== 'string') {\n throw new CommandError('Invalid value for alg in expo-expect-signature header');\n }\n expectedAlg = expectedAlgTemp;\n }\n\n if (expectedKeyId === 'expo-root') {\n return await getExpoRootDevelopmentCodeSigningInfoAsync(exp);\n } else if (expectedKeyId === 'expo-go') {\n throw new CommandError(\n 'Invalid certificate requested: cannot sign with embedded keyid=expo-go key'\n );\n } else {\n return await getProjectCodeSigningCertificateAsync(\n exp,\n privateKeyPath,\n expectedKeyId,\n expectedAlg\n );\n }\n}\n\n/**\n * Get a development code signing certificate for the expo-root -> expo-go -> (development certificate) certificate chain.\n * This requires the user be logged in and online, otherwise try to use the cached development certificate.\n */\nasync function getExpoRootDevelopmentCodeSigningInfoAsync(\n exp: ExpoConfig\n): Promise<CodeSigningInfo | null> {\n const easProjectId = exp.extra?.eas?.projectId;\n // can't check for scope key validity since scope key is derived on the server from projectId and we may be offline.\n // we rely upon the client certificate check to validate the scope key\n if (!easProjectId) {\n debug(\n `WARN: Expo Application Services (EAS) is not configured for your project. Configuring EAS enables a more secure development experience amongst many other benefits. ${learnMore(\n 'https://docs.expo.dev/eas/'\n )}`\n );\n return null;\n }\n\n const developmentCodeSigningInfoFromFile =\n await DevelopmentCodeSigningInfoFile.readAsync(easProjectId);\n const validatedCodeSigningInfo = validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n developmentCodeSigningInfoFromFile,\n easProjectId\n );\n\n // 1. If online, ensure logged in, generate key pair and CSR, fetch and cache certificate chain for projectId\n // (overwriting existing dev cert in case projectId changed or it has expired)\n if (!env.EXPO_OFFLINE) {\n try {\n return await fetchAndCacheNewDevelopmentCodeSigningInfoAsync(easProjectId);\n } catch (e: any) {\n if (validatedCodeSigningInfo) {\n Log.warn(\n 'There was an error fetching the Expo development certificate, falling back to cached certificate'\n );\n return validatedCodeSigningInfo;\n } else {\n // need to return null here and say a message\n throw e;\n }\n }\n }\n\n // 2. check for cached cert/private key matching projectId and scopeKey of project, if found and valid return private key and cert chain including expo-go cert\n if (validatedCodeSigningInfo) {\n return validatedCodeSigningInfo;\n }\n\n // 3. if offline, return null\n Log.warn('Offline and no cached development certificate found, unable to sign manifest');\n return null;\n}\n\n/**\n * Get the certificate configured for expo-updates for this project.\n */\nasync function getProjectCodeSigningCertificateAsync(\n exp: ExpoConfig,\n privateKeyPath: string | undefined,\n expectedKeyId: string,\n expectedAlg: string | null\n): Promise<CodeSigningInfo | null> {\n const codeSigningCertificatePath = exp.updates?.codeSigningCertificate;\n if (!codeSigningCertificatePath) {\n return null;\n }\n\n if (!privateKeyPath) {\n throw new CommandError(\n 'Must specify --private-key-path argument to sign development manifest for requested code signing key'\n );\n }\n\n const codeSigningMetadata = exp.updates?.codeSigningMetadata;\n if (!codeSigningMetadata) {\n throw new CommandError(\n 'Must specify \"codeSigningMetadata\" under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n const { alg, keyid } = codeSigningMetadata;\n if (!alg || !keyid) {\n throw new CommandError(\n 'Must specify \"keyid\" and \"alg\" in the \"codeSigningMetadata\" field under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n if (expectedKeyId !== keyid) {\n throw new CommandError(`keyid mismatch: client=${expectedKeyId}, project=${keyid}`);\n }\n\n if (expectedAlg && expectedAlg !== alg) {\n throw new CommandError(`\"alg\" field mismatch (client=${expectedAlg}, project=${alg})`);\n }\n\n const { privateKeyPEM, certificatePEM } =\n await getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n });\n\n return {\n keyId: keyid,\n privateKey: privateKeyPEM,\n certificateForPrivateKey: certificatePEM,\n certificateChainForResponse: [],\n scopeKey: null,\n };\n}\n\nasync function readFileWithErrorAsync(path: string, errorMessage: string): Promise<string> {\n try {\n return await fs.readFile(path, 'utf8');\n } catch {\n throw new CommandError(errorMessage);\n }\n}\n\nasync function getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n}: {\n codeSigningCertificatePath: string;\n privateKeyPath: string;\n}): Promise<{ privateKeyPEM: string; certificatePEM: string }> {\n const [codeSigningCertificatePEM, privateKeyPEM] = await Promise.all([\n readFileWithErrorAsync(\n codeSigningCertificatePath,\n `Code signing certificate cannot be read from path: ${codeSigningCertificatePath}`\n ),\n readFileWithErrorAsync(\n privateKeyPath,\n `Code signing private key cannot be read from path: ${privateKeyPath}`\n ),\n ]);\n\n const privateKey = convertPrivateKeyPEMToPrivateKey(privateKeyPEM);\n const certificate = convertCertificatePEMToCertificate(codeSigningCertificatePEM);\n validateSelfSignedCertificate(certificate, {\n publicKey: certificate.publicKey as PKI.rsa.PublicKey,\n privateKey,\n });\n\n return { privateKeyPEM, certificatePEM: codeSigningCertificatePEM };\n}\n\n/**\n * Validate that the cached code signing info is still valid for the current project and\n * that it hasn't expired. If invalid, return null.\n */\nfunction validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n codeSigningInfo: StoredDevelopmentExpoRootCodeSigningInfo,\n easProjectId: string\n): CodeSigningInfo | null {\n if (codeSigningInfo.easProjectId !== easProjectId) {\n return null;\n }\n\n const {\n privateKey: privateKeyPEM,\n certificateChain: certificatePEMs,\n scopeKey,\n } = codeSigningInfo;\n if (!privateKeyPEM || !certificatePEMs) {\n return null;\n }\n\n const certificateChain = certificatePEMs.map((certificatePEM) =>\n convertCertificatePEMToCertificate(certificatePEM)\n );\n\n // TODO(wschurman): maybe move to @expo/code-signing-certificates\n\n // ensure all intermediate certificates are valid\n for (const certificate of certificateChain) {\n const now = new Date();\n if (certificate.validity.notBefore > now || certificate.validity.notAfter < now) {\n return null;\n }\n }\n\n // TODO(wschurman): maybe do more validation, like validation of projectID and scopeKey within eas certificate extension\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: certificatePEMs,\n certificateForPrivateKey: certificatePEMs[0],\n privateKey: privateKeyPEM,\n scopeKey,\n };\n}\n\nfunction actorCanGetProjectDevelopmentCertificate(actor: Actor, app: AppByIdQuery['app']['byId']) {\n const owningAccountId = app.ownerAccount.id;\n\n const owningAccountIsActorPrimaryAccount =\n actor.__typename === 'User' || actor.__typename === 'SSOUser'\n ? actor.primaryAccount.id === owningAccountId\n : false;\n const userHasPublishPermissionForOwningAccount = !!actor.accounts\n .find((account) => account.id === owningAccountId)\n ?.users?.find((userPermission) => userPermission.actor.id === actor.id)\n ?.permissions?.includes(Permission.Publish);\n return owningAccountIsActorPrimaryAccount || userHasPublishPermissionForOwningAccount;\n}\n\nasync function fetchAndCacheNewDevelopmentCodeSigningInfoAsync(\n easProjectId: string\n): Promise<CodeSigningInfo | null> {\n const actor = await ensureLoggedInAsync();\n let app: AppByIdQuery['app']['byId'];\n try {\n app = await AppQuery.byIdAsync(easProjectId);\n } catch (e) {\n if (e instanceof GraphQLError || e instanceof CombinedError) {\n return null;\n }\n throw e;\n }\n if (!actorCanGetProjectDevelopmentCertificate(actor, app)) {\n return null;\n }\n\n const keyPair = generateKeyPair();\n const keyPairPEM = convertKeyPairToPEM(keyPair);\n const csr = generateCSR(keyPair, `Development Certificate for ${easProjectId}`);\n const csrPEM = convertCSRToCSRPEM(csr);\n const [developmentSigningCertificate, expoGoIntermediateCertificate] = await Promise.all([\n getProjectDevelopmentCertificateAsync(easProjectId, csrPEM),\n getExpoGoIntermediateCertificateAsync(easProjectId),\n ]);\n\n await DevelopmentCodeSigningInfoFile.setAsync(easProjectId, {\n easProjectId,\n scopeKey: app.scopeKey,\n privateKey: keyPairPEM.privateKeyPEM,\n certificateChain: [developmentSigningCertificate, expoGoIntermediateCertificate],\n });\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: [developmentSigningCertificate, expoGoIntermediateCertificate],\n certificateForPrivateKey: developmentSigningCertificate,\n privateKey: keyPairPEM.privateKeyPEM,\n scopeKey: app.scopeKey,\n };\n}\n/**\n * Generate the `expo-signature` header for a manifest and code signing info.\n */\nexport function signManifestString(\n stringifiedManifest: string,\n codeSigningInfo: CodeSigningInfo\n): string {\n const privateKey = convertPrivateKeyPEMToPrivateKey(codeSigningInfo.privateKey);\n const certificate = convertCertificatePEMToCertificate(codeSigningInfo.certificateForPrivateKey);\n return signBufferRSASHA256AndVerify(\n privateKey,\n certificate,\n Buffer.from(stringifiedManifest, 'utf8')\n );\n}\n"],"names":["getDevelopmentCodeSigningDirectory","DevelopmentCodeSigningInfoFile","getCodeSigningInfoAsync","signManifestString","debug","require","DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME","path","join","getExpoHomeDirectory","getProjectDevelopmentCodeSigningInfoFile","defaults","getFile","easProjectId","filePath","JsonFile","readAsync","projectSettings","writeAsync","ensureDir","setAsync","json","mergeAsync","cantReadFileDefault","scopeKey","privateKey","certificateChain","exp","expectSignatureHeader","privateKeyPath","parsedExpectSignature","parseDictionary","CommandError","expectedKeyIdOuter","get","expectedKeyId","expectedAlg","expectedAlgOuter","expectedAlgTemp","getExpoRootDevelopmentCodeSigningInfoAsync","getProjectCodeSigningCertificateAsync","extra","eas","projectId","learnMore","developmentCodeSigningInfoFromFile","validatedCodeSigningInfo","validateStoredDevelopmentExpoRootCertificateCodeSigningInfo","env","EXPO_OFFLINE","fetchAndCacheNewDevelopmentCodeSigningInfoAsync","e","Log","warn","codeSigningCertificatePath","updates","codeSigningCertificate","codeSigningMetadata","alg","keyid","privateKeyPEM","certificatePEM","getProjectPrivateKeyAndCertificateFromFilePathsAsync","keyId","certificateForPrivateKey","certificateChainForResponse","readFileWithErrorAsync","errorMessage","fs","readFile","codeSigningCertificatePEM","Promise","all","convertPrivateKeyPEMToPrivateKey","certificate","convertCertificatePEMToCertificate","validateSelfSignedCertificate","publicKey","codeSigningInfo","certificatePEMs","map","now","Date","validity","notBefore","notAfter","actorCanGetProjectDevelopmentCertificate","actor","app","owningAccountId","ownerAccount","id","owningAccountIsActorPrimaryAccount","__typename","primaryAccount","userHasPublishPermissionForOwningAccount","accounts","find","account","users","userPermission","permissions","includes","Permission","Publish","ensureLoggedInAsync","AppQuery","byIdAsync","GraphQLError","CombinedError","keyPair","generateKeyPair","keyPairPEM","convertKeyPairToPEM","csr","generateCSR","csrPEM","convertCSRToCSRPEM","developmentSigningCertificate","expoGoIntermediateCertificate","getProjectDevelopmentCertificateAsync","getExpoGoIntermediateCertificateAsync","stringifiedManifest","signBufferRSASHA256AndVerify","Buffer","from"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/codesigning.ts"],"sourcesContent":["import { GraphQLError } from '@0no-co/graphql.web';\nimport {\n convertCertificatePEMToCertificate,\n convertKeyPairToPEM,\n convertCSRToCSRPEM,\n generateKeyPair,\n generateCSR,\n convertPrivateKeyPEMToPrivateKey,\n validateSelfSignedCertificate,\n signBufferRSASHA256AndVerify,\n} from '@expo/code-signing-certificates';\nimport { ExpoConfig } from '@expo/config';\nimport { getExpoHomeDirectory } from '@expo/config/build/getUserState';\nimport JsonFile, { JSONObject } from '@expo/json-file';\nimport { CombinedError } from '@urql/core';\nimport { promises as fs } from 'fs';\nimport { pki as PKI } from 'node-forge';\nimport path from 'path';\nimport { Dictionary, parseDictionary } from 'structured-headers';\n\nimport { env } from './env';\nimport { CommandError } from './errors';\nimport { getExpoGoIntermediateCertificateAsync } from '../api/getExpoGoIntermediateCertificate';\nimport { getProjectDevelopmentCertificateAsync } from '../api/getProjectDevelopmentCertificate';\nimport { AppQuery } from '../api/graphql/queries/AppQuery';\nimport { ensureLoggedInAsync } from '../api/user/actions';\nimport { Actor } from '../api/user/user';\nimport { AppByIdQuery, Permission } from '../graphql/generated';\nimport * as Log from '../log';\nimport { learnMore } from '../utils/link';\n\nconst debug = require('debug')('expo:codesigning') as typeof console.log;\n\nexport type CodeSigningInfo = {\n keyId: string;\n privateKey: string;\n certificateForPrivateKey: string;\n /**\n * Chain of certificates to serve in the manifest multipart body \"certificate_chain\" part.\n * The leaf certificate must be the 0th element of the array, followed by any intermediate certificates\n * necessary to evaluate the chain of trust ending in the implicitly trusted root certificate embedded in\n * the client.\n *\n * An empty array indicates that there is no need to serve the certificate chain in the multipart response.\n */\n certificateChainForResponse: string[];\n /**\n * Scope key cached for the project when certificate is development Expo Go code signing.\n * For project-specific code signing (keyId == the project's generated keyId) this is undefined.\n */\n scopeKey: string | null;\n};\n\ntype StoredDevelopmentExpoRootCodeSigningInfo = {\n easProjectId: string | null;\n scopeKey: string | null;\n privateKey: string | null;\n certificateChain: string[] | null;\n};\nconst DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME = 'development-code-signing-settings-2.json';\n\nexport function getDevelopmentCodeSigningDirectory(): string {\n return path.join(getExpoHomeDirectory(), 'codesigning');\n}\n\nfunction getProjectDevelopmentCodeSigningInfoFile<T extends JSONObject>(defaults: T) {\n function getFile(easProjectId: string): JsonFile<T> {\n const filePath = path.join(\n getDevelopmentCodeSigningDirectory(),\n easProjectId,\n DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME\n );\n return new JsonFile<T>(filePath);\n }\n\n async function readAsync(easProjectId: string): Promise<T> {\n let projectSettings;\n try {\n projectSettings = await getFile(easProjectId).readAsync();\n } catch {\n projectSettings = await getFile(easProjectId).writeAsync(defaults, { ensureDir: true });\n }\n // Set defaults for any missing fields\n return { ...defaults, ...projectSettings };\n }\n\n async function setAsync(easProjectId: string, json: Partial<T>): Promise<T> {\n try {\n return await getFile(easProjectId).mergeAsync(json, {\n cantReadFileDefault: defaults,\n });\n } catch {\n return await getFile(easProjectId).writeAsync(\n {\n ...defaults,\n ...json,\n },\n { ensureDir: true }\n );\n }\n }\n\n return {\n getFile,\n readAsync,\n setAsync,\n };\n}\n\nexport const DevelopmentCodeSigningInfoFile =\n getProjectDevelopmentCodeSigningInfoFile<StoredDevelopmentExpoRootCodeSigningInfo>({\n easProjectId: null,\n scopeKey: null,\n privateKey: null,\n certificateChain: null,\n });\n\n/**\n * Get info necessary to generate a response `expo-signature` header given a project and incoming request `expo-expect-signature` header.\n * This only knows how to serve two code signing keyids:\n * - `expo-root` indicates that it should use a development certificate in the `expo-root` chain. See {@link getExpoRootDevelopmentCodeSigningInfoAsync}\n * - <developer's expo-updates keyid> indicates that it should sign with the configured certificate. See {@link getProjectCodeSigningCertificateAsync}\n */\nexport async function getCodeSigningInfoAsync(\n exp: ExpoConfig,\n expectSignatureHeader: string | null,\n privateKeyPath: string | undefined\n): Promise<CodeSigningInfo | null> {\n if (!expectSignatureHeader) {\n return null;\n }\n\n let parsedExpectSignature: Dictionary;\n try {\n parsedExpectSignature = parseDictionary(expectSignatureHeader);\n } catch {\n throw new CommandError('Invalid value for expo-expect-signature header');\n }\n\n const expectedKeyIdOuter = parsedExpectSignature.get('keyid');\n if (!expectedKeyIdOuter) {\n throw new CommandError('keyid not present in expo-expect-signature header');\n }\n\n const expectedKeyId = expectedKeyIdOuter[0];\n if (typeof expectedKeyId !== 'string') {\n throw new CommandError(\n `Invalid value for keyid in expo-expect-signature header: ${expectedKeyId}`\n );\n }\n\n let expectedAlg: string | null = null;\n const expectedAlgOuter = parsedExpectSignature.get('alg');\n if (expectedAlgOuter) {\n const expectedAlgTemp = expectedAlgOuter[0];\n if (typeof expectedAlgTemp !== 'string') {\n throw new CommandError('Invalid value for alg in expo-expect-signature header');\n }\n expectedAlg = expectedAlgTemp;\n }\n\n if (expectedKeyId === 'expo-root') {\n return await getExpoRootDevelopmentCodeSigningInfoAsync(exp);\n } else if (expectedKeyId === 'expo-go') {\n throw new CommandError(\n 'Invalid certificate requested: cannot sign with embedded keyid=expo-go key'\n );\n } else {\n return await getProjectCodeSigningCertificateAsync(\n exp,\n privateKeyPath,\n expectedKeyId,\n expectedAlg\n );\n }\n}\n\n/**\n * Get a development code signing certificate for the expo-root -> expo-go -> (development certificate) certificate chain.\n * This requires the user be logged in and online, otherwise try to use the cached development certificate.\n */\nasync function getExpoRootDevelopmentCodeSigningInfoAsync(\n exp: ExpoConfig\n): Promise<CodeSigningInfo | null> {\n const easProjectId = exp.extra?.eas?.projectId;\n // can't check for scope key validity since scope key is derived on the server from projectId and we may be offline.\n // we rely upon the client certificate check to validate the scope key\n if (!easProjectId) {\n debug(\n `WARN: Expo Application Services (EAS) is not configured for your project. Configuring EAS enables a more secure development experience amongst many other benefits. ${learnMore(\n 'https://docs.expo.dev/eas/'\n )}`\n );\n return null;\n }\n\n const developmentCodeSigningInfoFromFile =\n await DevelopmentCodeSigningInfoFile.readAsync(easProjectId);\n const validatedCodeSigningInfo = validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n developmentCodeSigningInfoFromFile,\n easProjectId\n );\n\n // 1. If online, ensure logged in, generate key pair and CSR, fetch and cache certificate chain for projectId\n // (overwriting existing dev cert in case projectId changed or it has expired)\n if (!env.EXPO_OFFLINE) {\n try {\n return await fetchAndCacheNewDevelopmentCodeSigningInfoAsync(easProjectId);\n } catch (e: any) {\n if (validatedCodeSigningInfo) {\n Log.warn(\n 'There was an error fetching the Expo development certificate, falling back to cached certificate'\n );\n return validatedCodeSigningInfo;\n } else {\n // need to return null here and say a message\n throw e;\n }\n }\n }\n\n // 2. check for cached cert/private key matching projectId and scopeKey of project, if found and valid return private key and cert chain including expo-go cert\n if (validatedCodeSigningInfo) {\n return validatedCodeSigningInfo;\n }\n\n // 3. if offline, return null\n Log.warn('Offline and no cached development certificate found, unable to sign manifest');\n return null;\n}\n\n/**\n * Get the certificate configured for expo-updates for this project.\n */\nasync function getProjectCodeSigningCertificateAsync(\n exp: ExpoConfig,\n privateKeyPath: string | undefined,\n expectedKeyId: string,\n expectedAlg: string | null\n): Promise<CodeSigningInfo | null> {\n const codeSigningCertificatePath = exp.updates?.codeSigningCertificate;\n if (!codeSigningCertificatePath) {\n return null;\n }\n\n if (!privateKeyPath) {\n throw new CommandError(\n 'Must specify --private-key-path argument to sign development manifest for requested code signing key'\n );\n }\n\n const codeSigningMetadata = exp.updates?.codeSigningMetadata;\n if (!codeSigningMetadata) {\n throw new CommandError(\n 'Must specify \"codeSigningMetadata\" under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n const { alg, keyid } = codeSigningMetadata;\n if (!alg || !keyid) {\n throw new CommandError(\n 'Must specify \"keyid\" and \"alg\" in the \"codeSigningMetadata\" field under the \"updates\" field of your app config file to use EAS code signing'\n );\n }\n\n if (expectedKeyId !== keyid) {\n throw new CommandError(`keyid mismatch: client=${expectedKeyId}, project=${keyid}`);\n }\n\n if (expectedAlg && expectedAlg !== alg) {\n throw new CommandError(`\"alg\" field mismatch (client=${expectedAlg}, project=${alg})`);\n }\n\n const { privateKeyPEM, certificatePEM } =\n await getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n });\n\n return {\n keyId: keyid,\n privateKey: privateKeyPEM,\n certificateForPrivateKey: certificatePEM,\n certificateChainForResponse: [],\n scopeKey: null,\n };\n}\n\nasync function readFileWithErrorAsync(path: string, errorMessage: string): Promise<string> {\n try {\n return await fs.readFile(path, 'utf8');\n } catch {\n throw new CommandError(errorMessage);\n }\n}\n\nasync function getProjectPrivateKeyAndCertificateFromFilePathsAsync({\n codeSigningCertificatePath,\n privateKeyPath,\n}: {\n codeSigningCertificatePath: string;\n privateKeyPath: string;\n}): Promise<{ privateKeyPEM: string; certificatePEM: string }> {\n const [codeSigningCertificatePEM, privateKeyPEM] = await Promise.all([\n readFileWithErrorAsync(\n codeSigningCertificatePath,\n `Code signing certificate cannot be read from path: ${codeSigningCertificatePath}`\n ),\n readFileWithErrorAsync(\n privateKeyPath,\n `Code signing private key cannot be read from path: ${privateKeyPath}`\n ),\n ]);\n\n const privateKey = convertPrivateKeyPEMToPrivateKey(privateKeyPEM);\n const certificate = convertCertificatePEMToCertificate(codeSigningCertificatePEM);\n validateSelfSignedCertificate(certificate, {\n publicKey: certificate.publicKey as PKI.rsa.PublicKey,\n privateKey,\n });\n\n return { privateKeyPEM, certificatePEM: codeSigningCertificatePEM };\n}\n\n/**\n * Validate that the cached code signing info is still valid for the current project and\n * that it hasn't expired. If invalid, return null.\n */\nfunction validateStoredDevelopmentExpoRootCertificateCodeSigningInfo(\n codeSigningInfo: StoredDevelopmentExpoRootCodeSigningInfo,\n easProjectId: string\n): CodeSigningInfo | null {\n if (codeSigningInfo.easProjectId !== easProjectId) {\n return null;\n }\n\n const {\n privateKey: privateKeyPEM,\n certificateChain: certificatePEMs,\n scopeKey,\n } = codeSigningInfo;\n if (!privateKeyPEM || !certificatePEMs) {\n return null;\n }\n\n const certificateChain = certificatePEMs.map((certificatePEM) =>\n convertCertificatePEMToCertificate(certificatePEM)\n );\n\n // TODO(wschurman): maybe move to @expo/code-signing-certificates\n\n // ensure all intermediate certificates are valid\n for (const certificate of certificateChain) {\n const now = new Date();\n if (certificate.validity.notBefore > now || certificate.validity.notAfter < now) {\n return null;\n }\n }\n\n // TODO(wschurman): maybe do more validation, like validation of projectID and scopeKey within eas certificate extension\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: certificatePEMs,\n certificateForPrivateKey: certificatePEMs[0],\n privateKey: privateKeyPEM,\n scopeKey,\n };\n}\n\nfunction actorCanGetProjectDevelopmentCertificate(actor: Actor, app: AppByIdQuery['app']['byId']) {\n const owningAccountId = app.ownerAccount.id;\n\n const owningAccountIsActorPrimaryAccount =\n actor.__typename === 'User' || actor.__typename === 'SSOUser'\n ? actor.primaryAccount.id === owningAccountId\n : false;\n const userHasPublishPermissionForOwningAccount = !!actor.accounts\n .find((account) => account.id === owningAccountId)\n ?.users?.find((userPermission) => userPermission.actor.id === actor.id)\n ?.permissions?.includes(Permission.Publish);\n return owningAccountIsActorPrimaryAccount || userHasPublishPermissionForOwningAccount;\n}\n\nasync function fetchAndCacheNewDevelopmentCodeSigningInfoAsync(\n easProjectId: string\n): Promise<CodeSigningInfo | null> {\n const actor = await ensureLoggedInAsync();\n let app: AppByIdQuery['app']['byId'];\n try {\n app = await AppQuery.byIdAsync(easProjectId);\n } catch (e) {\n if (e instanceof GraphQLError || e instanceof CombinedError) {\n return null;\n }\n throw e;\n }\n if (!actorCanGetProjectDevelopmentCertificate(actor, app)) {\n return null;\n }\n\n const keyPair = generateKeyPair();\n const keyPairPEM = convertKeyPairToPEM(keyPair);\n const csr = generateCSR(keyPair, `Development Certificate for ${easProjectId}`);\n const csrPEM = convertCSRToCSRPEM(csr);\n const [developmentSigningCertificate, expoGoIntermediateCertificate] = await Promise.all([\n getProjectDevelopmentCertificateAsync(easProjectId, csrPEM),\n getExpoGoIntermediateCertificateAsync(easProjectId),\n ]);\n\n await DevelopmentCodeSigningInfoFile.setAsync(easProjectId, {\n easProjectId,\n scopeKey: app.scopeKey,\n privateKey: keyPairPEM.privateKeyPEM,\n certificateChain: [developmentSigningCertificate, expoGoIntermediateCertificate],\n });\n\n return {\n keyId: 'expo-go',\n certificateChainForResponse: [developmentSigningCertificate, expoGoIntermediateCertificate],\n certificateForPrivateKey: developmentSigningCertificate,\n privateKey: keyPairPEM.privateKeyPEM,\n scopeKey: app.scopeKey,\n };\n}\n/**\n * Generate the `expo-signature` header for a manifest and code signing info.\n */\nexport function signManifestString(\n stringifiedManifest: string,\n codeSigningInfo: CodeSigningInfo\n): string {\n const privateKey = convertPrivateKeyPEMToPrivateKey(codeSigningInfo.privateKey);\n const certificate = convertCertificatePEMToCertificate(codeSigningInfo.certificateForPrivateKey);\n return signBufferRSASHA256AndVerify(\n privateKey,\n certificate,\n Buffer.from(stringifiedManifest, 'utf8')\n );\n}\n"],"names":["getDevelopmentCodeSigningDirectory","DevelopmentCodeSigningInfoFile","getCodeSigningInfoAsync","signManifestString","debug","require","DEVELOPMENT_CODE_SIGNING_SETTINGS_FILE_NAME","path","join","getExpoHomeDirectory","getProjectDevelopmentCodeSigningInfoFile","defaults","getFile","easProjectId","filePath","JsonFile","readAsync","projectSettings","writeAsync","ensureDir","setAsync","json","mergeAsync","cantReadFileDefault","scopeKey","privateKey","certificateChain","exp","expectSignatureHeader","privateKeyPath","parsedExpectSignature","parseDictionary","CommandError","expectedKeyIdOuter","get","expectedKeyId","expectedAlg","expectedAlgOuter","expectedAlgTemp","getExpoRootDevelopmentCodeSigningInfoAsync","getProjectCodeSigningCertificateAsync","extra","eas","projectId","learnMore","developmentCodeSigningInfoFromFile","validatedCodeSigningInfo","validateStoredDevelopmentExpoRootCertificateCodeSigningInfo","env","EXPO_OFFLINE","fetchAndCacheNewDevelopmentCodeSigningInfoAsync","e","Log","warn","codeSigningCertificatePath","updates","codeSigningCertificate","codeSigningMetadata","alg","keyid","privateKeyPEM","certificatePEM","getProjectPrivateKeyAndCertificateFromFilePathsAsync","keyId","certificateForPrivateKey","certificateChainForResponse","readFileWithErrorAsync","errorMessage","fs","readFile","codeSigningCertificatePEM","Promise","all","convertPrivateKeyPEMToPrivateKey","certificate","convertCertificatePEMToCertificate","validateSelfSignedCertificate","publicKey","codeSigningInfo","certificatePEMs","map","now","Date","validity","notBefore","notAfter","actorCanGetProjectDevelopmentCertificate","actor","app","owningAccountId","ownerAccount","id","owningAccountIsActorPrimaryAccount","__typename","primaryAccount","userHasPublishPermissionForOwningAccount","accounts","find","account","users","userPermission","permissions","includes","Permission","Publish","ensureLoggedInAsync","AppQuery","byIdAsync","GraphQLError","CombinedError","keyPair","generateKeyPair","keyPairPEM","convertKeyPairToPEM","csr","generateCSR","csrPEM","convertCSRToCSRPEM","developmentSigningCertificate","expoGoIntermediateCertificate","getProjectDevelopmentCertificateAsync","getExpoGoIntermediateCertificateAsync","stringifiedManifest","signBufferRSASHA256AndVerify","Buffer","from"],"mappings":"AAAA;;;;;;;;;;;IA6DgBA,kCAAkC,MAAlCA,kCAAkC;IAgDrCC,8BAA8B,MAA9BA,8BAA8B;IAcrBC,uBAAuB,MAAvBA,uBAAuB;IAiT7BC,kBAAkB,MAAlBA,kBAAkB;;;yBA5aL,qBAAqB;;;;;;;yBAU3C,iCAAiC;;;;;;;yBAEH,iCAAiC;;;;;;;8DACjC,iBAAiB;;;;;;;yBACxB,YAAY;;;;;;;yBACX,IAAI;;;;;;;8DAElB,MAAM;;;;;;;yBACqB,oBAAoB;;;;;;qBAE5C,OAAO;wBACE,UAAU;kDACe,yCAAyC;kDACzC,yCAAyC;0BACtE,iCAAiC;yBACtB,qBAAqB;2BAEhB,sBAAsB;2DAC1C,QAAQ;sBACH,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEzC,MAAMC,KAAK,GAAGC,OAAO,CAAC,OAAO,CAAC,CAAC,kBAAkB,CAAC,AAAsB,AAAC;AA4BzE,MAAMC,2CAA2C,GAAG,0CAA0C,AAAC;AAExF,SAASN,kCAAkC,GAAW;IAC3D,OAAOO,KAAI,EAAA,QAAA,CAACC,IAAI,CAACC,IAAAA,aAAoB,EAAA,qBAAA,GAAE,EAAE,aAAa,CAAC,CAAC;AAC1D,CAAC;AAED,SAASC,wCAAwC,CAAuBC,QAAW,EAAE;IACnF,SAASC,OAAO,CAACC,YAAoB,EAAe;QAClD,MAAMC,QAAQ,GAAGP,KAAI,EAAA,QAAA,CAACC,IAAI,CACxBR,kCAAkC,EAAE,EACpCa,YAAY,EACZP,2CAA2C,CAC5C,AAAC;QACF,OAAO,IAAIS,CAAAA,SAAQ,EAAA,CAAA,QAAA,CAAID,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,eAAeE,SAAS,CAACH,YAAoB,EAAc;QACzD,IAAII,eAAe,AAAC;QACpB,IAAI;YACFA,eAAe,GAAG,MAAML,OAAO,CAACC,YAAY,CAAC,CAACG,SAAS,EAAE,CAAC;QAC5D,EAAE,OAAM;YACNC,eAAe,GAAG,MAAML,OAAO,CAACC,YAAY,CAAC,CAACK,UAAU,CAACP,QAAQ,EAAE;gBAAEQ,SAAS,EAAE,IAAI;aAAE,CAAC,CAAC;QAC1F,CAAC;QACD,sCAAsC;QACtC,OAAO;YAAE,GAAGR,QAAQ;YAAE,GAAGM,eAAe;SAAE,CAAC;IAC7C,CAAC;IAED,eAAeG,QAAQ,CAACP,YAAoB,EAAEQ,IAAgB,EAAc;QAC1E,IAAI;YACF,OAAO,MAAMT,OAAO,CAACC,YAAY,CAAC,CAACS,UAAU,CAACD,IAAI,EAAE;gBAClDE,mBAAmB,EAAEZ,QAAQ;aAC9B,CAAC,CAAC;QACL,EAAE,OAAM;YACN,OAAO,MAAMC,OAAO,CAACC,YAAY,CAAC,CAACK,UAAU,CAC3C;gBACE,GAAGP,QAAQ;gBACX,GAAGU,IAAI;aACR,EACD;gBAAEF,SAAS,EAAE,IAAI;aAAE,CACpB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACLP,OAAO;QACPI,SAAS;QACTI,QAAQ;KACT,CAAC;AACJ,CAAC;AAEM,MAAMnB,8BAA8B,GACzCS,wCAAwC,CAA2C;IACjFG,YAAY,EAAE,IAAI;IAClBW,QAAQ,EAAE,IAAI;IACdC,UAAU,EAAE,IAAI;IAChBC,gBAAgB,EAAE,IAAI;CACvB,CAAC,AAAC;AAQE,eAAexB,uBAAuB,CAC3CyB,GAAe,EACfC,qBAAoC,EACpCC,cAAkC,EACD;IACjC,IAAI,CAACD,qBAAqB,EAAE;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAIE,qBAAqB,AAAY,AAAC;IACtC,IAAI;QACFA,qBAAqB,GAAGC,IAAAA,kBAAe,EAAA,gBAAA,EAACH,qBAAqB,CAAC,CAAC;IACjE,EAAE,OAAM;QACN,MAAM,IAAII,OAAY,aAAA,CAAC,gDAAgD,CAAC,CAAC;IAC3E,CAAC;IAED,MAAMC,kBAAkB,GAAGH,qBAAqB,CAACI,GAAG,CAAC,OAAO,CAAC,AAAC;IAC9D,IAAI,CAACD,kBAAkB,EAAE;QACvB,MAAM,IAAID,OAAY,aAAA,CAAC,mDAAmD,CAAC,CAAC;IAC9E,CAAC;IAED,MAAMG,aAAa,GAAGF,kBAAkB,CAAC,CAAC,CAAC,AAAC;IAC5C,IAAI,OAAOE,aAAa,KAAK,QAAQ,EAAE;QACrC,MAAM,IAAIH,OAAY,aAAA,CACpB,CAAC,yDAAyD,EAAEG,aAAa,CAAC,CAAC,CAC5E,CAAC;IACJ,CAAC;IAED,IAAIC,WAAW,GAAkB,IAAI,AAAC;IACtC,MAAMC,gBAAgB,GAAGP,qBAAqB,CAACI,GAAG,CAAC,KAAK,CAAC,AAAC;IAC1D,IAAIG,gBAAgB,EAAE;QACpB,MAAMC,eAAe,GAAGD,gBAAgB,CAAC,CAAC,CAAC,AAAC;QAC5C,IAAI,OAAOC,eAAe,KAAK,QAAQ,EAAE;YACvC,MAAM,IAAIN,OAAY,aAAA,CAAC,uDAAuD,CAAC,CAAC;QAClF,CAAC;QACDI,WAAW,GAAGE,eAAe,CAAC;IAChC,CAAC;IAED,IAAIH,aAAa,KAAK,WAAW,EAAE;QACjC,OAAO,MAAMI,0CAA0C,CAACZ,GAAG,CAAC,CAAC;IAC/D,OAAO,IAAIQ,aAAa,KAAK,SAAS,EAAE;QACtC,MAAM,IAAIH,OAAY,aAAA,CACpB,4EAA4E,CAC7E,CAAC;IACJ,OAAO;QACL,OAAO,MAAMQ,qCAAqC,CAChDb,GAAG,EACHE,cAAc,EACdM,aAAa,EACbC,WAAW,CACZ,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;CAGC,GACD,eAAeG,0CAA0C,CACvDZ,GAAe,EACkB;QACZA,GAAS;IAA9B,MAAMd,YAAY,GAAGc,CAAAA,GAAS,GAATA,GAAG,CAACc,KAAK,SAAK,GAAdd,KAAAA,CAAc,GAAdA,QAAAA,GAAS,CAAEe,GAAG,SAAA,GAAdf,KAAAA,CAAc,QAAEgB,SAAS,AAAX,AAAY;IAC/C,oHAAoH;IACpH,sEAAsE;IACtE,IAAI,CAAC9B,YAAY,EAAE;QACjBT,KAAK,CACH,CAAC,oKAAoK,EAAEwC,IAAAA,KAAS,UAAA,EAC9K,4BAA4B,CAC7B,CAAC,CAAC,CACJ,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAMC,kCAAkC,GACtC,MAAM5C,8BAA8B,CAACe,SAAS,CAACH,YAAY,CAAC,AAAC;IAC/D,MAAMiC,wBAAwB,GAAGC,2DAA2D,CAC1FF,kCAAkC,EAClChC,YAAY,CACb,AAAC;IAEF,6GAA6G;IAC7G,iFAAiF;IACjF,IAAI,CAACmC,IAAG,IAAA,CAACC,YAAY,EAAE;QACrB,IAAI;YACF,OAAO,MAAMC,+CAA+C,CAACrC,YAAY,CAAC,CAAC;QAC7E,EAAE,OAAOsC,CAAC,EAAO;YACf,IAAIL,wBAAwB,EAAE;gBAC5BM,IAAG,CAACC,IAAI,CACN,kGAAkG,CACnG,CAAC;gBACF,OAAOP,wBAAwB,CAAC;YAClC,OAAO;gBACL,6CAA6C;gBAC7C,MAAMK,CAAC,CAAC;YACV,CAAC;QACH,CAAC;IACH,CAAC;IAED,+JAA+J;IAC/J,IAAIL,wBAAwB,EAAE;QAC5B,OAAOA,wBAAwB,CAAC;IAClC,CAAC;IAED,6BAA6B;IAC7BM,IAAG,CAACC,IAAI,CAAC,8EAA8E,CAAC,CAAC;IACzF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;CAEC,GACD,eAAeb,qCAAqC,CAClDb,GAAe,EACfE,cAAkC,EAClCM,aAAqB,EACrBC,WAA0B,EACO;QACET,GAAW,EAWlBA,IAAW;IAXvC,MAAM2B,0BAA0B,GAAG3B,CAAAA,GAAW,GAAXA,GAAG,CAAC4B,OAAO,SAAwB,GAAnC5B,KAAAA,CAAmC,GAAnCA,GAAW,CAAE6B,sBAAsB,AAAC;IACvE,IAAI,CAACF,0BAA0B,EAAE;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAACzB,cAAc,EAAE;QACnB,MAAM,IAAIG,OAAY,aAAA,CACpB,sGAAsG,CACvG,CAAC;IACJ,CAAC;IAED,MAAMyB,mBAAmB,GAAG9B,CAAAA,IAAW,GAAXA,GAAG,CAAC4B,OAAO,SAAqB,GAAhC5B,KAAAA,CAAgC,GAAhCA,IAAW,CAAE8B,mBAAmB,AAAC;IAC7D,IAAI,CAACA,mBAAmB,EAAE;QACxB,MAAM,IAAIzB,OAAY,aAAA,CACpB,8GAA8G,CAC/G,CAAC;IACJ,CAAC;IAED,MAAM,EAAE0B,GAAG,CAAA,EAAEC,KAAK,CAAA,EAAE,GAAGF,mBAAmB,AAAC;IAC3C,IAAI,CAACC,GAAG,IAAI,CAACC,KAAK,EAAE;QAClB,MAAM,IAAI3B,OAAY,aAAA,CACpB,6IAA6I,CAC9I,CAAC;IACJ,CAAC;IAED,IAAIG,aAAa,KAAKwB,KAAK,EAAE;QAC3B,MAAM,IAAI3B,OAAY,aAAA,CAAC,CAAC,uBAAuB,EAAEG,aAAa,CAAC,UAAU,EAAEwB,KAAK,CAAC,CAAC,CAAC,CAAC;IACtF,CAAC;IAED,IAAIvB,WAAW,IAAIA,WAAW,KAAKsB,GAAG,EAAE;QACtC,MAAM,IAAI1B,OAAY,aAAA,CAAC,CAAC,6BAA6B,EAAEI,WAAW,CAAC,UAAU,EAAEsB,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,EAAEE,aAAa,CAAA,EAAEC,cAAc,CAAA,EAAE,GACrC,MAAMC,oDAAoD,CAAC;QACzDR,0BAA0B;QAC1BzB,cAAc;KACf,CAAC,AAAC;IAEL,OAAO;QACLkC,KAAK,EAAEJ,KAAK;QACZlC,UAAU,EAAEmC,aAAa;QACzBI,wBAAwB,EAAEH,cAAc;QACxCI,2BAA2B,EAAE,EAAE;QAC/BzC,QAAQ,EAAE,IAAI;KACf,CAAC;AACJ,CAAC;AAED,eAAe0C,sBAAsB,CAAC3D,IAAY,EAAE4D,YAAoB,EAAmB;IACzF,IAAI;QACF,OAAO,MAAMC,GAAE,EAAA,SAAA,CAACC,QAAQ,CAAC9D,IAAI,EAAE,MAAM,CAAC,CAAC;IACzC,EAAE,OAAM;QACN,MAAM,IAAIyB,OAAY,aAAA,CAACmC,YAAY,CAAC,CAAC;IACvC,CAAC;AACH,CAAC;AAED,eAAeL,oDAAoD,CAAC,EAClER,0BAA0B,CAAA,EAC1BzB,cAAc,CAAA,EAIf,EAA8D;IAC7D,MAAM,CAACyC,yBAAyB,EAAEV,aAAa,CAAC,GAAG,MAAMW,OAAO,CAACC,GAAG,CAAC;QACnEN,sBAAsB,CACpBZ,0BAA0B,EAC1B,CAAC,mDAAmD,EAAEA,0BAA0B,CAAC,CAAC,CACnF;QACDY,sBAAsB,CACpBrC,cAAc,EACd,CAAC,mDAAmD,EAAEA,cAAc,CAAC,CAAC,CACvE;KACF,CAAC,AAAC;IAEH,MAAMJ,UAAU,GAAGgD,IAAAA,wBAAgC,EAAA,iCAAA,EAACb,aAAa,CAAC,AAAC;IACnE,MAAMc,WAAW,GAAGC,IAAAA,wBAAkC,EAAA,mCAAA,EAACL,yBAAyB,CAAC,AAAC;IAClFM,IAAAA,wBAA6B,EAAA,8BAAA,EAACF,WAAW,EAAE;QACzCG,SAAS,EAAEH,WAAW,CAACG,SAAS;QAChCpD,UAAU;KACX,CAAC,CAAC;IAEH,OAAO;QAAEmC,aAAa;QAAEC,cAAc,EAAES,yBAAyB;KAAE,CAAC;AACtE,CAAC;AAED;;;CAGC,GACD,SAASvB,2DAA2D,CAClE+B,eAAyD,EACzDjE,YAAoB,EACI;IACxB,IAAIiE,eAAe,CAACjE,YAAY,KAAKA,YAAY,EAAE;QACjD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,EACJY,UAAU,EAAEmC,aAAa,CAAA,EACzBlC,gBAAgB,EAAEqD,eAAe,CAAA,EACjCvD,QAAQ,CAAA,IACT,GAAGsD,eAAe,AAAC;IACpB,IAAI,CAAClB,aAAa,IAAI,CAACmB,eAAe,EAAE;QACtC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAMrD,gBAAgB,GAAGqD,eAAe,CAACC,GAAG,CAAC,CAACnB,cAAc,GAC1Dc,IAAAA,wBAAkC,EAAA,mCAAA,EAACd,cAAc,CAAC,CACnD,AAAC;IAEF,iEAAiE;IAEjE,iDAAiD;IACjD,KAAK,MAAMa,WAAW,IAAIhD,gBAAgB,CAAE;QAC1C,MAAMuD,GAAG,GAAG,IAAIC,IAAI,EAAE,AAAC;QACvB,IAAIR,WAAW,CAACS,QAAQ,CAACC,SAAS,GAAGH,GAAG,IAAIP,WAAW,CAACS,QAAQ,CAACE,QAAQ,GAAGJ,GAAG,EAAE;YAC/E,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED,wHAAwH;IAExH,OAAO;QACLlB,KAAK,EAAE,SAAS;QAChBE,2BAA2B,EAAEc,eAAe;QAC5Cf,wBAAwB,EAAEe,eAAe,CAAC,CAAC,CAAC;QAC5CtD,UAAU,EAAEmC,aAAa;QACzBpC,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,SAAS8D,wCAAwC,CAACC,KAAY,EAAEC,GAAgC,EAAE;QAO7CD,GACC;IAPpD,MAAME,eAAe,GAAGD,GAAG,CAACE,YAAY,CAACC,EAAE,AAAC;IAE5C,MAAMC,kCAAkC,GACtCL,KAAK,CAACM,UAAU,KAAK,MAAM,IAAIN,KAAK,CAACM,UAAU,KAAK,SAAS,GACzDN,KAAK,CAACO,cAAc,CAACH,EAAE,KAAKF,eAAe,GAC3C,KAAK,AAAC;IACZ,MAAMM,wCAAwC,GAAG,CAAC,EAACR,QAAAA,CAAAA,GACC,GADDA,KAAK,CAACS,QAAQ,CAC9DC,IAAI,CAAC,CAACC,OAAO,GAAKA,OAAO,CAACP,EAAE,KAAKF,eAAe,CAAC,SAC3C,GAF0CF,KAAAA,CAE1C,GAF0CA,QAAAA,GACC,CAChDY,KAAK,SAAA,GAF0CZ,KAAAA,CAE1C,GAF0CA,KAExCU,IAAI,CAAC,CAACG,cAAc,GAAKA,cAAc,CAACb,KAAK,CAACI,EAAE,KAAKJ,KAAK,CAACI,EAAE,CAAC,SAC1D,GAHoCJ,KAAAA,CAGpC,GAHoCA,aAG/Cc,WAAW,SAAA,GAHoCd,KAAAA,CAGpC,GAHoCA,KAGlCe,QAAQ,CAACC,UAAU,WAAA,CAACC,OAAO,CAAC,CAAA,AAAC;IAC9C,OAAOZ,kCAAkC,IAAIG,wCAAwC,CAAC;AACxF,CAAC;AAED,eAAe7C,+CAA+C,CAC5DrC,YAAoB,EACa;IACjC,MAAM0E,KAAK,GAAG,MAAMkB,IAAAA,QAAmB,oBAAA,GAAE,AAAC;IAC1C,IAAIjB,GAAG,AAA6B,AAAC;IACrC,IAAI;QACFA,GAAG,GAAG,MAAMkB,SAAQ,SAAA,CAACC,SAAS,CAAC9F,YAAY,CAAC,CAAC;IAC/C,EAAE,OAAOsC,CAAC,EAAE;QACV,IAAIA,CAAC,YAAYyD,WAAY,EAAA,aAAA,IAAIzD,CAAC,YAAY0D,KAAa,EAAA,cAAA,EAAE;YAC3D,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM1D,CAAC,CAAC;IACV,CAAC;IACD,IAAI,CAACmC,wCAAwC,CAACC,KAAK,EAAEC,GAAG,CAAC,EAAE;QACzD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAMsB,OAAO,GAAGC,IAAAA,wBAAe,EAAA,gBAAA,GAAE,AAAC;IAClC,MAAMC,UAAU,GAAGC,IAAAA,wBAAmB,EAAA,oBAAA,EAACH,OAAO,CAAC,AAAC;IAChD,MAAMI,GAAG,GAAGC,IAAAA,wBAAW,EAAA,YAAA,EAACL,OAAO,EAAE,CAAC,4BAA4B,EAAEjG,YAAY,CAAC,CAAC,CAAC,AAAC;IAChF,MAAMuG,MAAM,GAAGC,IAAAA,wBAAkB,EAAA,mBAAA,EAACH,GAAG,CAAC,AAAC;IACvC,MAAM,CAACI,6BAA6B,EAAEC,6BAA6B,CAAC,GAAG,MAAMhD,OAAO,CAACC,GAAG,CAAC;QACvFgD,IAAAA,iCAAqC,sCAAA,EAAC3G,YAAY,EAAEuG,MAAM,CAAC;QAC3DK,IAAAA,iCAAqC,sCAAA,EAAC5G,YAAY,CAAC;KACpD,CAAC,AAAC;IAEH,MAAMZ,8BAA8B,CAACmB,QAAQ,CAACP,YAAY,EAAE;QAC1DA,YAAY;QACZW,QAAQ,EAAEgE,GAAG,CAAChE,QAAQ;QACtBC,UAAU,EAAEuF,UAAU,CAACpD,aAAa;QACpClC,gBAAgB,EAAE;YAAC4F,6BAA6B;YAAEC,6BAA6B;SAAC;KACjF,CAAC,CAAC;IAEH,OAAO;QACLxD,KAAK,EAAE,SAAS;QAChBE,2BAA2B,EAAE;YAACqD,6BAA6B;YAAEC,6BAA6B;SAAC;QAC3FvD,wBAAwB,EAAEsD,6BAA6B;QACvD7F,UAAU,EAAEuF,UAAU,CAACpD,aAAa;QACpCpC,QAAQ,EAAEgE,GAAG,CAAChE,QAAQ;KACvB,CAAC;AACJ,CAAC;AAIM,SAASrB,kBAAkB,CAChCuH,mBAA2B,EAC3B5C,eAAgC,EACxB;IACR,MAAMrD,UAAU,GAAGgD,IAAAA,wBAAgC,EAAA,iCAAA,EAACK,eAAe,CAACrD,UAAU,CAAC,AAAC;IAChF,MAAMiD,WAAW,GAAGC,IAAAA,wBAAkC,EAAA,mCAAA,EAACG,eAAe,CAACd,wBAAwB,CAAC,AAAC;IACjG,OAAO2D,IAAAA,wBAA4B,EAAA,6BAAA,EACjClG,UAAU,EACViD,WAAW,EACXkD,MAAM,CAACC,IAAI,CAACH,mBAAmB,EAAE,MAAM,CAAC,CACzC,CAAC;AACJ,CAAC"}
|
package/build/src/utils/exit.js
CHANGED
|
@@ -12,6 +12,13 @@ _export(exports, {
|
|
|
12
12
|
installExitHooks: ()=>installExitHooks,
|
|
13
13
|
ensureProcessExitsAfterDelay: ()=>ensureProcessExitsAfterDelay
|
|
14
14
|
});
|
|
15
|
+
function _nodeChildProcess() {
|
|
16
|
+
const data = require("node:child_process");
|
|
17
|
+
_nodeChildProcess = function() {
|
|
18
|
+
return data;
|
|
19
|
+
};
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
15
22
|
function _nodeProcess() {
|
|
16
23
|
const data = /*#__PURE__*/ _interopRequireDefault(require("node:process"));
|
|
17
24
|
_nodeProcess = function() {
|
|
@@ -20,6 +27,7 @@ function _nodeProcess() {
|
|
|
20
27
|
return data;
|
|
21
28
|
}
|
|
22
29
|
const _fn = require("./fn");
|
|
30
|
+
const _log = require("../log");
|
|
23
31
|
function _interopRequireDefault(obj) {
|
|
24
32
|
return obj && obj.__esModule ? obj : {
|
|
25
33
|
default: obj
|
|
@@ -86,17 +94,36 @@ function attachMasterListener() {
|
|
|
86
94
|
};
|
|
87
95
|
}
|
|
88
96
|
function ensureProcessExitsAfterDelay(waitUntilExitMs = 10000, startedAtMs = Date.now()) {
|
|
89
|
-
//
|
|
97
|
+
// Create a list of the expected active resources before exiting.
|
|
98
|
+
// Note, the order is undeterministic
|
|
99
|
+
const expectedResources = [
|
|
100
|
+
_nodeProcess().default.stdout.isTTY ? "TTYWrap" : "PipeWrap",
|
|
101
|
+
_nodeProcess().default.stderr.isTTY ? "TTYWrap" : "PipeWrap",
|
|
102
|
+
_nodeProcess().default.stdin.isTTY ? "TTYWrap" : "PipeWrap",
|
|
103
|
+
];
|
|
104
|
+
// Check active resources, besides the TTYWrap/PipeWrap (process.stdin, process.stdout, process.stderr)
|
|
90
105
|
// @ts-expect-error Added in v17.3.0, v16.14.0 but unavailable in v18 typings
|
|
91
106
|
const activeResources = _nodeProcess().default.getActiveResourcesInfo();
|
|
92
|
-
|
|
107
|
+
// Filter the active resource list by subtracting the expected resources, in undeterministic order
|
|
108
|
+
const unexpectedActiveResources = activeResources.filter((activeResource)=>{
|
|
109
|
+
const index = expectedResources.indexOf(activeResource);
|
|
110
|
+
if (index >= 0) {
|
|
111
|
+
expectedResources.splice(index, 1);
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
return true;
|
|
115
|
+
});
|
|
116
|
+
const canExitProcess = !unexpectedActiveResources.length;
|
|
93
117
|
if (canExitProcess) {
|
|
94
118
|
return debug("no active resources detected, process can safely exit");
|
|
119
|
+
} else {
|
|
120
|
+
debug(`process is trying to exit, but is stuck on unexpected active resources:`, unexpectedActiveResources);
|
|
95
121
|
}
|
|
96
122
|
// Check if the process needs to be force-closed
|
|
97
123
|
const elapsedTime = Date.now() - startedAtMs;
|
|
98
124
|
if (elapsedTime > waitUntilExitMs) {
|
|
99
125
|
debug("active handles detected past the exit delay, forcefully exiting:", activeResources);
|
|
126
|
+
tryWarnActiveProcesses();
|
|
100
127
|
return _nodeProcess().default.exit(0);
|
|
101
128
|
}
|
|
102
129
|
const timeoutId = setTimeout(()=>{
|
|
@@ -106,5 +133,35 @@ function ensureProcessExitsAfterDelay(waitUntilExitMs = 10000, startedAtMs = Dat
|
|
|
106
133
|
ensureProcessExitsAfterDelay(waitUntilExitMs, startedAtMs);
|
|
107
134
|
}, 100);
|
|
108
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Try to warn the user about unexpected active processes running in the background.
|
|
138
|
+
* This uses the internal `process._getActiveHandles` method, within a try-catch block.
|
|
139
|
+
* If active child processes are detected, the commands of these processes are logged.
|
|
140
|
+
*
|
|
141
|
+
* @example ```bash
|
|
142
|
+
* Done writing bundle output
|
|
143
|
+
* Detected 2 processes preventing Expo from exiting, forcefully exiting now.
|
|
144
|
+
* - node /Users/cedric/../node_modules/nativewind/dist/metro/tailwind/v3/child.js
|
|
145
|
+
* - node /Users/cedric/../node_modules/nativewind/dist/metro/tailwind/v3/child.js
|
|
146
|
+
* ```
|
|
147
|
+
*/ function tryWarnActiveProcesses() {
|
|
148
|
+
let activeProcesses = [];
|
|
149
|
+
try {
|
|
150
|
+
const children = _nodeProcess().default// @ts-expect-error - This is an internal method, not designed to be exposed. It's also our only way to get this info
|
|
151
|
+
._getActiveHandles().filter((handle)=>handle instanceof _nodeChildProcess().ChildProcess);
|
|
152
|
+
if (children.length) {
|
|
153
|
+
activeProcesses = children.map((child)=>child.spawnargs.join(" "));
|
|
154
|
+
}
|
|
155
|
+
} catch (error) {
|
|
156
|
+
debug("failed to get active process information:", error);
|
|
157
|
+
}
|
|
158
|
+
if (!activeProcesses.length) {
|
|
159
|
+
(0, _log.warn)("Something prevented Expo from exiting, forcefully exiting now.");
|
|
160
|
+
} else {
|
|
161
|
+
const singularOrPlural = activeProcesses.length === 1 ? "1 process" : `${activeProcesses.length} processes`;
|
|
162
|
+
(0, _log.warn)(`Detected ${singularOrPlural} preventing Expo from exiting, forcefully exiting now.`);
|
|
163
|
+
(0, _log.warn)(" - " + activeProcesses.join("\n - "));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
109
166
|
|
|
110
167
|
//# sourceMappingURL=exit.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/exit.ts"],"sourcesContent":["import process from 'node:process';\n\nimport { guardAsync } from './fn';\n\nconst debug = require('debug')('expo:utils:exit') as typeof console.log;\n\ntype AsyncExitHook = (signal: NodeJS.Signals) => void | Promise<void>;\n\nconst PRE_EXIT_SIGNALS: NodeJS.Signals[] = ['SIGHUP', 'SIGINT', 'SIGTERM', 'SIGBREAK'];\n\n// We create a queue since Node.js throws an error if we try to append too many listeners:\n// (node:4405) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGINT listeners added to [process]. Use emitter.setMaxListeners() to increase limit\nconst queue: AsyncExitHook[] = [];\n\nlet unsubscribe: (() => void) | null = null;\n\n/** Add functions that run before the process exits. Returns a function for removing the listeners. */\nexport function installExitHooks(asyncExitHook: AsyncExitHook): () => void {\n // We need to instantiate the master listener the first time the queue is used.\n if (!queue.length) {\n // Track the master listener so we can remove it later.\n unsubscribe = attachMasterListener();\n }\n\n queue.push(asyncExitHook);\n\n return () => {\n const index = queue.indexOf(asyncExitHook);\n if (index >= 0) {\n queue.splice(index, 1);\n }\n // Clean up the master listener if we don't need it anymore.\n if (!queue.length) {\n unsubscribe?.();\n }\n };\n}\n\n// Create a function that runs before the process exits and guards against running multiple times.\nfunction createExitHook(signal: NodeJS.Signals) {\n return guardAsync(async () => {\n debug(`pre-exit (signal: ${signal}, queue length: ${queue.length})`);\n\n for (const [index, hookAsync] of Object.entries(queue)) {\n try {\n await hookAsync(signal);\n } catch (error: any) {\n debug(`Error in exit hook: %O (queue: ${index})`, error);\n }\n }\n\n debug(`post-exit (code: ${process.exitCode ?? 0})`);\n\n process.exit();\n });\n}\n\nfunction attachMasterListener() {\n const hooks: [NodeJS.Signals, () => any][] = [];\n for (const signal of PRE_EXIT_SIGNALS) {\n const hook = createExitHook(signal);\n hooks.push([signal, hook]);\n process.on(signal, hook);\n }\n return () => {\n for (const [signal, hook] of hooks) {\n process.removeListener(signal, hook);\n }\n };\n}\n\n/**\n * Monitor if the current process is exiting before the delay is reached.\n * If there are active resources, the process will be forced to exit after the delay is reached.\n *\n * @see https://nodejs.org/docs/latest-v18.x/api/process.html#processgetactiveresourcesinfo\n */\nexport function ensureProcessExitsAfterDelay(waitUntilExitMs = 10000, startedAtMs = Date.now()) {\n // Check active resources, besides the TTYWrap (process.stdin, process.stdout, process.stderr)\n // @ts-expect-error Added in v17.3.0, v16.14.0 but unavailable in v18 typings\n const activeResources = process.getActiveResourcesInfo() as string[];\n const canExitProcess = activeResources.filter((resource) => resource !== 'TTYWrap').length === 0;\n if (canExitProcess) {\n return debug('no active resources detected, process can safely exit');\n }\n\n // Check if the process needs to be force-closed\n const elapsedTime = Date.now() - startedAtMs;\n if (elapsedTime > waitUntilExitMs) {\n debug('active handles detected past the exit delay, forcefully exiting:', activeResources);\n return process.exit(0);\n }\n\n const timeoutId = setTimeout(() => {\n // Ensure the timeout is cleared before checking the active resources\n clearTimeout(timeoutId);\n // Check if the process can exit\n ensureProcessExitsAfterDelay(waitUntilExitMs, startedAtMs);\n }, 100);\n}\n"],"names":["installExitHooks","ensureProcessExitsAfterDelay","debug","require","PRE_EXIT_SIGNALS","queue","unsubscribe","asyncExitHook","length","attachMasterListener","push","index","indexOf","splice","createExitHook","signal","guardAsync","hookAsync","Object","entries","error","process","exitCode","exit","hooks","hook","on","removeListener","waitUntilExitMs","startedAtMs","Date","now","activeResources","getActiveResourcesInfo","canExitProcess","filter","resource","elapsedTime","timeoutId","setTimeout","clearTimeout"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/exit.ts"],"sourcesContent":["import { ChildProcess } from 'node:child_process';\nimport process from 'node:process';\n\nimport { guardAsync } from './fn';\nimport { warn } from '../log';\n\nconst debug = require('debug')('expo:utils:exit') as typeof console.log;\n\ntype AsyncExitHook = (signal: NodeJS.Signals) => void | Promise<void>;\n\nconst PRE_EXIT_SIGNALS: NodeJS.Signals[] = ['SIGHUP', 'SIGINT', 'SIGTERM', 'SIGBREAK'];\n\n// We create a queue since Node.js throws an error if we try to append too many listeners:\n// (node:4405) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 SIGINT listeners added to [process]. Use emitter.setMaxListeners() to increase limit\nconst queue: AsyncExitHook[] = [];\n\nlet unsubscribe: (() => void) | null = null;\n\n/** Add functions that run before the process exits. Returns a function for removing the listeners. */\nexport function installExitHooks(asyncExitHook: AsyncExitHook): () => void {\n // We need to instantiate the master listener the first time the queue is used.\n if (!queue.length) {\n // Track the master listener so we can remove it later.\n unsubscribe = attachMasterListener();\n }\n\n queue.push(asyncExitHook);\n\n return () => {\n const index = queue.indexOf(asyncExitHook);\n if (index >= 0) {\n queue.splice(index, 1);\n }\n // Clean up the master listener if we don't need it anymore.\n if (!queue.length) {\n unsubscribe?.();\n }\n };\n}\n\n// Create a function that runs before the process exits and guards against running multiple times.\nfunction createExitHook(signal: NodeJS.Signals) {\n return guardAsync(async () => {\n debug(`pre-exit (signal: ${signal}, queue length: ${queue.length})`);\n\n for (const [index, hookAsync] of Object.entries(queue)) {\n try {\n await hookAsync(signal);\n } catch (error: any) {\n debug(`Error in exit hook: %O (queue: ${index})`, error);\n }\n }\n\n debug(`post-exit (code: ${process.exitCode ?? 0})`);\n\n process.exit();\n });\n}\n\nfunction attachMasterListener() {\n const hooks: [NodeJS.Signals, () => any][] = [];\n for (const signal of PRE_EXIT_SIGNALS) {\n const hook = createExitHook(signal);\n hooks.push([signal, hook]);\n process.on(signal, hook);\n }\n return () => {\n for (const [signal, hook] of hooks) {\n process.removeListener(signal, hook);\n }\n };\n}\n\n/**\n * Monitor if the current process is exiting before the delay is reached.\n * If there are active resources, the process will be forced to exit after the delay is reached.\n *\n * @see https://nodejs.org/docs/latest-v18.x/api/process.html#processgetactiveresourcesinfo\n */\nexport function ensureProcessExitsAfterDelay(waitUntilExitMs = 10000, startedAtMs = Date.now()) {\n // Create a list of the expected active resources before exiting.\n // Note, the order is undeterministic\n const expectedResources = [\n process.stdout.isTTY ? 'TTYWrap' : 'PipeWrap',\n process.stderr.isTTY ? 'TTYWrap' : 'PipeWrap',\n process.stdin.isTTY ? 'TTYWrap' : 'PipeWrap',\n ];\n // Check active resources, besides the TTYWrap/PipeWrap (process.stdin, process.stdout, process.stderr)\n // @ts-expect-error Added in v17.3.0, v16.14.0 but unavailable in v18 typings\n const activeResources = process.getActiveResourcesInfo() as string[];\n // Filter the active resource list by subtracting the expected resources, in undeterministic order\n const unexpectedActiveResources = activeResources.filter((activeResource) => {\n const index = expectedResources.indexOf(activeResource);\n if (index >= 0) {\n expectedResources.splice(index, 1);\n return false;\n }\n\n return true;\n });\n\n const canExitProcess = !unexpectedActiveResources.length;\n if (canExitProcess) {\n return debug('no active resources detected, process can safely exit');\n } else {\n debug(\n `process is trying to exit, but is stuck on unexpected active resources:`,\n unexpectedActiveResources\n );\n }\n\n // Check if the process needs to be force-closed\n const elapsedTime = Date.now() - startedAtMs;\n if (elapsedTime > waitUntilExitMs) {\n debug('active handles detected past the exit delay, forcefully exiting:', activeResources);\n tryWarnActiveProcesses();\n return process.exit(0);\n }\n\n const timeoutId = setTimeout(() => {\n // Ensure the timeout is cleared before checking the active resources\n clearTimeout(timeoutId);\n // Check if the process can exit\n ensureProcessExitsAfterDelay(waitUntilExitMs, startedAtMs);\n }, 100);\n}\n\n/**\n * Try to warn the user about unexpected active processes running in the background.\n * This uses the internal `process._getActiveHandles` method, within a try-catch block.\n * If active child processes are detected, the commands of these processes are logged.\n *\n * @example ```bash\n * Done writing bundle output\n * Detected 2 processes preventing Expo from exiting, forcefully exiting now.\n * - node /Users/cedric/../node_modules/nativewind/dist/metro/tailwind/v3/child.js\n * - node /Users/cedric/../node_modules/nativewind/dist/metro/tailwind/v3/child.js\n * ```\n */\nfunction tryWarnActiveProcesses() {\n let activeProcesses: string[] = [];\n\n try {\n const children: ChildProcess[] = process\n // @ts-expect-error - This is an internal method, not designed to be exposed. It's also our only way to get this info\n ._getActiveHandles()\n .filter((handle: any) => handle instanceof ChildProcess);\n\n if (children.length) {\n activeProcesses = children.map((child) => child.spawnargs.join(' '));\n }\n } catch (error) {\n debug('failed to get active process information:', error);\n }\n\n if (!activeProcesses.length) {\n warn('Something prevented Expo from exiting, forcefully exiting now.');\n } else {\n const singularOrPlural =\n activeProcesses.length === 1 ? '1 process' : `${activeProcesses.length} processes`;\n\n warn(`Detected ${singularOrPlural} preventing Expo from exiting, forcefully exiting now.`);\n warn(' - ' + activeProcesses.join('\\n - '));\n }\n}\n"],"names":["installExitHooks","ensureProcessExitsAfterDelay","debug","require","PRE_EXIT_SIGNALS","queue","unsubscribe","asyncExitHook","length","attachMasterListener","push","index","indexOf","splice","createExitHook","signal","guardAsync","hookAsync","Object","entries","error","process","exitCode","exit","hooks","hook","on","removeListener","waitUntilExitMs","startedAtMs","Date","now","expectedResources","stdout","isTTY","stderr","stdin","activeResources","getActiveResourcesInfo","unexpectedActiveResources","filter","activeResource","canExitProcess","elapsedTime","tryWarnActiveProcesses","timeoutId","setTimeout","clearTimeout","activeProcesses","children","_getActiveHandles","handle","ChildProcess","map","child","spawnargs","join","warn","singularOrPlural"],"mappings":"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"}
|