@expo/cli 0.10.10 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/bin/cli +2 -2
- package/build/src/api/endpoint.js +10 -0
- package/build/src/api/endpoint.js.map +1 -1
- package/build/src/api/graphql/queries/UserQuery.js +2 -1
- package/build/src/api/graphql/queries/UserQuery.js.map +1 -1
- package/build/src/api/user/UserSettings.js.map +1 -1
- package/build/src/api/user/actions.js +6 -1
- package/build/src/api/user/actions.js.map +1 -1
- package/build/src/api/user/expoSsoLauncher.js +127 -0
- package/build/src/api/user/expoSsoLauncher.js.map +1 -0
- package/build/src/api/user/user.js +46 -18
- package/build/src/api/user/user.js.map +1 -1
- package/build/src/export/index.js +3 -1
- package/build/src/export/index.js.map +1 -1
- package/build/src/export/resolveOptions.js +28 -29
- package/build/src/export/resolveOptions.js.map +1 -1
- package/build/src/graphql/generated.js +25 -1
- package/build/src/graphql/generated.js.map +1 -1
- package/build/src/login/index.js +7 -2
- package/build/src/login/index.js.map +1 -1
- package/build/src/start/server/metro/MetroBundlerDevServer.js +35 -3
- package/build/src/start/server/metro/MetroBundlerDevServer.js.map +1 -1
- package/build/src/start/server/metro/MetroTerminalReporter.js +9 -1
- package/build/src/start/server/metro/MetroTerminalReporter.js.map +1 -1
- package/build/src/start/server/metro/metroWatchTypeScriptFiles.js +1 -1
- package/build/src/start/server/metro/metroWatchTypeScriptFiles.js.map +1 -1
- package/build/src/start/server/metro/withMetroMultiPlatform.js +2 -2
- package/build/src/start/server/metro/withMetroMultiPlatform.js.map +1 -1
- package/build/src/start/server/metro/withMetroResolvers.js +166 -16
- package/build/src/start/server/metro/withMetroResolvers.js.map +1 -1
- package/build/src/start/server/middleware/ClassicManifestMiddleware.js +1 -1
- package/build/src/start/server/middleware/ManifestMiddleware.js +23 -6
- package/build/src/start/server/middleware/ManifestMiddleware.js.map +1 -1
- package/build/src/start/server/type-generation/__typetests__/fixtures/basic.js.map +1 -1
- package/build/src/start/server/type-generation/__typetests__/route.test.js +20 -9
- package/build/src/start/server/type-generation/__typetests__/route.test.js.map +1 -1
- package/build/src/start/server/type-generation/routes.js +120 -50
- package/build/src/start/server/type-generation/routes.js.map +1 -1
- package/build/src/utils/analytics/metroDebuggerMiddleware.js +9 -4
- package/build/src/utils/analytics/metroDebuggerMiddleware.js.map +1 -1
- package/build/src/utils/analytics/rudderstackClient.js +2 -2
- package/build/src/utils/env.js +3 -0
- package/build/src/utils/env.js.map +1 -1
- package/build/src/utils/port.js +2 -0
- package/build/src/utils/port.js.map +1 -1
- package/package.json +8 -8
- package/static/react-devtools-page/index.html +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/start/server/type-generation/__typetests__/route.test.ts"],"sourcesContent":["import { expectType, expectError } from 'tsd-lite';\n\nimport { useGlobalSearchParams, useSegments, useRouter, useSearchParams } from './fixtures/basic';\n\n// eslint-disable-next-line react-hooks/rules-of-hooks\nconst router = useRouter();\n\ndescribe('router.push()', () => {\n // router.push will return void when the type matches, otherwise it should error\n\n describe('href', () => {\n it('will error on non-urls', () => {\n expectError(router.push('should-error'));\n });\n\n it('can accept an absolute url', () => {\n expectType<void>(router.push('/apple'));\n expectType<void>(router.push('/banana'));\n });\n\n it('can accept a ANY relative url', () => {\n // We only type-check absolute urls\n expectType<void>(router.push('./this/work/but/is/not/valid'));\n });\n\n it('works for dynamic urls', () => {\n expectType<void>(router.push('/colors/blue'));\n });\n\n it('works for CatchAll routes', () => {\n expectType<void>(router.push('/animals/bear'));\n expectType<void>(router.push('/animals/bear/cat/dog'));\n expectType<void>(router.push('/mix/apple/blue/cat/dog'));\n });\n\n it.skip('works for optional CatchAll routes', () => {\n // CatchAll routes are not currently optional\n // expectType<void>(router.push('/animals/'));\n });\n\n it('will error when providing extra parameters', () => {\n expectError(router.push('/colors/blue/test'));\n });\n\n it('will error when providing too few parameters', () => {\n expectError(router.push('/mix/apple'));\n expectError(router.push('/mix/apple/cat'));\n });\n\n it('can accept any external url', () => {\n expectType<void>(router.push('http://expo.dev'));\n });\n\n it('throws if using inline search params', () => {\n // While this is allowed in Expo Router, the Typed Routes version throws as we cannot type it\n expectError(router.push('/colors?color=blue'));\n expectError(router.push('/animals/bear?color=blue'));\n });\n });\n\n describe('HrefObject', () => {\n it('will error on non-urls', () => {\n expectError(router.push({ pathname: 'should-error' }));\n });\n\n it('can accept an absolute url', () => {\n expectType<void>(router.push({ pathname: '/apple' }));\n expectType<void>(router.push({ pathname: '/banana' }));\n });\n\n it('can accept a ANY relative url', () => {\n // We only type-check absolute urls\n expectType<void>(router.push({ pathname: './this/work/but/is/not/valid' }));\n });\n\n it('works for dynamic urls', () => {\n expectType<void>(\n router.push({\n pathname: '/colors/[color]',\n params: { color: 'blue' },\n })\n );\n });\n\n it('requires a valid pathname', () => {\n expectError(\n router.push({\n pathname: '/colors/[invalid]',\n params: { color: 'blue' },\n })\n );\n });\n\n it('requires a valid param', () => {\n expectError(\n router.push({\n pathname: '/colors/[color]',\n params: { invalid: 'blue' },\n })\n );\n });\n\n it('works for catch all routes', () => {\n expectType<void>(\n router.push({\n pathname: '/animals/[...animal]',\n params: { animal: ['cat', 'dog'] },\n })\n );\n });\n\n it('requires an array for catch all routes', () => {\n expectError(\n router.push({\n pathname: '/animals/[...animal]',\n params: { animal: 'cat' },\n })\n );\n });\n\n it('works for mixed routes', () => {\n expectType<void>(\n router.push({\n pathname: '/mix/[fruit]/[color]/[...animals]',\n params: { color: 'red', fruit: 'apple', animals: ['cat', 'dog'] },\n })\n );\n });\n\n it('requires all params in mixed routes', () => {\n expectError(\n router.push({\n pathname: '/mix/[fruit]/[color]/[...animals]',\n params: { color: 'red', animals: ['cat', 'dog'] },\n })\n );\n });\n });\n});\n\ndescribe('useSearchParams', () => {\n expectType<Record<'color', string>>(useSearchParams<'/colors/[color]'>());\n expectType<Record<'color', string>>(useSearchParams<Record<'color', string>>());\n expectError(useSearchParams<'/invalid'>());\n expectError(useSearchParams<Record<'custom', string>>());\n});\n\ndescribe('useGlobalSearchParams', () => {\n expectType<Record<'color', string>>(useGlobalSearchParams<'/colors/[color]'>());\n expectType<Record<'color', string>>(useGlobalSearchParams<Record<'color', string>>());\n expectError(useGlobalSearchParams<'/invalid'>());\n expectError(useGlobalSearchParams<Record<'custom', string>>());\n});\n\ndescribe('useSegments', () => {\n it('can accept an absolute url', () => {\n expectType<['apple']>(useSegments<'/apple'>());\n });\n\n it('only accepts valid possible urls', () => {\n expectError(useSegments<'/invalid'>());\n });\n\n it('can accept an array of segments', () => {\n expectType<['apple']>(useSegments<['apple']>());\n });\n\n it('only accepts valid possible segments', () => {\n expectError(useSegments<['invalid segment']>());\n });\n});\n"],"names":["router","useRouter","describe","it","expectError","push","expectType","skip","pathname","params","color","invalid","animal","fruit","animals","useSearchParams","useGlobalSearchParams","useSegments"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/start/server/type-generation/__typetests__/route.test.ts"],"sourcesContent":["import { expectType, expectError } from 'tsd-lite';\n\nimport {\n useGlobalSearchParams,\n useSegments,\n useRouter,\n useSearchParams,\n useLocalSearchParams,\n} from './fixtures/basic';\n\n// eslint-disable-next-line react-hooks/rules-of-hooks\nconst router = useRouter();\n\ndescribe('router.push()', () => {\n // router.push will return void when the type matches, otherwise it should error\n\n describe('href', () => {\n it('will error on non-urls', () => {\n expectError(router.push('should-error'));\n });\n\n it('can accept an absolute url', () => {\n expectType<void>(router.push('/apple'));\n expectType<void>(router.push('/banana'));\n });\n\n it('can accept a ANY relative url', () => {\n // We only type-check absolute urls\n expectType<void>(router.push('./this/work/but/is/not/valid'));\n });\n\n it('works for dynamic urls', () => {\n expectType<void>(router.push('/colors/blue'));\n });\n\n it('works for CatchAll routes', () => {\n expectType<void>(router.push('/animals/bear'));\n expectType<void>(router.push('/animals/bear/cat/dog'));\n expectType<void>(router.push('/mix/apple/blue/cat/dog'));\n });\n\n it.skip('works for optional CatchAll routes', () => {\n // CatchAll routes are not currently optional\n // expectType<void>(router.push('/animals/'));\n });\n\n it('will error when providing extra parameters', () => {\n expectError(router.push('/colors/blue/test'));\n });\n\n it('will error when providing too few parameters', () => {\n expectError(router.push('/mix/apple'));\n expectError(router.push('/mix/apple/cat'));\n });\n\n it('can accept any external url', () => {\n expectType<void>(router.push('http://expo.dev'));\n });\n });\n\n describe('HrefObject', () => {\n it('will error on non-urls', () => {\n expectError(router.push({ pathname: 'should-error' }));\n });\n\n it('can accept an absolute url', () => {\n expectType<void>(router.push({ pathname: '/apple' }));\n expectType<void>(router.push({ pathname: '/banana' }));\n });\n\n it('can accept a ANY relative url', () => {\n // We only type-check absolute urls\n expectType<void>(router.push({ pathname: './this/work/but/is/not/valid' }));\n });\n\n it('works for dynamic urls', () => {\n expectType<void>(\n router.push({\n pathname: '/colors/[color]',\n params: { color: 'blue' },\n })\n );\n });\n\n it('requires a valid pathname', () => {\n expectError(\n router.push({\n pathname: '/colors/[invalid]',\n params: { color: 'blue' },\n })\n );\n });\n\n it('requires a valid param', () => {\n expectError(\n router.push({\n pathname: '/colors/[color]',\n params: { invalid: 'blue' },\n })\n );\n });\n\n it('works for catch all routes', () => {\n expectType<void>(\n router.push({\n pathname: '/animals/[...animal]',\n params: { animal: ['cat', 'dog'] },\n })\n );\n });\n\n it('allows numeric inputs', () => {\n expectType<void>(\n router.push({\n pathname: '/mix/[fruit]/[color]/[...animals]',\n params: { color: 1, fruit: 'apple', animals: [2, 'cat'] },\n })\n );\n });\n\n it('requires an array for catch all routes', () => {\n expectError(\n router.push({\n pathname: '/animals/[...animal]',\n params: { animal: 'cat' },\n })\n );\n });\n\n it('works for mixed routes', () => {\n expectType<void>(\n router.push({\n pathname: '/mix/[fruit]/[color]/[...animals]',\n params: { color: 'red', fruit: 'apple', animals: [] },\n })\n );\n });\n\n it('requires all params in mixed routes', () => {\n expectError(\n router.push({\n pathname: '/mix/[fruit]/[color]/[...animals]',\n params: { color: 'red', animals: ['cat', 'dog'] },\n })\n );\n });\n });\n});\n\ndescribe('useSearchParams', () => {\n expectType<Record<'color', string>>(useSearchParams<Record<'color', string>>());\n expectType<Record<'color', string> & Record<string, string | string[]>>(\n useSearchParams<'/colors/[color]'>()\n );\n\n expectError(useSearchParams<'/invalid'>());\n expectError(useSearchParams<Record<'custom', Function>>());\n});\n\ndescribe('useLocalSearchParams', () => {\n expectType<Record<'color', string>>(useLocalSearchParams<Record<'color', string>>());\n expectType<Record<'color', string> & Record<string, string | string[]>>(\n useLocalSearchParams<'/colors/[color]'>()\n );\n\n expectError(useSearchParams<'/invalid'>());\n expectError(useSearchParams<Record<'custom', Function>>());\n});\n\ndescribe('useGlobalSearchParams', () => {\n expectType<Record<'color', string>>(useGlobalSearchParams<Record<'color', string>>());\n expectType<Record<'color', string> & Record<string, string | string[]>>(\n useGlobalSearchParams<'/colors/[color]'>()\n );\n\n expectError(useGlobalSearchParams<'/invalid'>());\n expectError(useGlobalSearchParams<Record<'custom', Function>>());\n});\n\ndescribe('useSegments', () => {\n it('can accept an absolute url', () => {\n expectType<['apple']>(useSegments<'/apple'>());\n });\n\n it('only accepts valid possible urls', () => {\n expectError(useSegments<'/invalid'>());\n });\n\n it('can accept an array of segments', () => {\n expectType<['apple']>(useSegments<['apple']>());\n });\n\n it('only accepts valid possible segments', () => {\n expectError(useSegments<['invalid segment']>());\n });\n});\n"],"names":["router","useRouter","describe","it","expectError","push","expectType","skip","pathname","params","color","invalid","animal","fruit","animals","useSearchParams","useLocalSearchParams","useGlobalSearchParams","useSegments"],"mappings":"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"}
|
|
@@ -10,6 +10,7 @@ exports.setToUnionType = exports.CAPTURE_GROUP_REGEX = exports.ARRAY_GROUP_REGEX
|
|
|
10
10
|
var _promises = _interopRequireDefault(require("fs/promises"));
|
|
11
11
|
var _lodash = require("lodash");
|
|
12
12
|
var _path = _interopRequireDefault(require("path"));
|
|
13
|
+
var _dir = require("../../../utils/dir");
|
|
13
14
|
var _template = require("../../../utils/template");
|
|
14
15
|
var _metroWatchTypeScriptFiles = require("../metro/metroWatchTypeScriptFiles");
|
|
15
16
|
function _interopRequireDefault(obj) {
|
|
@@ -23,17 +24,17 @@ const CATCH_ALL = /\[\.\.\..+?\]/g;
|
|
|
23
24
|
exports.CATCH_ALL = CATCH_ALL;
|
|
24
25
|
const SLUG = /\[.+?\]/g;
|
|
25
26
|
exports.SLUG = SLUG;
|
|
26
|
-
const ARRAY_GROUP_REGEX = /\(\w
|
|
27
|
+
const ARRAY_GROUP_REGEX = /\(\s*\w[\w\s]*?,.*?\)/g;
|
|
27
28
|
exports.ARRAY_GROUP_REGEX = ARRAY_GROUP_REGEX;
|
|
28
|
-
const CAPTURE_GROUP_REGEX = /[\\(,](\w
|
|
29
|
+
const CAPTURE_GROUP_REGEX = /[\\(,]\s*(\w[\w\s]*?)\s*(?=[,\\)])/g;
|
|
29
30
|
exports.CAPTURE_GROUP_REGEX = CAPTURE_GROUP_REGEX;
|
|
30
31
|
async function setupTypedRoutes({ server , metro , typesDirectory , projectRoot , routerDirectory }) {
|
|
31
|
-
const
|
|
32
|
-
const { filePathToRoute , staticRoutes , dynamicRoutes , addFilePath } = getTypedRoutesUtils(
|
|
32
|
+
const absoluteRouterDirectory = _path.default.join(projectRoot, routerDirectory);
|
|
33
|
+
const { filePathToRoute , staticRoutes , dynamicRoutes , addFilePath , isRouteFile } = getTypedRoutesUtils(absoluteRouterDirectory);
|
|
33
34
|
if (metro) {
|
|
34
35
|
// Setup out watcher first
|
|
35
36
|
(0, _metroWatchTypeScriptFiles).metroWatchTypeScriptFiles({
|
|
36
|
-
projectRoot
|
|
37
|
+
projectRoot,
|
|
37
38
|
server,
|
|
38
39
|
metro,
|
|
39
40
|
eventTypes: [
|
|
@@ -42,6 +43,9 @@ async function setupTypedRoutes({ server , metro , typesDirectory , projectRoot
|
|
|
42
43
|
"change"
|
|
43
44
|
],
|
|
44
45
|
async callback ({ filePath , type }) {
|
|
46
|
+
if (!isRouteFile(filePath)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
45
49
|
let shouldRegenerate = false;
|
|
46
50
|
if (type === "delete") {
|
|
47
51
|
const route = filePathToRoute(filePath);
|
|
@@ -63,9 +67,11 @@ async function setupTypedRoutes({ server , metro , typesDirectory , projectRoot
|
|
|
63
67
|
}
|
|
64
68
|
});
|
|
65
69
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
70
|
+
if (await (0, _dir).directoryExistsAsync(absoluteRouterDirectory)) {
|
|
71
|
+
// Do we need to walk the entire tree on startup?
|
|
72
|
+
// Idea: Store the list of files in the last write, then simply check Git for what files have changed
|
|
73
|
+
await walk(absoluteRouterDirectory, addFilePath);
|
|
74
|
+
}
|
|
69
75
|
regenerateRouterDotTS(typesDirectory, new Set([
|
|
70
76
|
...staticRoutes.values()
|
|
71
77
|
].flatMap((v)=>Array.from(v)
|
|
@@ -77,8 +83,11 @@ async function setupTypedRoutes({ server , metro , typesDirectory , projectRoot
|
|
|
77
83
|
/**
|
|
78
84
|
* Generate a router.d.ts file that contains all of the routes in the project.
|
|
79
85
|
* Should be debounced as its very common for developers to make changes to multiple files at once (eg Save All)
|
|
80
|
-
*/ const regenerateRouterDotTS = (0, _lodash).debounce((typesDir, staticRoutes, dynamicRoutes, dynamicRouteTemplates)=>{
|
|
81
|
-
_promises.default.
|
|
86
|
+
*/ const regenerateRouterDotTS = (0, _lodash).debounce(async (typesDir, staticRoutes, dynamicRoutes, dynamicRouteTemplates)=>{
|
|
87
|
+
await _promises.default.mkdir(typesDir, {
|
|
88
|
+
recursive: true
|
|
89
|
+
});
|
|
90
|
+
await _promises.default.writeFile(_path.default.resolve(typesDir, "./router.d.ts"), getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates));
|
|
82
91
|
}, 100);
|
|
83
92
|
function getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates) {
|
|
84
93
|
return routerDotTSTemplate({
|
|
@@ -87,7 +96,7 @@ function getTemplateString(staticRoutes, dynamicRoutes, dynamicRouteTemplates) {
|
|
|
87
96
|
dynamicRouteParams: setToUnionType(dynamicRouteTemplates)
|
|
88
97
|
});
|
|
89
98
|
}
|
|
90
|
-
function getTypedRoutesUtils(appRoot) {
|
|
99
|
+
function getTypedRoutesUtils(appRoot, filePathSeperator = _path.default.sep) {
|
|
91
100
|
/*
|
|
92
101
|
* staticRoutes are a map where the key if the route without groups and the value
|
|
93
102
|
* is another set of all group versions of the route. e.g,
|
|
@@ -110,11 +119,24 @@ function getTypedRoutesUtils(appRoot) {
|
|
|
110
119
|
* The keys of this map are also important, as they can be used as "static" types
|
|
111
120
|
* <Link href={{ pathname: "/[...fruits]",params: { fruits: ["apple"] } }} />
|
|
112
121
|
*/ const dynamicRoutes = new Map();
|
|
122
|
+
function normalizedFilePath(filePath) {
|
|
123
|
+
return filePath.replaceAll(filePathSeperator, "/");
|
|
124
|
+
}
|
|
125
|
+
const normalizedAppRoot = normalizedFilePath(appRoot);
|
|
113
126
|
const filePathToRoute = (filePath)=>{
|
|
114
|
-
return filePath.replace(
|
|
127
|
+
return normalizedFilePath(filePath).replace(normalizedAppRoot, "").replace(/index\.[jt]sx?/, "").replace(/\.[jt]sx?$/, "");
|
|
128
|
+
};
|
|
129
|
+
const isRouteFile = (filePath)=>{
|
|
130
|
+
// Layout and filenames starting with `+` are not routes
|
|
131
|
+
if (filePath.match(/_layout\.[tj]sx?$/) || filePath.match(/\/\+/)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
// Route files must be nested with in the appRoot
|
|
135
|
+
const relative = _path.default.relative(appRoot, filePath);
|
|
136
|
+
return relative && !relative.startsWith("..") && !_path.default.isAbsolute(relative);
|
|
115
137
|
};
|
|
116
138
|
const addFilePath = (filePath)=>{
|
|
117
|
-
if (filePath
|
|
139
|
+
if (!isRouteFile(filePath)) {
|
|
118
140
|
return false;
|
|
119
141
|
}
|
|
120
142
|
const route1 = filePathToRoute(filePath);
|
|
@@ -163,7 +185,8 @@ function getTypedRoutesUtils(appRoot) {
|
|
|
163
185
|
staticRoutes,
|
|
164
186
|
dynamicRoutes,
|
|
165
187
|
filePathToRoute,
|
|
166
|
-
addFilePath
|
|
188
|
+
addFilePath,
|
|
189
|
+
isRouteFile
|
|
167
190
|
};
|
|
168
191
|
}
|
|
169
192
|
const setToUnionType = (set)=>{
|
|
@@ -183,7 +206,7 @@ exports.setToUnionType = setToUnionType;
|
|
|
183
206
|
await walk(p, callback);
|
|
184
207
|
} else {
|
|
185
208
|
// Normalise the paths so they are easier to convert to URLs
|
|
186
|
-
const normalizedPath = p.replaceAll(_path.default.sep, "/")
|
|
209
|
+
const normalizedPath = p.replaceAll(_path.default.sep, "/");
|
|
187
210
|
callback(normalizedPath);
|
|
188
211
|
}
|
|
189
212
|
}
|
|
@@ -198,7 +221,7 @@ function extrapolateGroupRoutes(route, routes = new Set()) {
|
|
|
198
221
|
}
|
|
199
222
|
const groupsMatch = match[0];
|
|
200
223
|
for (const group of groupsMatch.matchAll(CAPTURE_GROUP_REGEX)){
|
|
201
|
-
extrapolateGroupRoutes(route.replace(groupsMatch, `(${group[1]})`), routes);
|
|
224
|
+
extrapolateGroupRoutes(route.replace(groupsMatch, `(${group[1].trim()})`), routes);
|
|
202
225
|
}
|
|
203
226
|
return routes;
|
|
204
227
|
}
|
|
@@ -211,6 +234,7 @@ function extrapolateGroupRoutes(route, routes = new Set()) {
|
|
|
211
234
|
/* eslint-disable @typescript-eslint/ban-types */
|
|
212
235
|
declare module "expo-router" {
|
|
213
236
|
import type { LinkProps as OriginalLinkProps } from 'expo-router/build/link/Link';
|
|
237
|
+
import type { Router as OriginalRouter } from 'expo-router/src/types';
|
|
214
238
|
export * from 'expo-router/build';
|
|
215
239
|
|
|
216
240
|
// prettier-ignore
|
|
@@ -231,6 +255,8 @@ declare module "expo-router" {
|
|
|
231
255
|
****************/
|
|
232
256
|
|
|
233
257
|
type SearchOrHash = \`?\${string}\` | \`#\${string}\`;
|
|
258
|
+
type UnknownInputParams = Record<string, string | number | (string | number)[]>;
|
|
259
|
+
type UnknownOutputParams = Record<string, string | string[]>;
|
|
234
260
|
|
|
235
261
|
/**
|
|
236
262
|
* Return only the RoutePart of a string. If the string has multiple parts return never
|
|
@@ -250,6 +276,10 @@ declare module "expo-router" {
|
|
|
250
276
|
? never
|
|
251
277
|
: S extends ''
|
|
252
278
|
? never
|
|
279
|
+
: S extends \`(\${string})\`
|
|
280
|
+
? never
|
|
281
|
+
: S extends \`[\${string}]\`
|
|
282
|
+
? never
|
|
253
283
|
: S;
|
|
254
284
|
|
|
255
285
|
/**
|
|
@@ -259,6 +289,10 @@ declare module "expo-router" {
|
|
|
259
289
|
? never
|
|
260
290
|
: S extends ''
|
|
261
291
|
? never
|
|
292
|
+
: S extends \`\${string}(\${string})\${string}\`
|
|
293
|
+
? never
|
|
294
|
+
: S extends \`\${string}[\${string}]\${string}\`
|
|
295
|
+
? never
|
|
262
296
|
: S;
|
|
263
297
|
|
|
264
298
|
// type OptionalCatchAllRoutePart<S extends string> = S extends \`\${string}\${SearchOrHash}\` ? never : S
|
|
@@ -295,25 +329,34 @@ declare module "expo-router" {
|
|
|
295
329
|
: [Path];
|
|
296
330
|
|
|
297
331
|
/**
|
|
298
|
-
* Returns a Record of the routes parameters as strings and CatchAll parameters
|
|
332
|
+
* Returns a Record of the routes parameters as strings and CatchAll parameters
|
|
333
|
+
*
|
|
334
|
+
* There are two versions, input and output, as you can input 'string | number' but
|
|
335
|
+
* the output will always be 'string'
|
|
299
336
|
*
|
|
300
337
|
* /[id]/[...rest] -> { id: string, rest: string[] }
|
|
301
338
|
* /no-params -> {}
|
|
302
339
|
*/
|
|
303
|
-
type
|
|
340
|
+
type InputRouteParams<Path> = {
|
|
341
|
+
[Key in ParameterNames<Path> as Key extends \`...\${infer Name}\`
|
|
342
|
+
? Name
|
|
343
|
+
: Key]: Key extends \`...\${string}\` ? (string | number)[] : string | number;
|
|
344
|
+
} & UnknownInputParams;
|
|
345
|
+
|
|
346
|
+
type OutputRouteParams<Path> = {
|
|
304
347
|
[Key in ParameterNames<Path> as Key extends \`...\${infer Name}\`
|
|
305
348
|
? Name
|
|
306
349
|
: Key]: Key extends \`...\${string}\` ? string[] : string;
|
|
307
|
-
};
|
|
350
|
+
} & UnknownOutputParams;
|
|
308
351
|
|
|
309
352
|
/**
|
|
310
|
-
* Returns the search parameters for a route
|
|
353
|
+
* Returns the search parameters for a route.
|
|
311
354
|
*/
|
|
312
355
|
export type SearchParams<T extends AllRoutes> = T extends DynamicRouteTemplate
|
|
313
|
-
?
|
|
356
|
+
? OutputRouteParams<T>
|
|
314
357
|
: T extends StaticRoutes
|
|
315
358
|
? never
|
|
316
|
-
:
|
|
359
|
+
: UnknownOutputParams;
|
|
317
360
|
|
|
318
361
|
/**
|
|
319
362
|
* Route is mostly used as part of Href to ensure that a valid route is provided
|
|
@@ -328,71 +371,98 @@ declare module "expo-router" {
|
|
|
328
371
|
*
|
|
329
372
|
* This is named Route to prevent confusion, as users they will often see it in tooltips
|
|
330
373
|
*/
|
|
331
|
-
export type Route<T> = T extends
|
|
332
|
-
?
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
374
|
+
export type Route<T> = T extends string
|
|
375
|
+
? T extends DynamicRouteTemplate
|
|
376
|
+
? never
|
|
377
|
+
:
|
|
378
|
+
| StaticRoutes
|
|
379
|
+
| RelativePathString
|
|
380
|
+
| ExternalPathString
|
|
381
|
+
| (T extends \`\${infer P}\${SearchOrHash}\`
|
|
382
|
+
? P extends DynamicRoutes<infer _>
|
|
383
|
+
? T
|
|
384
|
+
: never
|
|
385
|
+
: T extends DynamicRoutes<infer _>
|
|
386
|
+
? T
|
|
387
|
+
: never)
|
|
388
|
+
: never;
|
|
338
389
|
|
|
339
390
|
/*********
|
|
340
391
|
* Href *
|
|
341
392
|
*********/
|
|
342
393
|
|
|
343
|
-
export type Href<T extends string>
|
|
394
|
+
export type Href<T> = T extends Record<'pathname', string> ? HrefObject<T> : Route<T>;
|
|
344
395
|
|
|
345
|
-
export type HrefObject<
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
396
|
+
export type HrefObject<
|
|
397
|
+
R extends Record<'pathname', string>,
|
|
398
|
+
P = R['pathname']
|
|
399
|
+
> = P extends DynamicRouteTemplate
|
|
400
|
+
? { pathname: P; params: InputRouteParams<P> }
|
|
401
|
+
: P extends Route<P>
|
|
402
|
+
? { pathname: Route<P> | DynamicRouteTemplate; params?: never | InputRouteParams<never> }
|
|
349
403
|
: never;
|
|
350
404
|
|
|
351
405
|
/***********************
|
|
352
406
|
* Expo Router Exports *
|
|
353
407
|
***********************/
|
|
354
408
|
|
|
355
|
-
export type Router = {
|
|
409
|
+
export type Router = Omit<OriginalRouter, 'push' | 'replace' | 'setParams'> & {
|
|
356
410
|
/** Navigate to the provided href. */
|
|
357
|
-
push: <T
|
|
411
|
+
push: <T>(href: Href<T>) => void;
|
|
358
412
|
/** Navigate to route without appending to the history. */
|
|
359
|
-
replace: <T
|
|
360
|
-
/** Go back in the history. */
|
|
361
|
-
back: () => void;
|
|
413
|
+
replace: <T>(href: Href<T>) => void;
|
|
362
414
|
/** Update the current route query params. */
|
|
363
|
-
setParams: <T
|
|
364
|
-
params?: T extends '' ? Record<string, string> : RouteParams<T>
|
|
365
|
-
) => void;
|
|
415
|
+
setParams: <T = ''>(params?: T extends '' ? Record<string, string> : InputRouteParams<T>) => void;
|
|
366
416
|
};
|
|
367
417
|
|
|
418
|
+
/** The imperative router. */
|
|
419
|
+
export const router: Router;
|
|
420
|
+
|
|
368
421
|
/************
|
|
369
422
|
* <Link /> *
|
|
370
423
|
************/
|
|
371
|
-
export interface LinkProps<T
|
|
372
|
-
href:
|
|
424
|
+
export interface LinkProps<T> extends OriginalLinkProps {
|
|
425
|
+
href: Href<T>;
|
|
373
426
|
}
|
|
374
427
|
|
|
375
428
|
export interface LinkComponent {
|
|
376
|
-
<T
|
|
429
|
+
<T>(props: React.PropsWithChildren<LinkProps<T>>): JSX.Element;
|
|
377
430
|
/** Helper method to resolve an Href object into a string. */
|
|
378
|
-
resolveHref: <T
|
|
431
|
+
resolveHref: <T>(href: Href<T>) => string;
|
|
379
432
|
}
|
|
380
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Component to render link to another route using a path.
|
|
436
|
+
* Uses an anchor tag on the web.
|
|
437
|
+
*
|
|
438
|
+
* @param props.href Absolute path to route (e.g. \`/feeds/hot\`).
|
|
439
|
+
* @param props.replace Should replace the current route without adding to the history.
|
|
440
|
+
* @param props.asChild Forward props to child component. Useful for custom buttons.
|
|
441
|
+
* @param props.children Child elements to render the content.
|
|
442
|
+
*/
|
|
381
443
|
export const Link: LinkComponent;
|
|
444
|
+
|
|
445
|
+
/** Redirects to the href as soon as the component is mounted. */
|
|
446
|
+
export const Redirect: <T>(
|
|
447
|
+
props: React.PropsWithChildren<{ href: Href<T> }>
|
|
448
|
+
) => JSX.Element;
|
|
382
449
|
|
|
383
450
|
/************
|
|
384
451
|
* Hooks *
|
|
385
452
|
************/
|
|
386
453
|
export function useRouter(): Router;
|
|
454
|
+
|
|
387
455
|
export function useLocalSearchParams<
|
|
388
|
-
T extends
|
|
389
|
-
>(): SearchParams<T
|
|
456
|
+
T extends AllRoutes | UnknownOutputParams = UnknownOutputParams
|
|
457
|
+
>(): T extends AllRoutes ? SearchParams<T> : T;
|
|
458
|
+
|
|
459
|
+
/** @deprecated renamed to \`useGlobalSearchParams\` */
|
|
390
460
|
export function useSearchParams<
|
|
391
|
-
T extends AllRoutes |
|
|
461
|
+
T extends AllRoutes | UnknownOutputParams = UnknownOutputParams
|
|
392
462
|
>(): T extends AllRoutes ? SearchParams<T> : T;
|
|
393
463
|
|
|
394
464
|
export function useGlobalSearchParams<
|
|
395
|
-
T extends AllRoutes |
|
|
465
|
+
T extends AllRoutes | UnknownOutputParams = UnknownOutputParams
|
|
396
466
|
>(): T extends AllRoutes ? SearchParams<T> : T;
|
|
397
467
|
|
|
398
468
|
export function useSegments<
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/start/server/type-generation/routes.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport { debounce } from 'lodash';\nimport { Server } from 'metro';\nimport path from 'path';\n\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 = /\\(\\w+?,.*?\\)/g;\n// /(group1,group2,group3)/test - captures [\"group1\", \"group2\", \"group3\"]\nexport const CAPTURE_GROUP_REGEX = /[\\\\(,](\\w+?)(?=[,\\\\)])/g;\n\nexport interface SetupTypedRoutesOptions {\n server: ServerLike;\n metro?: Server | null;\n typesDirectory: string;\n projectRoot: string;\n routerDirectory: string;\n}\n\nexport async function setupTypedRoutes({\n server,\n metro,\n typesDirectory,\n projectRoot,\n routerDirectory,\n}: SetupTypedRoutesOptions) {\n const appRoot = path.join(projectRoot, routerDirectory);\n\n const { filePathToRoute, staticRoutes, dynamicRoutes, addFilePath } =\n getTypedRoutesUtils(appRoot);\n\n if (metro) {\n // Setup out watcher first\n metroWatchTypeScriptFiles({\n projectRoot: appRoot,\n server,\n metro,\n eventTypes: ['add', 'delete', 'change'],\n async callback({ filePath, type }) {\n let shouldRegenerate = false;\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 // 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(appRoot, addFilePath);\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 (\n typesDir: string,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteTemplates: Set<string>\n ) => {\n 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) {\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 const filePathToRoute = (filePath: string) => {\n return filePath\n .replace(appRoot, '')\n .replace(/index.[jt]sx?/, '')\n .replace(/\\.[jt]sx?$/, '');\n };\n\n const addFilePath = (filePath: string): boolean => {\n if (filePath.match(/_layout\\.[tj]sx?$/)) {\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 };\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, '/').replaceAll(' ', '_');\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]})`), 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 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 = \\`http\\${string}\\`;\n type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString;\n type AllRoutes = ExpoRouterRoutes | ExternalPathString;\n\n /****************\n * Route Utils *\n ****************/\n\n type SearchOrHash = \\`?\\${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;\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;\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 as string[]\n *\n * /[id]/[...rest] -> { id: string, rest: string[] }\n * /no-params -> {}\n */\n type RouteParams<Path> = {\n [Key in ParameterNames<Path> as Key extends \\`...\\${infer Name}\\`\n ? Name\n : Key]: Key extends \\`...\\${string}\\` ? string[] : string;\n };\n\n /**\n * Returns the search parameters for a route\n */\n export type SearchParams<T extends AllRoutes> = T extends DynamicRouteTemplate\n ? RouteParams<T>\n : T extends StaticRoutes\n ? never\n : Record<string, string>;\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 DynamicRouteTemplate\n ? never\n :\n | StaticRoutes\n | RelativePathString\n | ExternalPathString\n | (T extends DynamicRoutes<infer _> ? T : never);\n\n /*********\n * Href *\n *********/\n\n export type Href<T extends string> = Route<T> | HrefObject<T>;\n\n export type HrefObject<T = AllRoutes> = T extends DynamicRouteTemplate\n ? { pathname: T; params: RouteParams<T> }\n : T extends Route<T>\n ? { pathname: Route<T>; params?: never }\n : never;\n\n /***********************\n * Expo Router Exports *\n ***********************/\n\n export type Router = {\n /** Navigate to the provided href. */\n push: <T extends string>(href: Href<T>) => void;\n /** Navigate to route without appending to the history. */\n replace: <T extends string>(href: Href<T>) => void;\n /** Go back in the history. */\n back: () => void;\n /** Update the current route query params. */\n setParams: <T extends string = ''>(\n params?: T extends '' ? Record<string, string> : RouteParams<T>\n ) => void;\n };\n\n /************\n * <Link /> *\n ************/\n export interface LinkProps<T extends string> extends OriginalLinkProps {\n href: T extends DynamicRouteTemplate ? HrefObject<T> : Href<T>;\n }\n\n export interface LinkComponent {\n <T extends string>(props: React.PropsWithChildren<LinkProps<T>>): JSX.Element;\n /** Helper method to resolve an Href object into a string. */\n resolveHref: <T extends string>(href: Href<T>) => string;\n }\n\n export const Link: LinkComponent;\n\n /************\n * Hooks *\n ************/\n export function useRouter(): Router;\n export function useLocalSearchParams<\n T extends DynamicRouteTemplate | StaticRoutes | RelativePathString\n >(): SearchParams<T>;\n export function useSearchParams<\n T extends AllRoutes | SearchParams<DynamicRouteTemplate>\n >(): T extends AllRoutes ? SearchParams<T> : T;\n\n export function useGlobalSearchParams<\n T extends AllRoutes | SearchParams<DynamicRouteTemplate>\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":["setupTypedRoutes","getTemplateString","getTypedRoutesUtils","extrapolateGroupRoutes","CAPTURE_DYNAMIC_PARAMS","CATCH_ALL","SLUG","ARRAY_GROUP_REGEX","CAPTURE_GROUP_REGEX","server","metro","typesDirectory","projectRoot","routerDirectory","appRoot","path","join","filePathToRoute","staticRoutes","dynamicRoutes","addFilePath","metroWatchTypeScriptFiles","eventTypes","callback","filePath","type","shouldRegenerate","route","delete","regenerateRouterDotTS","Set","values","flatMap","v","Array","from","keys","walk","debounce","typesDir","dynamicRouteTemplates","fs","writeFile","resolve","routerDotTSTemplate","setToUnionType","dynamicRouteParams","Map","replace","match","has","dynamicParams","matchAll","map","isDynamic","size","addRoute","originalRoute","set","get","add","replaceAll","includes","routeWithoutGroups","routeWithSingleGroup","s","directory","files","readdir","file","p","stat","isDirectory","normalizedPath","sep","routes","groupsMatch","group","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';\nimport { Server } from 'metro';\nimport path from 'path';\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\nexport interface SetupTypedRoutesOptions {\n server: ServerLike;\n metro?: Server | null;\n typesDirectory: string;\n projectRoot: string;\n routerDirectory: string;\n}\n\nexport async function setupTypedRoutes({\n server,\n metro,\n typesDirectory,\n projectRoot,\n routerDirectory,\n}: SetupTypedRoutesOptions) {\n const absoluteRouterDirectory = path.join(projectRoot, routerDirectory);\n\n const { filePathToRoute, staticRoutes, dynamicRoutes, addFilePath, isRouteFile } =\n getTypedRoutesUtils(absoluteRouterDirectory);\n\n if (metro) {\n // Setup out watcher first\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(absoluteRouterDirectory)) {\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(absoluteRouterDirectory, 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 // Layout and filenames starting with `+` are not routes\n if (filePath.match(/_layout\\.[tj]sx?$/) || filePath.match(/\\/\\+/)) {\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/src/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 = \\`http\\${string}\\`;\n type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString;\n 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 */\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":["setupTypedRoutes","getTemplateString","getTypedRoutesUtils","extrapolateGroupRoutes","CAPTURE_DYNAMIC_PARAMS","CATCH_ALL","SLUG","ARRAY_GROUP_REGEX","CAPTURE_GROUP_REGEX","server","metro","typesDirectory","projectRoot","routerDirectory","absoluteRouterDirectory","path","join","filePathToRoute","staticRoutes","dynamicRoutes","addFilePath","isRouteFile","metroWatchTypeScriptFiles","eventTypes","callback","filePath","type","shouldRegenerate","route","delete","regenerateRouterDotTS","Set","values","flatMap","v","Array","from","keys","directoryExistsAsync","walk","debounce","typesDir","dynamicRouteTemplates","fs","mkdir","recursive","writeFile","resolve","routerDotTSTemplate","setToUnionType","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","directory","files","readdir","file","p","stat","isDirectory","normalizedPath","routes","groupsMatch","group","trim","unsafeTemplate"],"mappings":"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"}
|
|
@@ -11,12 +11,15 @@ function createDebuggerTelemetryMiddleware(projectRoot, exp) {
|
|
|
11
11
|
let hasReported = false;
|
|
12
12
|
// This only works for Hermes apps, disable when telemetry is turned off
|
|
13
13
|
if (_env.env.EXPO_NO_TELEMETRY || exp.jsEngine !== "hermes") {
|
|
14
|
-
return (req, res, next)=>
|
|
15
|
-
|
|
14
|
+
return (req, res, next)=>{
|
|
15
|
+
if (typeof next === "function") {
|
|
16
|
+
next(undefined);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
16
19
|
}
|
|
17
20
|
return (req, res, next)=>{
|
|
18
21
|
// Only report once
|
|
19
|
-
if (hasReported) {
|
|
22
|
+
if (hasReported && typeof next === "function") {
|
|
20
23
|
return next(undefined);
|
|
21
24
|
}
|
|
22
25
|
const debugTool = findDebugTool(req);
|
|
@@ -24,7 +27,9 @@ function createDebuggerTelemetryMiddleware(projectRoot, exp) {
|
|
|
24
27
|
hasReported = true;
|
|
25
28
|
(0, _rudderstackClient).logEventAsync("metro debug", (0, _getMetroDebugProperties).getMetroDebugProperties(projectRoot, exp, debugTool));
|
|
26
29
|
}
|
|
27
|
-
|
|
30
|
+
if (typeof next === "function") {
|
|
31
|
+
return next(undefined);
|
|
32
|
+
}
|
|
28
33
|
};
|
|
29
34
|
}
|
|
30
35
|
function findDebugTool(req) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/utils/analytics/metroDebuggerMiddleware.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport { Middleware } from 'metro-config';\n\nimport { env } from '../env';\nimport { DebugTool, getMetroDebugProperties } from './getMetroDebugProperties';\nimport { logEventAsync } from './rudderstackClient';\n\n/**\n * Create a Metro middleware that reports when a debugger request was found.\n * This will only be reported once, if the app uses Hermes and telemetry is not enabled.\n */\nexport function createDebuggerTelemetryMiddleware(\n projectRoot: string,\n exp: ExpoConfig\n): Middleware {\n let hasReported = false;\n\n // This only works for Hermes apps, disable when telemetry is turned off\n if (env.EXPO_NO_TELEMETRY || exp.jsEngine !== 'hermes') {\n return (req, res, next) => next(undefined);\n }\n\n return (req, res, next) => {\n // Only report once\n if (hasReported) {\n return next(undefined);\n }\n\n const debugTool = findDebugTool(req);\n if (debugTool) {\n hasReported = true;\n logEventAsync('metro debug', getMetroDebugProperties(projectRoot, exp, debugTool));\n }\n\n return next(undefined);\n };\n}\n\n/** Exposed for testing */\nexport function findDebugTool(\n req: Pick<Parameters<Middleware>[0], 'headers' | 'url'>\n): DebugTool | null {\n if (req.headers['origin']?.includes('chrome-devtools')) {\n return { name: 'chrome' };\n }\n\n if (req.url?.startsWith('/json')) {\n const flipperUserAgent = req.headers['user-agent']?.match(/(Flipper)\\/([^\\s]+)/);\n if (flipperUserAgent) {\n return {\n name: flipperUserAgent[1].toLowerCase(),\n version: flipperUserAgent[2],\n };\n }\n }\n\n return null;\n}\n"],"names":["createDebuggerTelemetryMiddleware","findDebugTool","projectRoot","exp","hasReported","env","EXPO_NO_TELEMETRY","jsEngine","req","res","next","undefined","debugTool","logEventAsync","getMetroDebugProperties","headers","includes","name","url","startsWith","flipperUserAgent","match","toLowerCase","version"],"mappings":"AAAA;;;;
|
|
1
|
+
{"version":3,"sources":["../../../../src/utils/analytics/metroDebuggerMiddleware.ts"],"sourcesContent":["import { ExpoConfig } from '@expo/config';\nimport { Middleware } from 'metro-config';\n\nimport { env } from '../env';\nimport { DebugTool, getMetroDebugProperties } from './getMetroDebugProperties';\nimport { logEventAsync } from './rudderstackClient';\n\ntype Request = Parameters<Middleware>[0];\ntype Response = Parameters<Middleware>[1];\ntype Next = Parameters<Middleware>[2];\n\n/**\n * Create a Metro middleware that reports when a debugger request was found.\n * This will only be reported once, if the app uses Hermes and telemetry is not enabled.\n */\nexport function createDebuggerTelemetryMiddleware(\n projectRoot: string,\n exp: ExpoConfig\n): Middleware {\n let hasReported = false;\n\n // This only works for Hermes apps, disable when telemetry is turned off\n if (env.EXPO_NO_TELEMETRY || exp.jsEngine !== 'hermes') {\n return (req: Request, res: Response, next: Next) => {\n if (typeof next === 'function') {\n next(undefined);\n }\n };\n }\n\n return (req: Request, res: Response, next: Next) => {\n // Only report once\n if (hasReported && typeof next === 'function') {\n return next(undefined);\n }\n\n const debugTool = findDebugTool(req);\n if (debugTool) {\n hasReported = true;\n logEventAsync('metro debug', getMetroDebugProperties(projectRoot, exp, debugTool));\n }\n\n if (typeof next === 'function') {\n return next(undefined);\n }\n };\n}\n\n/** Exposed for testing */\nexport function findDebugTool(\n req: Pick<Parameters<Middleware>[0], 'headers' | 'url'>\n): DebugTool | null {\n if (req.headers['origin']?.includes('chrome-devtools')) {\n return { name: 'chrome' };\n }\n\n if (req.url?.startsWith('/json')) {\n const flipperUserAgent = req.headers['user-agent']?.match(/(Flipper)\\/([^\\s]+)/);\n if (flipperUserAgent) {\n return {\n name: flipperUserAgent[1].toLowerCase(),\n version: flipperUserAgent[2],\n };\n }\n }\n\n return null;\n}\n"],"names":["createDebuggerTelemetryMiddleware","findDebugTool","projectRoot","exp","hasReported","env","EXPO_NO_TELEMETRY","jsEngine","req","res","next","undefined","debugTool","logEventAsync","getMetroDebugProperties","headers","includes","name","url","startsWith","flipperUserAgent","match","toLowerCase","version"],"mappings":"AAAA;;;;QAegBA,iCAAiC,GAAjCA,iCAAiC;QAkCjCC,aAAa,GAAbA,aAAa;AA9CT,IAAA,IAAQ,WAAR,QAAQ,CAAA;AACuB,IAAA,wBAA2B,WAA3B,2BAA2B,CAAA;AAChD,IAAA,kBAAqB,WAArB,qBAAqB,CAAA;AAU5C,SAASD,iCAAiC,CAC/CE,WAAmB,EACnBC,GAAe,EACH;IACZ,IAAIC,WAAW,GAAG,KAAK,AAAC;IAExB,wEAAwE;IACxE,IAAIC,IAAG,IAAA,CAACC,iBAAiB,IAAIH,GAAG,CAACI,QAAQ,KAAK,QAAQ,EAAE;QACtD,OAAO,CAACC,GAAY,EAAEC,GAAa,EAAEC,IAAU,GAAK;YAClD,IAAI,OAAOA,IAAI,KAAK,UAAU,EAAE;gBAC9BA,IAAI,CAACC,SAAS,CAAC,CAAC;aACjB;SACF,CAAC;KACH;IAED,OAAO,CAACH,GAAY,EAAEC,GAAa,EAAEC,IAAU,GAAK;QAClD,mBAAmB;QACnB,IAAIN,WAAW,IAAI,OAAOM,IAAI,KAAK,UAAU,EAAE;YAC7C,OAAOA,IAAI,CAACC,SAAS,CAAC,CAAC;SACxB;QAED,MAAMC,SAAS,GAAGX,aAAa,CAACO,GAAG,CAAC,AAAC;QACrC,IAAII,SAAS,EAAE;YACbR,WAAW,GAAG,IAAI,CAAC;YACnBS,CAAAA,GAAAA,kBAAa,AAAqE,CAAA,cAArE,CAAC,aAAa,EAAEC,CAAAA,GAAAA,wBAAuB,AAA6B,CAAA,wBAA7B,CAACZ,WAAW,EAAEC,GAAG,EAAES,SAAS,CAAC,CAAC,CAAC;SACpF;QAED,IAAI,OAAOF,IAAI,KAAK,UAAU,EAAE;YAC9B,OAAOA,IAAI,CAACC,SAAS,CAAC,CAAC;SACxB;KACF,CAAC;CACH;AAGM,SAASV,aAAa,CAC3BO,GAAuD,EACrC;QACdA,GAAqB,EAIrBA,IAAO;IAJX,IAAIA,CAAAA,GAAqB,GAArBA,GAAG,CAACO,OAAO,CAAC,QAAQ,CAAC,SAAU,GAA/BP,KAAAA,CAA+B,GAA/BA,GAAqB,CAAEQ,QAAQ,CAAC,iBAAiB,CAAC,EAAE;QACtD,OAAO;YAAEC,IAAI,EAAE,QAAQ;SAAE,CAAC;KAC3B;IAED,IAAIT,CAAAA,IAAO,GAAPA,GAAG,CAACU,GAAG,SAAY,GAAnBV,KAAAA,CAAmB,GAAnBA,IAAO,CAAEW,UAAU,CAAC,OAAO,CAAC,EAAE;YACPX,IAAyB;QAAlD,MAAMY,gBAAgB,GAAGZ,CAAAA,IAAyB,GAAzBA,GAAG,CAACO,OAAO,CAAC,YAAY,CAAC,SAAO,GAAhCP,KAAAA,CAAgC,GAAhCA,IAAyB,CAAEa,KAAK,uBAAuB,AAAC;QACjF,IAAID,gBAAgB,EAAE;YACpB,OAAO;gBACLH,IAAI,EAAEG,gBAAgB,CAAC,CAAC,CAAC,CAACE,WAAW,EAAE;gBACvCC,OAAO,EAAEH,gBAAgB,CAAC,CAAC,CAAC;aAC7B,CAAC;SACH;KACF;IAED,OAAO,IAAI,CAAC;CACb"}
|
|
@@ -94,7 +94,7 @@ async function logEventAsync(event, properties = {}) {
|
|
|
94
94
|
}
|
|
95
95
|
const { userId , deviceId } = identifyData;
|
|
96
96
|
const commonEventProperties = {
|
|
97
|
-
source_version: "0.
|
|
97
|
+
source_version: "0.11.0",
|
|
98
98
|
source: "expo"
|
|
99
99
|
};
|
|
100
100
|
const identity = {
|
|
@@ -135,7 +135,7 @@ function getContext() {
|
|
|
135
135
|
},
|
|
136
136
|
app: {
|
|
137
137
|
name: "expo",
|
|
138
|
-
version: "0.
|
|
138
|
+
version: "0.11.0"
|
|
139
139
|
},
|
|
140
140
|
ci: ciInfo.isCI ? {
|
|
141
141
|
name: ciInfo.name,
|
package/build/src/utils/env.js
CHANGED
|
@@ -115,6 +115,9 @@ class Env {
|
|
|
115
115
|
/** Disable lazy bundling in Metro bundler. */ get EXPO_NO_METRO_LAZY() {
|
|
116
116
|
return (0, _getenv).boolish("EXPO_NO_METRO_LAZY", false);
|
|
117
117
|
}
|
|
118
|
+
/** Enable the unstable inverse dependency stack trace for Metro bundling errors. */ get EXPO_METRO_UNSTABLE_ERRORS() {
|
|
119
|
+
return (0, _getenv).boolish("EXPO_METRO_UNSTABLE_ERRORS", false);
|
|
120
|
+
}
|
|
118
121
|
}
|
|
119
122
|
const env = new Env();
|
|
120
123
|
exports.env = env;
|