expo-router 3.5.3 → 3.5.5

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/_ctx.android.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export const ctx = require.context(
2
2
  process.env.EXPO_ROUTER_APP_ROOT,
3
3
  true,
4
- /^(?:\.\/)(?!(?:(?:(?:.*\+api)|(?:\+html)))\.[tj]sx?$).*\.[tj]sx?$/,
4
+ /^(?:\.\/)(?!(?:(?:(?:.*\+api)|(?:\+html)))\.[tj]sx?$).*(?:\.ios|\.web)?\.[tj]sx?$/,
5
5
  process.env.EXPO_ROUTER_IMPORT_MODE
6
6
  );
package/_ctx.ios.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export const ctx = require.context(
2
2
  process.env.EXPO_ROUTER_APP_ROOT,
3
3
  true,
4
- /^(?:\.\/)(?!(?:(?:(?:.*\+api)|(?:\+html)))\.[tj]sx?$).*\.[tj]sx?$/,
4
+ /^(?:\.\/)(?!(?:(?:(?:.*\+api)|(?:\+html)))\.[tj]sx?$).*(?:\.android|\.web)?\.[tj]sx?$/,
5
5
  process.env.EXPO_ROUTER_IMPORT_MODE
6
6
  );
package/_ctx.web.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export const ctx = require.context(
2
2
  process.env.EXPO_ROUTER_APP_ROOT,
3
3
  true,
4
- /^(?:\.\/)(?!(?:(?:(?:.*\+api)|(?:\+html)))\.[tj]sx?$).*\.[tj]sx?$/,
4
+ /^(?:\.\/)(?!(?:(?:(?:.*\+api)|(?:\+html)))\.[tj]sx?$).*(?:\.android|\.ios|\.native)?\.[tj]sx?$/,
5
5
  process.env.EXPO_ROUTER_IMPORT_MODE
6
6
  );
@@ -8,6 +8,8 @@ export type Options = {
8
8
  internal_stripLoadRoute?: boolean;
9
9
  skipGenerated?: boolean;
10
10
  importMode?: string;
11
+ platformRoutes?: boolean;
12
+ platform?: string;
11
13
  };
12
14
  /**
13
15
  * Given a Metro context module, return an array of nested routes.
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAQvD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAQF;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,EAAE,OAAO,GAAE,OAAY,GAAG,SAAS,GAAG,IAAI,CAehG;AAED,wBAAgB,cAAc,CAC5B,aAAa,EAAE,cAAc,EAC7B,OAAO,GAAE,OAAY,GACpB,SAAS,GAAG,IAAI,CAKlB;AAqSD,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,OAAO,YAM9C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAwBzF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAqBxE"}
1
+ {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAQvD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAElC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAUF;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,EAAE,OAAO,GAAE,OAAY,GAAG,SAAS,GAAG,IAAI,CAehG;AAED,wBAAgB,cAAc,CAC5B,aAAa,EAAE,cAAc,EAC7B,OAAO,GAAE,OAAY,GACpB,SAAS,GAAG,IAAI,CAKlB;AAsUD,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,OAAO,YAM9C;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAwBzF;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,GAAG,IAAI,CAqBxE"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateDynamic = exports.extrapolateGroups = exports.getIgnoreList = exports.getExactRoutes = exports.getRoutes = void 0;
4
4
  const matchers_1 = require("./matchers");
5
+ const validPlatforms = new Set(['android', 'ios', 'native', 'web']);
5
6
  /**
6
7
  * Given a Metro context module, return an array of nested routes.
7
8
  *
@@ -57,7 +58,7 @@ function getDirectoryTree(contextModule, options) {
57
58
  continue;
58
59
  }
59
60
  isValid = true;
60
- const meta = getFileMeta(filePath);
61
+ const meta = getFileMeta(filePath, options);
61
62
  // This is a file that should be ignored. e.g maybe it has an invalid platform?
62
63
  if (meta.specificity < 0) {
63
64
  continue;
@@ -135,7 +136,7 @@ function getDirectoryTree(contextModule, options) {
135
136
  nodes = [];
136
137
  directory.files.set(fileKey, nodes);
137
138
  }
138
- // TODO(Platform Route): Throw error if specificity > 0, as you cannot specify platform extensions for api routes
139
+ // API Routes have no specificity, they are always the first node
139
140
  const existing = nodes[0];
140
141
  if (existing) {
141
142
  // In production, use the first route found
@@ -220,7 +221,7 @@ pathToRemove = '') {
220
221
  */
221
222
  if (directory.layout) {
222
223
  const previousLayout = layout;
223
- layout = directory.layout[0]; // TODO(Platform Routes): We need to pick the most specific layout.
224
+ layout = getMostSpecific(directory.layout);
224
225
  // Add the new layout as a child of its parent
225
226
  if (previousLayout) {
226
227
  previousLayout.children.push(layout);
@@ -239,8 +240,7 @@ pathToRemove = '') {
239
240
  if (!layout)
240
241
  throw new Error('Expo Router Internal Error: No nearest layout');
241
242
  for (const routes of directory.files.values()) {
242
- // TODO(Platform Routes): We need to pick the most specific layout and ensure that all routes have a non-platform route.
243
- const routeNode = routes[0];
243
+ const routeNode = getMostSpecific(routes);
244
244
  // `route` is the absolute pathname. We need to make this relative to the nearest layout
245
245
  routeNode.route = routeNode.route.replace(pathToRemove, '');
246
246
  routeNode.dynamic = generateDynamic(routeNode.route);
@@ -255,14 +255,15 @@ pathToRemove = '') {
255
255
  }
256
256
  return layout;
257
257
  }
258
- function getFileMeta(key) {
258
+ function getFileMeta(key, options) {
259
259
  // Remove the leading `./`
260
260
  key = key.replace(/^\.\//, '');
261
261
  const parts = key.split('/');
262
+ let route = (0, matchers_1.removeSupportedExtensions)(key);
262
263
  const filename = parts[parts.length - 1];
263
264
  const filenameWithoutExtensions = (0, matchers_1.removeSupportedExtensions)(filename);
264
265
  const isLayout = filenameWithoutExtensions === '_layout';
265
- const isApi = filename.match(/\+api\.[jt]sx?$/);
266
+ const isApi = filename.match(/\+api\.(\w+\.)?[jt]sx?$/);
266
267
  if (filenameWithoutExtensions.startsWith('(') && filenameWithoutExtensions.endsWith(')')) {
267
268
  throw new Error(`Invalid route ./${key}. Routes cannot end with '(group)' syntax`);
268
269
  }
@@ -271,9 +272,41 @@ function getFileMeta(key) {
271
272
  const renamedRoute = [...parts.slice(0, -1), filename.slice(1)].join('/');
272
273
  throw new Error(`Invalid route ./${key}. Route nodes cannot start with the '+' character. "Please rename to ${renamedRoute}"`);
273
274
  }
275
+ let specificity = 0;
276
+ const platformExtension = filenameWithoutExtensions.split('.')[1];
277
+ const hasPlatformExtension = validPlatforms.has(platformExtension);
278
+ const usePlatformRoutes = options.platformRoutes ?? true;
279
+ if (hasPlatformExtension) {
280
+ if (!usePlatformRoutes) {
281
+ // If the user has disabled platform routes, then we should ignore this file
282
+ specificity = -1;
283
+ }
284
+ else if (!options.platform) {
285
+ // If we don't have a platform, then we should ignore this file
286
+ // This used by typed routes, sitemap, etc
287
+ specificity = -1;
288
+ }
289
+ else if (platformExtension === options.platform) {
290
+ // If the platform extension is the same as the options.platform, then it is the most specific
291
+ specificity = 2;
292
+ }
293
+ else if (platformExtension === 'native' && options.platform !== 'web') {
294
+ // `native` is allow but isn't as specific as the platform
295
+ specificity = 1;
296
+ }
297
+ else if (platformExtension !== options.platform) {
298
+ // Somehow we have a platform extension that doesn't match the options.platform and it isn't native
299
+ // This is an invalid file and we will ignore it
300
+ specificity = -1;
301
+ }
302
+ if (isApi && specificity !== 0) {
303
+ throw new Error(`Api routes cannot have platform extensions. Please remove '.${platformExtension}' from './${key}'`);
304
+ }
305
+ route = route.replace(new RegExp(`.${platformExtension}$`), '');
306
+ }
274
307
  return {
275
- route: (0, matchers_1.removeSupportedExtensions)(key),
276
- specificity: 0,
308
+ route,
309
+ specificity,
277
310
  isLayout,
278
311
  isApi,
279
312
  };
@@ -457,4 +490,13 @@ function crawlAndAppendInitialRoutesAndEntryFiles(node, options, entryPoints = [
457
490
  }
458
491
  }
459
492
  }
493
+ function getMostSpecific(routes) {
494
+ const route = routes[routes.length - 1];
495
+ if (!routes[0]) {
496
+ throw new Error(`The file ${route.contextKey} does not have a fallback sibling file without a platform extension.`);
497
+ }
498
+ // This works even tho routes is holey array (e.g it might have index 0 and 2 but not 1)
499
+ // `.length` includes the holes in its count
500
+ return routes[routes.length - 1];
501
+ }
460
502
  //# sourceMappingURL=getRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.js","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":";;;AACA,yCAMoB;AAqBpB;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAC,aAA6B,EAAE,UAAmB,EAAE;IAC5E,MAAM,aAAa,GAAG,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAE/D,yBAAyB;IACzB,IAAI,CAAC,aAAa,EAAE;QAClB,OAAO,IAAI,CAAC;KACb;IAED,MAAM,QAAQ,GAAG,4BAA4B,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEtE,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE;QAC9B,wCAAwC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;KAC7D;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAfD,8BAeC;AAED,SAAgB,cAAc,CAC5B,aAA6B,EAC7B,UAAmB,EAAE;IAErB,OAAO,SAAS,CAAC,aAAa,EAAE;QAC9B,GAAG,OAAO;QACV,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;AACL,CAAC;AARD,wCAQC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,aAA6B,EAAE,OAAgB;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAE7E,MAAM,UAAU,GAAa,CAAC,uBAAuB,CAAC,CAAC,CAAC,oCAAoC;IAE5F,IAAI,OAAO,CAAC,MAAM,EAAE;QAClB,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;KACpC;IACD,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE;QAC9B,UAAU,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;KACpC;IAED,MAAM,aAAa,GAAkB;QACnC,KAAK,EAAE,IAAI,GAAG,EAAE;QAChB,cAAc,EAAE,IAAI,GAAG,EAAE;KAC1B,CAAC;IAEF,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,MAAM,QAAQ,IAAI,aAAa,CAAC,IAAI,EAAE,EAAE;QAC3C,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE;YACpD,SAAS;SACV;QAED,OAAO,GAAG,IAAI,CAAC;QAEf,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEnC,+EAA+E;QAC/E,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE;YACxB,SAAS;SACV;QAED,IAAI,IAAI,GAAc;YACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO;YAC7D,SAAS;gBACP,IAAI,OAAO,CAAC,mBAAmB,EAAE;oBAC/B,IAAI;wBACF,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;qBAChC;oBAAC,MAAM;wBACN,OAAO,EAAE,CAAC;qBACX;iBACF;qBAAM;oBACL,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;iBAChC;YACH,CAAC;YACD,UAAU,EAAE,QAAQ;YACpB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,EAAE,EAAE,sHAAsH;SACrI,CAAC;QAEF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;YAC1C,6EAA6E;YAC7E,6BAA6B;YAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,UAAU,KAAK,MAAM,EAAE;gBAChD,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE;oBAC9B,SAAS;iBACV;aACF;SACF;QAED;;;WAGG;QACH,KAAK,MAAM,KAAK,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YACjD,+FAA+F;YAC/F,MAAM,iBAAiB,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAExD,0EAA0E;YAC1E,IAAI,SAAS,GAAG,aAAa,CAAC;YAE9B,KAAK,MAAM,IAAI,IAAI,iBAAiB,EAAE;gBACpC,IAAI,YAAY,GAAG,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAEtD,oCAAoC;gBACpC,IAAI,CAAC,YAAY,EAAE;oBACjB,YAAY,GAAG;wBACb,KAAK,EAAE,IAAI,GAAG,EAAE;wBAChB,cAAc,EAAE,IAAI,GAAG,EAAE;qBAC1B,CAAC;oBACF,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;iBAClD;gBAED,SAAS,GAAG,YAAY,CAAC;aAC1B;YAED,gCAAgC;YAChC,IAAI,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC;YAE1B,IAAI,IAAI,CAAC,QAAQ,EAAE;gBACjB,SAAS,CAAC,MAAM,KAAK,EAAE,CAAC;gBACxB,MAAM,QAAQ,GAAG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACpD,IAAI,QAAQ,EAAE;oBACZ,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;wBACzC,MAAM,IAAI,KAAK,CACb,gBAAgB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,gDAAgD,CACxI,CAAC;qBACH;iBACF;qBAAM;oBACL,IAAI,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACpC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;iBAC3C;aACF;iBAAM,IAAI,IAAI,CAAC,KAAK,EAAE;gBACrB,MAAM,OAAO,GAAG,GAAG,KAAK,MAAM,CAAC;gBAC/B,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBAEzC,IAAI,CAAC,KAAK,EAAE;oBACV,KAAK,GAAG,EAAE,CAAC;oBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;iBACrC;gBAED,iHAAiH;gBAEjH,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBAE1B,IAAI,QAAQ,EAAE;oBACZ,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;wBACzC,MAAM,IAAI,KAAK,CACb,uBAAuB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,gDAAgD,CAC/I,CAAC;qBACH;iBACF;qBAAM;oBACL,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;iBACjB;aACF;iBAAM;gBACL,IAAI,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAEvC,IAAI,CAAC,KAAK,EAAE;oBACV,KAAK,GAAG,EAAE,CAAC;oBACX,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;iBACnC;gBAED;;;;;mBAKG;gBACH,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBACzC,IAAI,QAAQ,EAAE;oBACZ,2CAA2C;oBAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;wBACzC,MAAM,IAAI,KAAK,CACb,oBAAoB,QAAQ,UAAU,QAAQ,CAAC,UAAU,6BAA6B,KAAK,gDAAgD,CAC5I,CAAC;qBACH;iBACF;qBAAM;oBACL,SAAS,KAAK,IAAI,CAAC;oBACnB,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;iBAChC;aACF;SACF;KACF;IAED,sEAAsE;IACtE,IAAI,CAAC,OAAO,EAAE;QACZ,OAAO,IAAI,CAAC;KACb;IAED;;;OAGG;IACH,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE;QACzB,aAAa,CAAC,MAAM,GAAG;YACrB;gBACE,IAAI,EAAE,QAAQ;gBACd,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;oBAChB,OAAO,EAAG,OAAO,CAAC,mBAAmB,CAAwC;yBAC1E,gBAAgB;iBACpB,CAAC;gBACF,8CAA8C;gBAC9C,UAAU,EAAE,sCAAsC;gBAClD,KAAK,EAAE,EAAE;gBACT,SAAS,EAAE,IAAI;gBACf,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,EAAE;aACb;SACF,CAAC;KACH;IAED,gDAAgD;IAChD,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;QAC1B,IAAI,SAAS,EAAE;YACb,kBAAkB,CAAC,aAAa,CAAC,CAAC;SACnC;QACD,mBAAmB,CAAC,aAAa,CAAC,CAAC;KACpC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,SAAS,4BAA4B,CACnC,SAAwB,EACxB,OAAgB;AAChB,oDAAoD;AACpD,MAAkB;AAClB,8CAA8C;AAC9C,YAAY,GAAG,EAAE;IAEjB;;OAEG;IACH,IAAI,SAAS,CAAC,MAAM,EAAE;QACpB,MAAM,cAAc,GAAG,MAAM,CAAC;QAC9B,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,mEAAmE;QAEjG,8CAA8C;QAC9C,IAAI,cAAc,EAAE;YAClB,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;SACtC;QAED,IAAI,OAAO,CAAC,uBAAuB,EAAE;YACnC,OAAQ,MAAc,CAAC,SAAS,CAAC;SAClC;QAED,sFAAsF;QACtF,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QACxD,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtD,6EAA6E;QAC7E,MAAM,CAAC,KAAK,GAAG,QAAQ,CAAC;QACxB,MAAM,CAAC,OAAO,GAAG,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;KAChD;IAED,oGAAoG;IACpG,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IAE9E,KAAK,MAAM,MAAM,IAAI,SAAS,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE;QAC7C,wHAAwH;QACxH,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QAE5B,wFAAwF;QACxF,SAAS,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC5D,SAAS,CAAC,OAAO,GAAG,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAErD,IAAI,OAAO,CAAC,uBAAuB,EAAE;YACnC,OAAQ,SAAiB,CAAC,SAAS,CAAC;SACrC;QAED,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;KACjC;IAED,yCAAyC;IACzC,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE;QACrD,4BAA4B,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;KACpE;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,0BAA0B;IAC1B,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE/B,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,MAAM,yBAAyB,GAAG,IAAA,oCAAyB,EAAC,QAAQ,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAG,yBAAyB,KAAK,SAAS,CAAC;IACzD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAEhD,IAAI,yBAAyB,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE;QACxF,MAAM,IAAI,KAAK,CAAC,mBAAmB,GAAG,2CAA2C,CAAC,CAAC;KACpF;IAED,uFAAuF;IACvF,IAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,yBAAyB,KAAK,YAAY,EAAE;QACpF,MAAM,YAAY,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,IAAI,KAAK,CACb,mBAAmB,GAAG,wEAAwE,YAAY,GAAG,CAC9G,CAAC;KACH;IAED,OAAO;QACL,KAAK,EAAE,IAAA,oCAAyB,EAAC,GAAG,CAAC;QACrC,WAAW,EAAE,CAAC;QACd,QAAQ;QACR,KAAK;KACN,CAAC;AACJ,CAAC;AAED,SAAgB,aAAa,CAAC,OAAiB;IAC7C,MAAM,MAAM,GAAa,CAAC,uBAAuB,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/E,IAAI,OAAO,EAAE,iBAAiB,KAAK,IAAI,EAAE;QACvC,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;KAChC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAND,sCAMC;AAED;;;;GAIG;AACH,SAAgB,iBAAiB,CAAC,GAAW,EAAE,OAAoB,IAAI,GAAG,EAAE;IAC1E,MAAM,KAAK,GAAG,IAAA,8BAAmB,EAAC,GAAG,CAAC,CAAC;IAEvC,IAAI,CAAC,KAAK,EAAE;QACV,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;KACb;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAElC,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,EAAE;QACpC,MAAM,IAAI,KAAK,CAAC,qDAAqD,MAAM,SAAS,GAAG,IAAI,CAAC,CAAC;KAC9F;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;KACb;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;QAC1B,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;KAC3D;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAxBD,8CAwBC;AAED,SAAgB,eAAe,CAAC,IAAY;IAC1C,MAAM,OAAO,GAAG,IAAI;SACjB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAA4B,EAAE;QACtC,IAAI,IAAI,KAAK,YAAY,EAAE;YACzB,OAAO;gBACL,IAAI,EAAE,YAAY;gBAClB,IAAI,EAAE,IAAI;gBACV,QAAQ,EAAE,IAAI;aACf,CAAC;SACH;QAED,MAAM,eAAe,GAAG,IAAA,oCAAyB,EAAC,IAAI,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,eAAe,IAAI,IAAA,2BAAgB,EAAC,IAAI,CAAC,CAAC;QAE9D,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAC9B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,eAAe,EAAE,CAAC;IACxD,CAAC,CAAC;SACD,MAAM,CAAC,CAAC,IAAI,EAA6B,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAEvD,OAAO,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC;AAC/C,CAAC;AArBD,0CAqBC;AAED,SAAS,kBAAkB,CAAC,SAAwB;IAClD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE;QACpC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE;YAC9B;gBACE,SAAS;oBACP,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;oBAC9D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC;gBAC7C,CAAC;gBACD,KAAK,EAAE,UAAU;gBACjB,IAAI,EAAE,OAAO;gBACb,UAAU,EAAE,oCAAoC;gBAChD,SAAS,EAAE,IAAI;gBACf,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,EAAE;aACb;SACF,CAAC,CAAC;KACJ;AACH,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAwB;IACnD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE;QACtC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,EAAE;YAChC;gBACE,SAAS;oBACP,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC,SAAS,EAAE,CAAC;gBAC7D,CAAC;gBACD,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,YAAY;gBACnB,UAAU,EAAE,sCAAsC;gBAClD,SAAS,EAAE,IAAI;gBACf,QAAQ,EAAE,IAAI;gBACd,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;gBAC7D,QAAQ,EAAE,EAAE;aACb;SACF,CAAC,CAAC;KACJ;AACH,CAAC;AAED,SAAS,aAAa,CAAC,IAAe,EAAE,OAAgB;IACtD;;;;;OAKG;IAEH,wCAAwC;IACxC,MAAM,SAAS,GAAG,IAAA,yBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7C,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACtD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC;IAC3D,CAAC,CAAC,CAAC;IACH,IAAI,gBAAgB,GAAG,kBAAkB,EAAE,KAAK,CAAC;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;IAChC,IAAI,MAAM,EAAE,iBAAiB,EAAE;QAC7B,kGAAkG;QAClG,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,gBAAgB,CAAC;QAEjF,IAAI,SAAS,EAAE;YACb,sHAAsH;YACtH,MAAM,6BAA6B,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;YAE9F,gBAAgB,GAAG,6BAA6B,IAAI,gBAAgB,CAAC;SACtE;KACF;IAED,OAAO;QACL,GAAG,IAAI;QACP,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC;QAC5C,QAAQ,EAAE,EAAE;QACZ,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,SAAS,wCAAwC,CAC/C,IAAe,EACf,OAAgB,EAChB,cAAwB,EAAE;IAE1B,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE;QACzB,IAAI,CAAC,WAAW,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;KACpE;SAAM,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ,EAAE;QACjC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE;YAClB,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,CAAC,UAAU,qCAAqC,CAAC,CAAC;SAClF;QAED,6DAA6D;QAC7D,WAAW,GAAG,CAAC,GAAG,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;QAEhD;;;;;WAKG;QACH,MAAM,SAAS,GAAG,IAAA,yBAAc,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACtD,OAAO,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,KAAK,SAAS,CAAC;QAC3D,CAAC,CAAC,CAAC;QACH,IAAI,gBAAgB,GAAG,kBAAkB,EAAE,KAAK,CAAC;QACjD,wCAAwC;QACxC,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE;YACpC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,IAAI,MAAM,EAAE,iBAAiB,EAAE;gBAC7B,kGAAkG;gBAClG,gBAAgB,GAAG,MAAM,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,gBAAgB,CAAC;gBAEjF,IAAI,SAAS,EAAE;oBACb,sHAAsH;oBACtH,MAAM,6BAA6B,GACjC,MAAM,CAAC,iBAAiB,EAAE,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;oBAE1D,gBAAgB,GAAG,6BAA6B,IAAI,gBAAgB,CAAC;iBACtE;aACF;SACF;QAED,IAAI,gBAAgB,EAAE;YACpB,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,gBAAgB,CAAC,CAAC;YACrF,IAAI,CAAC,YAAY,EAAE;gBACjB,MAAM,kBAAkB,GAAG,IAAI,CAAC,QAAQ;qBACrC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC;qBACnC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;qBAClC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEd,IAAI,SAAS,EAAE;oBACb,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,UAAU,kCAAkC,gBAAgB,iBAAiB,SAAS,0BAA0B,kBAAkB,EAAE,CACpJ,CAAC;iBACH;qBAAM;oBACL,MAAM,IAAI,KAAK,CACb,UAAU,IAAI,CAAC,UAAU,kCAAkC,gBAAgB,yBAAyB,kBAAkB,EAAE,CACzH,CAAC;iBACH;aACF;YAED,2GAA2G;YAC3G,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;YACzC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;SAC3C;QAED,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,EAAE;YACjC,wCAAwC,CAAC,KAAK,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;SACvE;KACF;AACH,CAAC","sourcesContent":["import { DynamicConvention, RouteNode } from './Route';\nimport {\n matchArrayGroupName,\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchGroupName,\n removeSupportedExtensions,\n} from './matchers';\nimport { RequireContext } from './types';\n\nexport type Options = {\n ignore?: RegExp[];\n preserveApiRoutes?: boolean;\n ignoreRequireErrors?: boolean;\n ignoreEntryPoints?: boolean;\n /* Used to simplify testing for toEqual() comparison */\n internal_stripLoadRoute?: boolean;\n /* Used to simplify by skipping the generated routes */\n skipGenerated?: boolean;\n importMode?: string;\n};\n\ntype DirectoryNode = {\n layout?: RouteNode[];\n files: Map<string, RouteNode[]>;\n subdirectories: Map<string, DirectoryNode>;\n};\n\n/**\n * Given a Metro context module, return an array of nested routes.\n *\n * This is a two step process:\n * 1. Convert the RequireContext keys (file paths) into a directory tree.\n * - This should extrapolate array syntax into multiple routes\n * - Routes are given a specificity score\n * 2. Flatten the directory tree into routes\n * - Routes in directories without _layout files are hoisted to the nearest _layout\n * - The name of the route is relative to the nearest _layout\n * - If multiple routes have the same name, the most specific route is used\n */\nexport function getRoutes(contextModule: RequireContext, options: Options = {}): RouteNode | null {\n const directoryTree = getDirectoryTree(contextModule, options);\n\n // If there are no routes\n if (!directoryTree) {\n return null;\n }\n\n const rootNode = flattenDirectoryTreeToRoutes(directoryTree, options);\n\n if (!options.ignoreEntryPoints) {\n crawlAndAppendInitialRoutesAndEntryFiles(rootNode, options);\n }\n\n return rootNode;\n}\n\nexport function getExactRoutes(\n contextModule: RequireContext,\n options: Options = {}\n): RouteNode | null {\n return getRoutes(contextModule, {\n ...options,\n skipGenerated: true,\n });\n}\n\n/**\n * Converts the RequireContext keys (file paths) into a directory tree.\n */\nfunction getDirectoryTree(contextModule: RequireContext, options: Options) {\n const importMode = options.importMode || process.env.EXPO_ROUTER_IMPORT_MODE;\n\n const ignoreList: RegExp[] = [/^\\.\\/\\+html\\.[tj]sx?$/]; // Ignore the top level ./+html file\n\n if (options.ignore) {\n ignoreList.push(...options.ignore);\n }\n if (!options.preserveApiRoutes) {\n ignoreList.push(/\\+api\\.[tj]sx?$/);\n }\n\n const rootDirectory: DirectoryNode = {\n files: new Map(),\n subdirectories: new Map(),\n };\n\n let hasRoutes = false;\n let isValid = false;\n\n for (const filePath of contextModule.keys()) {\n if (ignoreList.some((regex) => regex.test(filePath))) {\n continue;\n }\n\n isValid = true;\n\n const meta = getFileMeta(filePath);\n\n // This is a file that should be ignored. e.g maybe it has an invalid platform?\n if (meta.specificity < 0) {\n continue;\n }\n\n let node: RouteNode = {\n type: meta.isApi ? 'api' : meta.isLayout ? 'layout' : 'route',\n loadRoute() {\n if (options.ignoreRequireErrors) {\n try {\n return contextModule(filePath);\n } catch {\n return {};\n }\n } else {\n return contextModule(filePath);\n }\n },\n contextKey: filePath,\n route: '', // This is overwritten during hoisting based upon the _layout\n dynamic: null,\n children: [], // While we are building the directory tree, we don't know the node's children just yet. This is added during hoisting\n };\n\n if (process.env.NODE_ENV === 'development') {\n // If the user has set the `EXPO_ROUTER_IMPORT_MODE` to `sync` then we should\n // filter the missing routes.\n if (node.type !== 'api' && importMode === 'sync') {\n if (!node.loadRoute()?.default) {\n continue;\n }\n }\n }\n\n /**\n * A single filepath may be extrapolated into multiple routes if it contains array syntax.\n * Another way to thinking about is that a filepath node is present in multiple leaves of the directory tree.\n */\n for (const route of extrapolateGroups(meta.route)) {\n // Traverse the directory tree to its leaf node, creating any missing directories along the way\n const subdirectoryParts = route.split('/').slice(0, -1);\n\n // Start at the root directory and traverse the path to the leaf directory\n let directory = rootDirectory;\n\n for (const part of subdirectoryParts) {\n let subDirectory = directory.subdirectories.get(part);\n\n // Create any missing subdirectories\n if (!subDirectory) {\n subDirectory = {\n files: new Map(),\n subdirectories: new Map(),\n };\n directory.subdirectories.set(part, subDirectory);\n }\n\n directory = subDirectory;\n }\n\n // Clone the node for this route\n node = { ...node, route };\n\n if (meta.isLayout) {\n directory.layout ??= [];\n const existing = directory.layout[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The layouts \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Please remove or rename one of these files.`\n );\n }\n } else {\n node = getLayoutNode(node, options);\n directory.layout[meta.specificity] = node;\n }\n } else if (meta.isApi) {\n const fileKey = `${route}+api`;\n let nodes = directory.files.get(fileKey);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(fileKey, nodes);\n }\n\n // TODO(Platform Route): Throw error if specificity > 0, as you cannot specify platform extensions for api routes\n\n const existing = nodes[0];\n\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The API route file \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Please remove or rename one of these files.`\n );\n }\n } else {\n nodes[0] = node;\n }\n } else {\n let nodes = directory.files.get(route);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(route, nodes);\n }\n\n /**\n * If there is an existing node with the same specificity, then we have a conflict.\n * NOTE(Platform Routes):\n * We cannot check for specificity conflicts here, as we haven't processed all the context keys yet!\n * This will be checked during hoisting, as well as enforcing that all routes have a non-platform route.\n */\n const existing = nodes[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The route files \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Please remove or rename one of these files.`\n );\n }\n } else {\n hasRoutes ||= true;\n nodes[meta.specificity] = node;\n }\n }\n }\n }\n\n // If there are no routes/layouts then we should display the tutorial.\n if (!isValid) {\n return null;\n }\n\n /**\n * If there are no top-level _layout, add a default _layout\n * While this is a generated route, it will still be generated even if skipGenerated is true.\n */\n if (!rootDirectory.layout) {\n rootDirectory.layout = [\n {\n type: 'layout',\n loadRoute: () => ({\n default: (require('./views/Navigator') as typeof import('./views/Navigator'))\n .DefaultNavigator,\n }),\n // Generate a fake file name for the directory\n contextKey: 'expo-router/build/views/Navigator.js',\n route: '',\n generated: true,\n dynamic: null,\n children: [],\n },\n ];\n }\n\n // Only include the sitemap if there are routes.\n if (!options.skipGenerated) {\n if (hasRoutes) {\n appendSitemapRoute(rootDirectory);\n }\n appendNotFoundRoute(rootDirectory);\n }\n return rootDirectory;\n}\n\n/**\n * Flatten the directory tree into routes, hoisting routes to the nearest _layout.\n */\nfunction flattenDirectoryTreeToRoutes(\n directory: DirectoryNode,\n options: Options,\n /* The nearest _layout file in the directory tree */\n layout?: RouteNode,\n /* Route names are relative to their layout */\n pathToRemove = ''\n) {\n /**\n * This directory has a _layout file so it becomes the new target for hoisting routes.\n */\n if (directory.layout) {\n const previousLayout = layout;\n layout = directory.layout[0]; // TODO(Platform Routes): We need to pick the most specific layout.\n\n // Add the new layout as a child of its parent\n if (previousLayout) {\n previousLayout.children.push(layout);\n }\n\n if (options.internal_stripLoadRoute) {\n delete (layout as any).loadRoute;\n }\n\n // `route` is the absolute pathname. We need to make this relative to the last _layout\n const newRoute = layout.route.replace(pathToRemove, '');\n pathToRemove = layout.route ? `${layout.route}/` : '';\n\n // Now update this layout with the new relative route and dynamic conventions\n layout.route = newRoute;\n layout.dynamic = generateDynamic(layout.route);\n }\n\n // This should never occur as there will always be a root layout, but it makes the type system happy\n if (!layout) throw new Error('Expo Router Internal Error: No nearest layout');\n\n for (const routes of directory.files.values()) {\n // TODO(Platform Routes): We need to pick the most specific layout and ensure that all routes have a non-platform route.\n const routeNode = routes[0];\n\n // `route` is the absolute pathname. We need to make this relative to the nearest layout\n routeNode.route = routeNode.route.replace(pathToRemove, '');\n routeNode.dynamic = generateDynamic(routeNode.route);\n\n if (options.internal_stripLoadRoute) {\n delete (routeNode as any).loadRoute;\n }\n\n layout.children.push(routeNode);\n }\n\n // Recursively flatten the subdirectories\n for (const child of directory.subdirectories.values()) {\n flattenDirectoryTreeToRoutes(child, options, layout, pathToRemove);\n }\n\n return layout;\n}\n\nfunction getFileMeta(key: string) {\n // Remove the leading `./`\n key = key.replace(/^\\.\\//, '');\n\n const parts = key.split('/');\n const filename = parts[parts.length - 1];\n const filenameWithoutExtensions = removeSupportedExtensions(filename);\n const isLayout = filenameWithoutExtensions === '_layout';\n const isApi = filename.match(/\\+api\\.[jt]sx?$/);\n\n if (filenameWithoutExtensions.startsWith('(') && filenameWithoutExtensions.endsWith(')')) {\n throw new Error(`Invalid route ./${key}. Routes cannot end with '(group)' syntax`);\n }\n\n // Nested routes cannot start with the '+' character, except for the '+not-found' route\n if (!isApi && filename.startsWith('+') && filenameWithoutExtensions !== '+not-found') {\n const renamedRoute = [...parts.slice(0, -1), filename.slice(1)].join('/');\n throw new Error(\n `Invalid route ./${key}. Route nodes cannot start with the '+' character. \"Please rename to ${renamedRoute}\"`\n );\n }\n\n return {\n route: removeSupportedExtensions(key),\n specificity: 0,\n isLayout,\n isApi,\n };\n}\n\nexport function getIgnoreList(options?: Options) {\n const ignore: RegExp[] = [/^\\.\\/\\+html\\.[tj]sx?$/, ...(options?.ignore ?? [])];\n if (options?.preserveApiRoutes !== true) {\n ignore.push(/\\+api\\.[tj]sx?$/);\n }\n return ignore;\n}\n\n/**\n * Generates a set of strings which have the router array syntax extrapolated.\n *\n * /(a,b)/(c,d)/e.tsx => new Set(['a/c/e.tsx', 'a/d/e.tsx', 'b/c/e.tsx', 'b/d/e.tsx'])\n */\nexport function extrapolateGroups(key: string, keys: Set<string> = new Set()): Set<string> {\n const match = matchArrayGroupName(key);\n\n if (!match) {\n keys.add(key);\n return keys;\n }\n const groups = match.split(',');\n const groupsSet = new Set(groups);\n\n if (groupsSet.size !== groups.length) {\n throw new Error(`Array syntax cannot contain duplicate group name \"${groups}\" in \"${key}\".`);\n }\n\n if (groups.length === 1) {\n keys.add(key);\n return keys;\n }\n\n for (const group of groups) {\n extrapolateGroups(key.replace(match, group.trim()), keys);\n }\n\n return keys;\n}\n\nexport function generateDynamic(path: string): DynamicConvention[] | null {\n const dynamic = path\n .split('/')\n .map((part): DynamicConvention | null => {\n if (part === '+not-found') {\n return {\n name: '+not-found',\n deep: true,\n notFound: true,\n };\n }\n\n const deepDynamicName = matchDeepDynamicRouteName(part);\n const dynamicName = deepDynamicName ?? matchDynamicName(part);\n\n if (!dynamicName) return null;\n return { name: dynamicName, deep: !!deepDynamicName };\n })\n .filter((part): part is DynamicConvention => !!part);\n\n return dynamic.length === 0 ? null : dynamic;\n}\n\nfunction appendSitemapRoute(directory: DirectoryNode) {\n if (!directory.files.has('_sitemap')) {\n directory.files.set('_sitemap', [\n {\n loadRoute() {\n const { Sitemap, getNavOptions } = require('./views/Sitemap');\n return { default: Sitemap, getNavOptions };\n },\n route: '_sitemap',\n type: 'route',\n contextKey: 'expo-router/build/views/Sitemap.js',\n generated: true,\n internal: true,\n dynamic: null,\n children: [],\n },\n ]);\n }\n}\n\nfunction appendNotFoundRoute(directory: DirectoryNode) {\n if (!directory.files.has('+not-found')) {\n directory.files.set('+not-found', [\n {\n loadRoute() {\n return { default: require('./views/Unmatched').Unmatched };\n },\n type: 'route',\n route: '+not-found',\n contextKey: 'expo-router/build/views/Unmatched.js',\n generated: true,\n internal: true,\n dynamic: [{ name: '+not-found', deep: true, notFound: true }],\n children: [],\n },\n ]);\n }\n}\n\nfunction getLayoutNode(node: RouteNode, options: Options) {\n /**\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different initialRouteName based upon the first group name.\n *\n * So\n */\n\n // We may strip loadRoute during testing\n const groupName = matchGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let initialRouteName = childMatchingGroup?.route;\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n initialRouteName = loaded.unstable_settings.initialRouteName ?? initialRouteName;\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName = loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n initialRouteName = groupSpecificInitialRouteName ?? initialRouteName;\n }\n }\n\n return {\n ...node,\n route: node.route.replace(/\\/?_layout$/, ''),\n children: [], // Each layout should have its own children\n initialRouteName,\n };\n}\n\nfunction crawlAndAppendInitialRoutesAndEntryFiles(\n node: RouteNode,\n options: Options,\n entryPoints: string[] = []\n) {\n if (node.type === 'route') {\n node.entryPoints = [...new Set([...entryPoints, node.contextKey])];\n } else if (node.type === 'layout') {\n if (!node.children) {\n throw new Error(`Layout \"${node.contextKey}\" does not contain any child routes`);\n }\n\n // Every node below this layout will have it as an entryPoint\n entryPoints = [...entryPoints, node.contextKey];\n\n /**\n * Calculate the initialRouteNode\n *\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different initialRouteName based upon the first group.\n */\n const groupName = matchGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let initialRouteName = childMatchingGroup?.route;\n // We may strip loadRoute during testing\n if (!options.internal_stripLoadRoute) {\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n initialRouteName = loaded.unstable_settings.initialRouteName ?? initialRouteName;\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName =\n loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n initialRouteName = groupSpecificInitialRouteName ?? initialRouteName;\n }\n }\n }\n\n if (initialRouteName) {\n const initialRoute = node.children.find((child) => child.route === initialRouteName);\n if (!initialRoute) {\n const validInitialRoutes = node.children\n .filter((child) => !child.generated)\n .map((child) => `'${child.route}'`)\n .join(', ');\n\n if (groupName) {\n throw new Error(\n `Layout ${node.contextKey} has invalid initialRouteName '${initialRouteName}' for group '(${groupName})'. Valid options are: ${validInitialRoutes}`\n );\n } else {\n throw new Error(\n `Layout ${node.contextKey} has invalid initialRouteName '${initialRouteName}'. Valid options are: ${validInitialRoutes}`\n );\n }\n }\n\n // Navigators can add initialsRoutes into the history, so they need to be to be included in the entryPoints\n node.initialRouteName = initialRouteName;\n entryPoints.push(initialRoute.contextKey);\n }\n\n for (const child of node.children) {\n crawlAndAppendInitialRoutesAndEntryFiles(child, options, entryPoints);\n }\n }\n}\n"]}
1
+ {"version":3,"file":"getRoutes.js","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["import { DynamicConvention, RouteNode } from './Route';\nimport {\n matchArrayGroupName,\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchGroupName,\n removeSupportedExtensions,\n} from './matchers';\nimport { RequireContext } from './types';\n\nexport type Options = {\n ignore?: RegExp[];\n preserveApiRoutes?: boolean;\n ignoreRequireErrors?: boolean;\n ignoreEntryPoints?: boolean;\n /* Used to simplify testing for toEqual() comparison */\n internal_stripLoadRoute?: boolean;\n /* Used to simplify by skipping the generated routes */\n skipGenerated?: boolean;\n importMode?: string;\n platformRoutes?: boolean;\n platform?: string;\n};\n\ntype DirectoryNode = {\n layout?: RouteNode[];\n files: Map<string, RouteNode[]>;\n subdirectories: Map<string, DirectoryNode>;\n};\n\nconst validPlatforms = new Set(['android', 'ios', 'native', 'web']);\n\n/**\n * Given a Metro context module, return an array of nested routes.\n *\n * This is a two step process:\n * 1. Convert the RequireContext keys (file paths) into a directory tree.\n * - This should extrapolate array syntax into multiple routes\n * - Routes are given a specificity score\n * 2. Flatten the directory tree into routes\n * - Routes in directories without _layout files are hoisted to the nearest _layout\n * - The name of the route is relative to the nearest _layout\n * - If multiple routes have the same name, the most specific route is used\n */\nexport function getRoutes(contextModule: RequireContext, options: Options = {}): RouteNode | null {\n const directoryTree = getDirectoryTree(contextModule, options);\n\n // If there are no routes\n if (!directoryTree) {\n return null;\n }\n\n const rootNode = flattenDirectoryTreeToRoutes(directoryTree, options);\n\n if (!options.ignoreEntryPoints) {\n crawlAndAppendInitialRoutesAndEntryFiles(rootNode, options);\n }\n\n return rootNode;\n}\n\nexport function getExactRoutes(\n contextModule: RequireContext,\n options: Options = {}\n): RouteNode | null {\n return getRoutes(contextModule, {\n ...options,\n skipGenerated: true,\n });\n}\n\n/**\n * Converts the RequireContext keys (file paths) into a directory tree.\n */\nfunction getDirectoryTree(contextModule: RequireContext, options: Options) {\n const importMode = options.importMode || process.env.EXPO_ROUTER_IMPORT_MODE;\n\n const ignoreList: RegExp[] = [/^\\.\\/\\+html\\.[tj]sx?$/]; // Ignore the top level ./+html file\n\n if (options.ignore) {\n ignoreList.push(...options.ignore);\n }\n if (!options.preserveApiRoutes) {\n ignoreList.push(/\\+api\\.[tj]sx?$/);\n }\n\n const rootDirectory: DirectoryNode = {\n files: new Map(),\n subdirectories: new Map(),\n };\n\n let hasRoutes = false;\n let isValid = false;\n\n for (const filePath of contextModule.keys()) {\n if (ignoreList.some((regex) => regex.test(filePath))) {\n continue;\n }\n\n isValid = true;\n\n const meta = getFileMeta(filePath, options);\n\n // This is a file that should be ignored. e.g maybe it has an invalid platform?\n if (meta.specificity < 0) {\n continue;\n }\n\n let node: RouteNode = {\n type: meta.isApi ? 'api' : meta.isLayout ? 'layout' : 'route',\n loadRoute() {\n if (options.ignoreRequireErrors) {\n try {\n return contextModule(filePath);\n } catch {\n return {};\n }\n } else {\n return contextModule(filePath);\n }\n },\n contextKey: filePath,\n route: '', // This is overwritten during hoisting based upon the _layout\n dynamic: null,\n children: [], // While we are building the directory tree, we don't know the node's children just yet. This is added during hoisting\n };\n\n if (process.env.NODE_ENV === 'development') {\n // If the user has set the `EXPO_ROUTER_IMPORT_MODE` to `sync` then we should\n // filter the missing routes.\n if (node.type !== 'api' && importMode === 'sync') {\n if (!node.loadRoute()?.default) {\n continue;\n }\n }\n }\n\n /**\n * A single filepath may be extrapolated into multiple routes if it contains array syntax.\n * Another way to thinking about is that a filepath node is present in multiple leaves of the directory tree.\n */\n for (const route of extrapolateGroups(meta.route)) {\n // Traverse the directory tree to its leaf node, creating any missing directories along the way\n const subdirectoryParts = route.split('/').slice(0, -1);\n\n // Start at the root directory and traverse the path to the leaf directory\n let directory = rootDirectory;\n\n for (const part of subdirectoryParts) {\n let subDirectory = directory.subdirectories.get(part);\n\n // Create any missing subdirectories\n if (!subDirectory) {\n subDirectory = {\n files: new Map(),\n subdirectories: new Map(),\n };\n directory.subdirectories.set(part, subDirectory);\n }\n\n directory = subDirectory;\n }\n\n // Clone the node for this route\n node = { ...node, route };\n\n if (meta.isLayout) {\n directory.layout ??= [];\n const existing = directory.layout[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The layouts \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Please remove or rename one of these files.`\n );\n }\n } else {\n node = getLayoutNode(node, options);\n directory.layout[meta.specificity] = node;\n }\n } else if (meta.isApi) {\n const fileKey = `${route}+api`;\n let nodes = directory.files.get(fileKey);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(fileKey, nodes);\n }\n\n // API Routes have no specificity, they are always the first node\n const existing = nodes[0];\n\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The API route file \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Please remove or rename one of these files.`\n );\n }\n } else {\n nodes[0] = node;\n }\n } else {\n let nodes = directory.files.get(route);\n\n if (!nodes) {\n nodes = [];\n directory.files.set(route, nodes);\n }\n\n /**\n * If there is an existing node with the same specificity, then we have a conflict.\n * NOTE(Platform Routes):\n * We cannot check for specificity conflicts here, as we haven't processed all the context keys yet!\n * This will be checked during hoisting, as well as enforcing that all routes have a non-platform route.\n */\n const existing = nodes[meta.specificity];\n if (existing) {\n // In production, use the first route found\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n `The route files \"${filePath}\" and \"${existing.contextKey}\" conflict on the route \"/${route}\". Please remove or rename one of these files.`\n );\n }\n } else {\n hasRoutes ||= true;\n nodes[meta.specificity] = node;\n }\n }\n }\n }\n\n // If there are no routes/layouts then we should display the tutorial.\n if (!isValid) {\n return null;\n }\n\n /**\n * If there are no top-level _layout, add a default _layout\n * While this is a generated route, it will still be generated even if skipGenerated is true.\n */\n if (!rootDirectory.layout) {\n rootDirectory.layout = [\n {\n type: 'layout',\n loadRoute: () => ({\n default: (require('./views/Navigator') as typeof import('./views/Navigator'))\n .DefaultNavigator,\n }),\n // Generate a fake file name for the directory\n contextKey: 'expo-router/build/views/Navigator.js',\n route: '',\n generated: true,\n dynamic: null,\n children: [],\n },\n ];\n }\n\n // Only include the sitemap if there are routes.\n if (!options.skipGenerated) {\n if (hasRoutes) {\n appendSitemapRoute(rootDirectory);\n }\n appendNotFoundRoute(rootDirectory);\n }\n return rootDirectory;\n}\n\n/**\n * Flatten the directory tree into routes, hoisting routes to the nearest _layout.\n */\nfunction flattenDirectoryTreeToRoutes(\n directory: DirectoryNode,\n options: Options,\n /* The nearest _layout file in the directory tree */\n layout?: RouteNode,\n /* Route names are relative to their layout */\n pathToRemove = ''\n) {\n /**\n * This directory has a _layout file so it becomes the new target for hoisting routes.\n */\n if (directory.layout) {\n const previousLayout = layout;\n layout = getMostSpecific(directory.layout);\n\n // Add the new layout as a child of its parent\n if (previousLayout) {\n previousLayout.children.push(layout);\n }\n\n if (options.internal_stripLoadRoute) {\n delete (layout as any).loadRoute;\n }\n\n // `route` is the absolute pathname. We need to make this relative to the last _layout\n const newRoute = layout.route.replace(pathToRemove, '');\n pathToRemove = layout.route ? `${layout.route}/` : '';\n\n // Now update this layout with the new relative route and dynamic conventions\n layout.route = newRoute;\n layout.dynamic = generateDynamic(layout.route);\n }\n\n // This should never occur as there will always be a root layout, but it makes the type system happy\n if (!layout) throw new Error('Expo Router Internal Error: No nearest layout');\n\n for (const routes of directory.files.values()) {\n const routeNode = getMostSpecific(routes);\n\n // `route` is the absolute pathname. We need to make this relative to the nearest layout\n routeNode.route = routeNode.route.replace(pathToRemove, '');\n routeNode.dynamic = generateDynamic(routeNode.route);\n\n if (options.internal_stripLoadRoute) {\n delete (routeNode as any).loadRoute;\n }\n\n layout.children.push(routeNode);\n }\n\n // Recursively flatten the subdirectories\n for (const child of directory.subdirectories.values()) {\n flattenDirectoryTreeToRoutes(child, options, layout, pathToRemove);\n }\n\n return layout;\n}\n\nfunction getFileMeta(key: string, options: Options) {\n // Remove the leading `./`\n key = key.replace(/^\\.\\//, '');\n\n const parts = key.split('/');\n let route = removeSupportedExtensions(key);\n const filename = parts[parts.length - 1];\n const filenameWithoutExtensions = removeSupportedExtensions(filename);\n const isLayout = filenameWithoutExtensions === '_layout';\n const isApi = filename.match(/\\+api\\.(\\w+\\.)?[jt]sx?$/);\n\n if (filenameWithoutExtensions.startsWith('(') && filenameWithoutExtensions.endsWith(')')) {\n throw new Error(`Invalid route ./${key}. Routes cannot end with '(group)' syntax`);\n }\n\n // Nested routes cannot start with the '+' character, except for the '+not-found' route\n if (!isApi && filename.startsWith('+') && filenameWithoutExtensions !== '+not-found') {\n const renamedRoute = [...parts.slice(0, -1), filename.slice(1)].join('/');\n throw new Error(\n `Invalid route ./${key}. Route nodes cannot start with the '+' character. \"Please rename to ${renamedRoute}\"`\n );\n }\n let specificity = 0;\n\n const platformExtension = filenameWithoutExtensions.split('.')[1];\n const hasPlatformExtension = validPlatforms.has(platformExtension);\n const usePlatformRoutes = options.platformRoutes ?? true;\n\n if (hasPlatformExtension) {\n if (!usePlatformRoutes) {\n // If the user has disabled platform routes, then we should ignore this file\n specificity = -1;\n } else if (!options.platform) {\n // If we don't have a platform, then we should ignore this file\n // This used by typed routes, sitemap, etc\n specificity = -1;\n } else if (platformExtension === options.platform) {\n // If the platform extension is the same as the options.platform, then it is the most specific\n specificity = 2;\n } else if (platformExtension === 'native' && options.platform !== 'web') {\n // `native` is allow but isn't as specific as the platform\n specificity = 1;\n } else if (platformExtension !== options.platform) {\n // Somehow we have a platform extension that doesn't match the options.platform and it isn't native\n // This is an invalid file and we will ignore it\n specificity = -1;\n }\n\n if (isApi && specificity !== 0) {\n throw new Error(\n `Api routes cannot have platform extensions. Please remove '.${platformExtension}' from './${key}'`\n );\n }\n\n route = route.replace(new RegExp(`.${platformExtension}$`), '');\n }\n\n return {\n route,\n specificity,\n isLayout,\n isApi,\n };\n}\n\nexport function getIgnoreList(options?: Options) {\n const ignore: RegExp[] = [/^\\.\\/\\+html\\.[tj]sx?$/, ...(options?.ignore ?? [])];\n if (options?.preserveApiRoutes !== true) {\n ignore.push(/\\+api\\.[tj]sx?$/);\n }\n return ignore;\n}\n\n/**\n * Generates a set of strings which have the router array syntax extrapolated.\n *\n * /(a,b)/(c,d)/e.tsx => new Set(['a/c/e.tsx', 'a/d/e.tsx', 'b/c/e.tsx', 'b/d/e.tsx'])\n */\nexport function extrapolateGroups(key: string, keys: Set<string> = new Set()): Set<string> {\n const match = matchArrayGroupName(key);\n\n if (!match) {\n keys.add(key);\n return keys;\n }\n const groups = match.split(',');\n const groupsSet = new Set(groups);\n\n if (groupsSet.size !== groups.length) {\n throw new Error(`Array syntax cannot contain duplicate group name \"${groups}\" in \"${key}\".`);\n }\n\n if (groups.length === 1) {\n keys.add(key);\n return keys;\n }\n\n for (const group of groups) {\n extrapolateGroups(key.replace(match, group.trim()), keys);\n }\n\n return keys;\n}\n\nexport function generateDynamic(path: string): DynamicConvention[] | null {\n const dynamic = path\n .split('/')\n .map((part): DynamicConvention | null => {\n if (part === '+not-found') {\n return {\n name: '+not-found',\n deep: true,\n notFound: true,\n };\n }\n\n const deepDynamicName = matchDeepDynamicRouteName(part);\n const dynamicName = deepDynamicName ?? matchDynamicName(part);\n\n if (!dynamicName) return null;\n return { name: dynamicName, deep: !!deepDynamicName };\n })\n .filter((part): part is DynamicConvention => !!part);\n\n return dynamic.length === 0 ? null : dynamic;\n}\n\nfunction appendSitemapRoute(directory: DirectoryNode) {\n if (!directory.files.has('_sitemap')) {\n directory.files.set('_sitemap', [\n {\n loadRoute() {\n const { Sitemap, getNavOptions } = require('./views/Sitemap');\n return { default: Sitemap, getNavOptions };\n },\n route: '_sitemap',\n type: 'route',\n contextKey: 'expo-router/build/views/Sitemap.js',\n generated: true,\n internal: true,\n dynamic: null,\n children: [],\n },\n ]);\n }\n}\n\nfunction appendNotFoundRoute(directory: DirectoryNode) {\n if (!directory.files.has('+not-found')) {\n directory.files.set('+not-found', [\n {\n loadRoute() {\n return { default: require('./views/Unmatched').Unmatched };\n },\n type: 'route',\n route: '+not-found',\n contextKey: 'expo-router/build/views/Unmatched.js',\n generated: true,\n internal: true,\n dynamic: [{ name: '+not-found', deep: true, notFound: true }],\n children: [],\n },\n ]);\n }\n}\n\nfunction getLayoutNode(node: RouteNode, options: Options) {\n /**\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different initialRouteName based upon the first group name.\n *\n * So\n */\n\n // We may strip loadRoute during testing\n const groupName = matchGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let initialRouteName = childMatchingGroup?.route;\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n initialRouteName = loaded.unstable_settings.initialRouteName ?? initialRouteName;\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName = loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n initialRouteName = groupSpecificInitialRouteName ?? initialRouteName;\n }\n }\n\n return {\n ...node,\n route: node.route.replace(/\\/?_layout$/, ''),\n children: [], // Each layout should have its own children\n initialRouteName,\n };\n}\n\nfunction crawlAndAppendInitialRoutesAndEntryFiles(\n node: RouteNode,\n options: Options,\n entryPoints: string[] = []\n) {\n if (node.type === 'route') {\n node.entryPoints = [...new Set([...entryPoints, node.contextKey])];\n } else if (node.type === 'layout') {\n if (!node.children) {\n throw new Error(`Layout \"${node.contextKey}\" does not contain any child routes`);\n }\n\n // Every node below this layout will have it as an entryPoint\n entryPoints = [...entryPoints, node.contextKey];\n\n /**\n * Calculate the initialRouteNode\n *\n * A file called `(a,b)/(c)/_layout.tsx` will generate two _layout routes: `(a)/(c)/_layout` and `(b)/(c)/_layout`.\n * Each of these layouts will have a different initialRouteName based upon the first group.\n */\n const groupName = matchGroupName(node.route);\n const childMatchingGroup = node.children.find((child) => {\n return child.route.replace(/\\/index$/, '') === groupName;\n });\n let initialRouteName = childMatchingGroup?.route;\n // We may strip loadRoute during testing\n if (!options.internal_stripLoadRoute) {\n const loaded = node.loadRoute();\n if (loaded?.unstable_settings) {\n // Allow unstable_settings={ initialRouteName: '...' } to override the default initial route name.\n initialRouteName = loaded.unstable_settings.initialRouteName ?? initialRouteName;\n\n if (groupName) {\n // Allow unstable_settings={ 'custom': { initialRouteName: '...' } } to override the less specific initial route name.\n const groupSpecificInitialRouteName =\n loaded.unstable_settings?.[groupName]?.initialRouteName;\n\n initialRouteName = groupSpecificInitialRouteName ?? initialRouteName;\n }\n }\n }\n\n if (initialRouteName) {\n const initialRoute = node.children.find((child) => child.route === initialRouteName);\n if (!initialRoute) {\n const validInitialRoutes = node.children\n .filter((child) => !child.generated)\n .map((child) => `'${child.route}'`)\n .join(', ');\n\n if (groupName) {\n throw new Error(\n `Layout ${node.contextKey} has invalid initialRouteName '${initialRouteName}' for group '(${groupName})'. Valid options are: ${validInitialRoutes}`\n );\n } else {\n throw new Error(\n `Layout ${node.contextKey} has invalid initialRouteName '${initialRouteName}'. Valid options are: ${validInitialRoutes}`\n );\n }\n }\n\n // Navigators can add initialsRoutes into the history, so they need to be to be included in the entryPoints\n node.initialRouteName = initialRouteName;\n entryPoints.push(initialRoute.contextKey);\n }\n\n for (const child of node.children) {\n crawlAndAppendInitialRoutesAndEntryFiles(child, options, entryPoints);\n }\n }\n}\n\nfunction getMostSpecific(routes: RouteNode[]) {\n const route = routes[routes.length - 1];\n\n if (!routes[0]) {\n throw new Error(\n `The file ${route.contextKey} does not have a fallback sibling file without a platform extension.`\n );\n }\n\n // This works even tho routes is holey array (e.g it might have index 0 and 2 but not 1)\n // `.length` includes the holes in its count\n return routes[routes.length - 1];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"router-store.d.ts","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EAGlC,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAiC,aAAa,EAAY,MAAM,OAAO,CAAC;AAe/E,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG1C;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAS,EAAG,SAAS,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,aAAa,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,wBAAwB,CAAkB;IAElD,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAEpC,aAAa,EAAG,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACjF,yBAAyB,EAAG,MAAM,IAAI,CAAC;IAEvC,oBAAoB,YAAiB,IAAI,EAAI;IAC7C,gBAAgB,YAAiB,IAAI,EAAI;IAEzC,MAAM,MAAqB;IAC3B,eAAe,MAA8B;IAC7C,MAAM,MAAqB;IAC3B,SAAS,MAAwB;IACjC,IAAI,MAAmB;IACvB,OAAO,MAAsB;IAC7B,OAAO,MAAsB;IAC7B,UAAU,MAAyB;IACnC,UAAU,MAAyB;IACnC,SAAS,MAAwB;IACjC,QAAQ,MAAuB;IAE/B,UAAU,CACR,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,EAC/E,eAAe,CAAC,EAAE,GAAG;IAgGvB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,cAAQ;IAWjD,YAAY,CAAC,KAAK,EAAE,WAAW;IAgB/B,kBAAkB;IAIlB,uEAAuE;IACvE,oBAAoB,eAAgB,MAAM,IAAI,mBAG5C;IACF,gBAAgB,eAAgB,MAAM,IAAI,mBAGxC;IACF,QAAQ,aAEN;IACF,iBAAiB,oBAEf;IACF,iBAAiB,kBAEf;IAEF,OAAO;CAKR;AAED,eAAO,MAAM,KAAK,aAAoB,CAAC;AAEvC,wBAAgB,aAAa,gBAE5B;AAYD,wBAAgB,iBAAiB,gBAOhC;AAED,wBAAgB,iBAAiB,cAOhC;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,GAAG,SAAS,eAQhG"}
1
+ {"version":3,"file":"router-store.d.ts","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EAGlC,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAiC,aAAa,EAAY,MAAM,OAAO,CAAC;AAgB/E,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAG1C;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAS,EAAG,SAAS,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,aAAa,CAAC;IAC9B,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,OAAO,CAAC,wBAAwB,CAAkB;IAElD,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAEpC,aAAa,EAAG,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACjF,yBAAyB,EAAG,MAAM,IAAI,CAAC;IAEvC,oBAAoB,YAAiB,IAAI,EAAI;IAC7C,gBAAgB,YAAiB,IAAI,EAAI;IAEzC,MAAM,MAAqB;IAC3B,eAAe,MAA8B;IAC7C,MAAM,MAAqB;IAC3B,SAAS,MAAwB;IACjC,IAAI,MAAmB;IACvB,OAAO,MAAsB;IAC7B,OAAO,MAAsB;IAC7B,UAAU,MAAyB;IACnC,UAAU,MAAyB;IACnC,SAAS,MAAwB;IACjC,QAAQ,MAAuB;IAE/B,UAAU,CACR,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,EAC/E,eAAe,CAAC,EAAE,GAAG;IAoGvB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,cAAQ;IAWjD,YAAY,CAAC,KAAK,EAAE,WAAW;IAgB/B,kBAAkB;IAIlB,uEAAuE;IACvE,oBAAoB,eAAgB,MAAM,IAAI,mBAG5C;IACF,gBAAgB,eAAgB,MAAM,IAAI,mBAGxC;IACF,QAAQ,aAEN;IACF,iBAAiB,oBAEf;IACF,iBAAiB,kBAEf;IAEF,OAAO;CAKR;AAED,eAAO,MAAM,KAAK,aAAoB,CAAC;AAEvC,wBAAgB,aAAa,gBAE5B;AAYD,wBAAgB,iBAAiB,gBAOhC;AAED,wBAAgB,iBAAiB,cAOhC;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,GAAG,SAAS,eAQhG"}
@@ -22,11 +22,16 @@ var __importStar = (this && this.__importStar) || function (mod) {
22
22
  __setModuleDefault(result, mod);
23
23
  return result;
24
24
  };
25
+ var __importDefault = (this && this.__importDefault) || function (mod) {
26
+ return (mod && mod.__esModule) ? mod : { "default": mod };
27
+ };
25
28
  Object.defineProperty(exports, "__esModule", { value: true });
26
29
  exports.useInitializeExpoRouter = exports.useStoreRouteInfo = exports.useStoreRootState = exports.useExpoRouter = exports.store = exports.RouterStore = void 0;
27
30
  const native_1 = require("@react-navigation/native");
31
+ const expo_constants_1 = __importDefault(require("expo-constants"));
28
32
  const SplashScreen = __importStar(require("expo-splash-screen"));
29
33
  const react_1 = require("react");
34
+ const react_native_1 = require("react-native");
30
35
  const routing_1 = require("./routing");
31
36
  const sort_routes_1 = require("./sort-routes");
32
37
  const LocationProvider_1 = require("../LocationProvider");
@@ -74,7 +79,11 @@ class RouterStore {
74
79
  this.navigationRefSubscription?.();
75
80
  this.rootStateSubscribers.clear();
76
81
  this.storeSubscribers.clear();
77
- this.routeNode = (0, getRoutes_1.getRoutes)(context, { ignoreEntryPoints: true });
82
+ this.routeNode = (0, getRoutes_1.getRoutes)(context, {
83
+ ...expo_constants_1.default.expoConfig?.extra?.router,
84
+ ignoreEntryPoints: true,
85
+ platform: react_native_1.Platform.OS,
86
+ });
78
87
  this.rootComponent = this.routeNode ? (0, useScreens_1.getQualifiedRouteComponent)(this.routeNode) : react_1.Fragment;
79
88
  // Only error in production, in development we will show the onboarding screen
80
89
  if (!this.routeNode && process.env.NODE_ENV === 'production') {
@@ -1 +1 @@
1
- {"version":3,"file":"router-store.js","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n NavigationContainerRefWithCurrent,\n getPathFromState,\n useNavigationContainerRef,\n} from '@react-navigation/native';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { useSyncExternalStore, useMemo, ComponentType, Fragment } from 'react';\n\nimport {\n canGoBack,\n canDismiss,\n goBack,\n linkTo,\n navigate,\n dismiss,\n dismissAll,\n push,\n replace,\n setParams,\n} from './routing';\nimport { getSortedRoutes } from './sort-routes';\nimport { UrlObject, getRouteInfoFromState } from '../LocationProvider';\nimport { RouteNode } from '../Route';\nimport { deepEqual, getPathDataFromState } from '../fork/getPathFromState';\nimport { ResultState } from '../fork/getStateFromPath';\nimport { ExpoLinkingOptions, getLinkingConfig } from '../getLinkingConfig';\nimport { getRoutes } from '../getRoutes';\nimport { RequireContext } from '../types';\nimport { getQualifiedRouteComponent } from '../useScreens';\n\n/**\n * This is the global state for the router. It is used to keep track of the current route, and to provide a way to navigate to other routes.\n *\n * There should only be one instance of this class and be initialized via `useInitializeExpoRouter`\n */\nexport class RouterStore {\n routeNode!: RouteNode | null;\n rootComponent!: ComponentType;\n linking?: ExpoLinkingOptions;\n private hasAttemptedToHideSplash: boolean = false;\n\n initialState?: ResultState;\n rootState?: ResultState;\n nextState?: ResultState;\n routeInfo?: UrlObject;\n splashScreenAnimationFrame?: number;\n\n navigationRef!: NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>;\n navigationRefSubscription!: () => void;\n\n rootStateSubscribers = new Set<() => void>();\n storeSubscribers = new Set<() => void>();\n\n linkTo = linkTo.bind(this);\n getSortedRoutes = getSortedRoutes.bind(this);\n goBack = goBack.bind(this);\n canGoBack = canGoBack.bind(this);\n push = push.bind(this);\n dismiss = dismiss.bind(this);\n replace = replace.bind(this);\n dismissAll = dismissAll.bind(this);\n canDismiss = canDismiss.bind(this);\n setParams = setParams.bind(this);\n navigate = navigate.bind(this);\n\n initialize(\n context: RequireContext,\n navigationRef: NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>,\n initialLocation?: URL\n ) {\n // Clean up any previous state\n this.initialState = undefined;\n this.rootState = undefined;\n this.nextState = undefined;\n this.routeInfo = undefined;\n this.linking = undefined;\n this.navigationRefSubscription?.();\n this.rootStateSubscribers.clear();\n this.storeSubscribers.clear();\n\n this.routeNode = getRoutes(context, { ignoreEntryPoints: true });\n\n this.rootComponent = this.routeNode ? getQualifiedRouteComponent(this.routeNode) : Fragment;\n\n // Only error in production, in development we will show the onboarding screen\n if (!this.routeNode && process.env.NODE_ENV === 'production') {\n throw new Error('No routes found');\n }\n\n this.navigationRef = navigationRef;\n\n if (this.routeNode) {\n this.linking = getLinkingConfig(this.routeNode!);\n\n if (initialLocation) {\n this.linking.getInitialURL = () => initialLocation.toString();\n this.initialState = this.linking.getStateFromPath?.(\n initialLocation.pathname + initialLocation.search,\n this.linking.config\n );\n }\n }\n\n // There is no routeNode, so we will be showing the onboarding screen\n // In the meantime, just mock the routeInfo\n if (this.initialState) {\n this.rootState = this.initialState;\n this.routeInfo = this.getRouteInfo(this.initialState);\n } else {\n this.routeInfo = {\n unstable_globalHref: '',\n pathname: '',\n isIndex: false,\n params: {},\n segments: [],\n };\n }\n\n /**\n * Counter intuitively - this fires AFTER both React Navigation's state changes and the subsequent paint.\n * This poses a couple of issues for Expo Router,\n * - Ensuring hooks (e.g. useSearchParams()) have data in the initial render\n * - Reacting to state changes after a navigation event\n *\n * This is why the initial render renders a Fragment and we wait until `onReady()` is called\n * Additionally, some hooks compare the state from both the store and the navigationRef. If the store it stale,\n * that hooks will manually update the store.\n *\n */\n this.navigationRefSubscription = navigationRef.addListener('state', (data) => {\n const state = data.data.state as ResultState;\n\n if (!this.hasAttemptedToHideSplash) {\n this.hasAttemptedToHideSplash = true;\n // NOTE(EvanBacon): `navigationRef.isReady` is sometimes not true when state is called initially.\n this.splashScreenAnimationFrame = requestAnimationFrame(() => {\n // @ts-expect-error: This function is native-only and for internal-use only.\n SplashScreen._internal_maybeHideAsync?.();\n });\n }\n\n let shouldUpdateSubscribers = this.nextState === state;\n this.nextState = undefined;\n\n // This can sometimes be undefined when an error is thrown in the Root Layout Route.\n // Additionally that state may already equal the rootState if it was updated within a hook\n if (state && state !== this.rootState) {\n store.updateState(state, undefined);\n shouldUpdateSubscribers = true;\n }\n\n // If the state has changed, or was changed inside a hook we need to update the subscribers\n if (shouldUpdateSubscribers) {\n for (const subscriber of this.rootStateSubscribers) {\n subscriber();\n }\n }\n });\n\n for (const subscriber of this.storeSubscribers) {\n subscriber();\n }\n }\n\n updateState(state: ResultState, nextState = state) {\n store.rootState = state;\n store.nextState = nextState;\n\n const nextRouteInfo = store.getRouteInfo(state);\n\n if (!deepEqual(this.routeInfo, nextRouteInfo)) {\n store.routeInfo = nextRouteInfo;\n }\n }\n\n getRouteInfo(state: ResultState) {\n return getRouteInfoFromState(\n (state: Parameters<typeof getPathFromState>[0], asPath: boolean) => {\n return getPathDataFromState(state, {\n screens: [],\n ...this.linking?.config,\n preserveDynamicRoutes: asPath,\n preserveGroups: asPath,\n });\n },\n state\n );\n }\n\n // This is only used in development, to show the onboarding screen\n // In production we should have errored during the initialization\n shouldShowTutorial() {\n return !this.routeNode && process.env.NODE_ENV === 'development';\n }\n\n /** Make sure these are arrow functions so `this` is correctly bound */\n subscribeToRootState = (subscriber: () => void) => {\n this.rootStateSubscribers.add(subscriber);\n return () => this.rootStateSubscribers.delete(subscriber);\n };\n subscribeToStore = (subscriber: () => void) => {\n this.storeSubscribers.add(subscriber);\n return () => this.storeSubscribers.delete(subscriber);\n };\n snapshot = () => {\n return this;\n };\n rootStateSnapshot = () => {\n return this.rootState!;\n };\n routeInfoSnapshot = () => {\n return this.routeInfo!;\n };\n\n cleanup() {\n if (this.splashScreenAnimationFrame) {\n cancelAnimationFrame(this.splashScreenAnimationFrame);\n }\n }\n}\n\nexport const store = new RouterStore();\n\nexport function useExpoRouter() {\n return useSyncExternalStore(store.subscribeToStore, store.snapshot, store.snapshot);\n}\n\nfunction syncStoreRootState() {\n if (store.navigationRef.isReady()) {\n const currentState = store.navigationRef.getRootState() as unknown as ResultState;\n\n if (store.rootState !== currentState) {\n store.updateState(currentState);\n }\n }\n}\n\nexport function useStoreRootState() {\n syncStoreRootState();\n return useSyncExternalStore(\n store.subscribeToRootState,\n store.rootStateSnapshot,\n store.rootStateSnapshot\n );\n}\n\nexport function useStoreRouteInfo() {\n syncStoreRootState();\n return useSyncExternalStore(\n store.subscribeToRootState,\n store.routeInfoSnapshot,\n store.routeInfoSnapshot\n );\n}\n\nexport function useInitializeExpoRouter(context: RequireContext, initialLocation: URL | undefined) {\n const navigationRef = useNavigationContainerRef();\n useMemo(\n () => store.initialize(context, navigationRef, initialLocation),\n [context, initialLocation]\n );\n useExpoRouter();\n return store;\n}\n"]}
1
+ {"version":3,"file":"router-store.js","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n NavigationContainerRefWithCurrent,\n getPathFromState,\n useNavigationContainerRef,\n} from '@react-navigation/native';\nimport Constants from 'expo-constants';\nimport * as SplashScreen from 'expo-splash-screen';\nimport { useSyncExternalStore, useMemo, ComponentType, Fragment } from 'react';\nimport { Platform } from 'react-native';\n\nimport {\n canGoBack,\n canDismiss,\n goBack,\n linkTo,\n navigate,\n dismiss,\n dismissAll,\n push,\n replace,\n setParams,\n} from './routing';\nimport { getSortedRoutes } from './sort-routes';\nimport { UrlObject, getRouteInfoFromState } from '../LocationProvider';\nimport { RouteNode } from '../Route';\nimport { deepEqual, getPathDataFromState } from '../fork/getPathFromState';\nimport { ResultState } from '../fork/getStateFromPath';\nimport { ExpoLinkingOptions, getLinkingConfig } from '../getLinkingConfig';\nimport { getRoutes } from '../getRoutes';\nimport { RequireContext } from '../types';\nimport { getQualifiedRouteComponent } from '../useScreens';\n\n/**\n * This is the global state for the router. It is used to keep track of the current route, and to provide a way to navigate to other routes.\n *\n * There should only be one instance of this class and be initialized via `useInitializeExpoRouter`\n */\nexport class RouterStore {\n routeNode!: RouteNode | null;\n rootComponent!: ComponentType;\n linking?: ExpoLinkingOptions;\n private hasAttemptedToHideSplash: boolean = false;\n\n initialState?: ResultState;\n rootState?: ResultState;\n nextState?: ResultState;\n routeInfo?: UrlObject;\n splashScreenAnimationFrame?: number;\n\n navigationRef!: NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>;\n navigationRefSubscription!: () => void;\n\n rootStateSubscribers = new Set<() => void>();\n storeSubscribers = new Set<() => void>();\n\n linkTo = linkTo.bind(this);\n getSortedRoutes = getSortedRoutes.bind(this);\n goBack = goBack.bind(this);\n canGoBack = canGoBack.bind(this);\n push = push.bind(this);\n dismiss = dismiss.bind(this);\n replace = replace.bind(this);\n dismissAll = dismissAll.bind(this);\n canDismiss = canDismiss.bind(this);\n setParams = setParams.bind(this);\n navigate = navigate.bind(this);\n\n initialize(\n context: RequireContext,\n navigationRef: NavigationContainerRefWithCurrent<ReactNavigation.RootParamList>,\n initialLocation?: URL\n ) {\n // Clean up any previous state\n this.initialState = undefined;\n this.rootState = undefined;\n this.nextState = undefined;\n this.routeInfo = undefined;\n this.linking = undefined;\n this.navigationRefSubscription?.();\n this.rootStateSubscribers.clear();\n this.storeSubscribers.clear();\n\n this.routeNode = getRoutes(context, {\n ...Constants.expoConfig?.extra?.router,\n ignoreEntryPoints: true,\n platform: Platform.OS,\n });\n\n this.rootComponent = this.routeNode ? getQualifiedRouteComponent(this.routeNode) : Fragment;\n\n // Only error in production, in development we will show the onboarding screen\n if (!this.routeNode && process.env.NODE_ENV === 'production') {\n throw new Error('No routes found');\n }\n\n this.navigationRef = navigationRef;\n\n if (this.routeNode) {\n this.linking = getLinkingConfig(this.routeNode!);\n\n if (initialLocation) {\n this.linking.getInitialURL = () => initialLocation.toString();\n this.initialState = this.linking.getStateFromPath?.(\n initialLocation.pathname + initialLocation.search,\n this.linking.config\n );\n }\n }\n\n // There is no routeNode, so we will be showing the onboarding screen\n // In the meantime, just mock the routeInfo\n if (this.initialState) {\n this.rootState = this.initialState;\n this.routeInfo = this.getRouteInfo(this.initialState);\n } else {\n this.routeInfo = {\n unstable_globalHref: '',\n pathname: '',\n isIndex: false,\n params: {},\n segments: [],\n };\n }\n\n /**\n * Counter intuitively - this fires AFTER both React Navigation's state changes and the subsequent paint.\n * This poses a couple of issues for Expo Router,\n * - Ensuring hooks (e.g. useSearchParams()) have data in the initial render\n * - Reacting to state changes after a navigation event\n *\n * This is why the initial render renders a Fragment and we wait until `onReady()` is called\n * Additionally, some hooks compare the state from both the store and the navigationRef. If the store it stale,\n * that hooks will manually update the store.\n *\n */\n this.navigationRefSubscription = navigationRef.addListener('state', (data) => {\n const state = data.data.state as ResultState;\n\n if (!this.hasAttemptedToHideSplash) {\n this.hasAttemptedToHideSplash = true;\n // NOTE(EvanBacon): `navigationRef.isReady` is sometimes not true when state is called initially.\n this.splashScreenAnimationFrame = requestAnimationFrame(() => {\n // @ts-expect-error: This function is native-only and for internal-use only.\n SplashScreen._internal_maybeHideAsync?.();\n });\n }\n\n let shouldUpdateSubscribers = this.nextState === state;\n this.nextState = undefined;\n\n // This can sometimes be undefined when an error is thrown in the Root Layout Route.\n // Additionally that state may already equal the rootState if it was updated within a hook\n if (state && state !== this.rootState) {\n store.updateState(state, undefined);\n shouldUpdateSubscribers = true;\n }\n\n // If the state has changed, or was changed inside a hook we need to update the subscribers\n if (shouldUpdateSubscribers) {\n for (const subscriber of this.rootStateSubscribers) {\n subscriber();\n }\n }\n });\n\n for (const subscriber of this.storeSubscribers) {\n subscriber();\n }\n }\n\n updateState(state: ResultState, nextState = state) {\n store.rootState = state;\n store.nextState = nextState;\n\n const nextRouteInfo = store.getRouteInfo(state);\n\n if (!deepEqual(this.routeInfo, nextRouteInfo)) {\n store.routeInfo = nextRouteInfo;\n }\n }\n\n getRouteInfo(state: ResultState) {\n return getRouteInfoFromState(\n (state: Parameters<typeof getPathFromState>[0], asPath: boolean) => {\n return getPathDataFromState(state, {\n screens: [],\n ...this.linking?.config,\n preserveDynamicRoutes: asPath,\n preserveGroups: asPath,\n });\n },\n state\n );\n }\n\n // This is only used in development, to show the onboarding screen\n // In production we should have errored during the initialization\n shouldShowTutorial() {\n return !this.routeNode && process.env.NODE_ENV === 'development';\n }\n\n /** Make sure these are arrow functions so `this` is correctly bound */\n subscribeToRootState = (subscriber: () => void) => {\n this.rootStateSubscribers.add(subscriber);\n return () => this.rootStateSubscribers.delete(subscriber);\n };\n subscribeToStore = (subscriber: () => void) => {\n this.storeSubscribers.add(subscriber);\n return () => this.storeSubscribers.delete(subscriber);\n };\n snapshot = () => {\n return this;\n };\n rootStateSnapshot = () => {\n return this.rootState!;\n };\n routeInfoSnapshot = () => {\n return this.routeInfo!;\n };\n\n cleanup() {\n if (this.splashScreenAnimationFrame) {\n cancelAnimationFrame(this.splashScreenAnimationFrame);\n }\n }\n}\n\nexport const store = new RouterStore();\n\nexport function useExpoRouter() {\n return useSyncExternalStore(store.subscribeToStore, store.snapshot, store.snapshot);\n}\n\nfunction syncStoreRootState() {\n if (store.navigationRef.isReady()) {\n const currentState = store.navigationRef.getRootState() as unknown as ResultState;\n\n if (store.rootState !== currentState) {\n store.updateState(currentState);\n }\n }\n}\n\nexport function useStoreRootState() {\n syncStoreRootState();\n return useSyncExternalStore(\n store.subscribeToRootState,\n store.rootStateSnapshot,\n store.rootStateSnapshot\n );\n}\n\nexport function useStoreRouteInfo() {\n syncStoreRootState();\n return useSyncExternalStore(\n store.subscribeToRootState,\n store.routeInfoSnapshot,\n store.routeInfoSnapshot\n );\n}\n\nexport function useInitializeExpoRouter(context: RequireContext, initialLocation: URL | undefined) {\n const navigationRef = useNavigationContainerRef();\n useMemo(\n () => store.initialize(context, navigationRef, initialLocation),\n [context, initialLocation]\n );\n useExpoRouter();\n return store;\n}\n"]}
@@ -160,7 +160,6 @@ function getNavigateAction(actionState, navigationState, type = 'NAVIGATE') {
160
160
  * - /1/page -> /2/anotherPage needs to target the /[id] navigator
161
161
  *
162
162
  * Other parameters such as search params and hash are not evaluated.
163
- *
164
163
  */
165
164
  let actionStateRoute;
166
165
  // Traverse the state tree comparing the current state and the action state until we find where they diverge
@@ -189,12 +188,18 @@ function getNavigateAction(actionState, navigationState, type = 'NAVIGATE') {
189
188
  let params = payload.params;
190
189
  // The root level of payload is a bit weird, its params are in the child object
191
190
  while (actionStateRoute) {
192
- Object.assign(params, { ...actionStateRoute.params });
191
+ Object.assign(params, { ...payload.params, ...actionStateRoute.params });
192
+ // Assign the screen name to the payload
193
193
  payload.screen = actionStateRoute.name;
194
- actionStateRoute = actionStateRoute.state?.routes[actionStateRoute.state?.routes.length - 1];
195
- payload.params ??= {};
194
+ // Merge the params, ensuring that we create a new object
195
+ payload.params = { ...params };
196
+ // Params don't include the screen, thats a separate attribute
197
+ delete payload.params['screen'];
198
+ // Continue down the payload tree
199
+ // Initially these values are separate, but React Nav merges them after the first layer
196
200
  payload = payload.params;
197
201
  params = payload;
202
+ actionStateRoute = actionStateRoute.state?.routes[actionStateRoute.state?.routes.length - 1];
198
203
  }
199
204
  // Expo Router uses only three actions, but these don't directly translate to all navigator actions
200
205
  if (type === 'PUSH') {
@@ -1 +1 @@
1
- {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/global-state/routing.ts"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, type NavigationState, PartialRoute } from '@react-navigation/native';\nimport * as Linking from 'expo-linking';\nimport { nanoid } from 'nanoid/non-secure';\n\nimport { type RouterStore } from './router-store';\nimport { ExpoRouter } from '../../types/expo-router';\nimport { ResultState } from '../fork/getStateFromPath';\nimport { resolveHref } from '../link/href';\nimport { resolve } from '../link/path';\nimport { matchDynamicName } from '../matchers';\nimport { shouldLinkExternally } from '../utils/url';\n\nfunction assertIsReady(store: RouterStore) {\n if (!store.navigationRef.isReady()) {\n throw new Error(\n 'Attempted to navigate before mounting the Root Layout component. Ensure the Root Layout component is rendering a Slot, or other navigator on the first render.'\n );\n }\n}\n\nexport function navigate(this: RouterStore, url: ExpoRouter.Href) {\n return this.linkTo(resolveHref(url), 'NAVIGATE');\n}\n\nexport function push(this: RouterStore, url: ExpoRouter.Href) {\n return this.linkTo(resolveHref(url), 'PUSH');\n}\n\nexport function dismiss(this: RouterStore, count?: number) {\n this.navigationRef?.dispatch(StackActions.pop(count));\n}\n\nexport function replace(this: RouterStore, url: ExpoRouter.Href) {\n return this.linkTo(resolveHref(url), 'REPLACE');\n}\n\nexport function dismissAll(this: RouterStore) {\n this.navigationRef?.dispatch(StackActions.popToTop());\n}\n\nexport function goBack(this: RouterStore) {\n assertIsReady(this);\n this.navigationRef?.current?.goBack();\n}\n\nexport function canGoBack(this: RouterStore): boolean {\n // Return a default value here if the navigation hasn't mounted yet.\n // This can happen if the user calls `canGoBack` from the Root Layout route\n // before mounting a navigator. This behavior exists due to React Navigation being dynamically\n // constructed at runtime. We can get rid of this in the future if we use\n // the static configuration internally.\n if (!this.navigationRef.isReady()) {\n return false;\n }\n return this.navigationRef?.current?.canGoBack() ?? false;\n}\n\nexport function canDismiss(this: RouterStore): boolean {\n let state = this.rootState;\n\n // Keep traversing down the state tree until we find a stack navigator that we can pop\n while (state) {\n if (state.type === 'stack' && state.routes.length > 1) {\n return true;\n }\n if (state.index === undefined) return false;\n\n state = state.routes?.[state.index]?.state as any;\n }\n\n return false;\n}\n\nexport function setParams(this: RouterStore, params: Record<string, string | number> = {}) {\n assertIsReady(this);\n return (this.navigationRef?.current?.setParams as any)(params);\n}\n\nexport function linkTo(this: RouterStore, href: string, event?: string) {\n if (shouldLinkExternally(href)) {\n Linking.openURL(href);\n return;\n }\n\n assertIsReady(this);\n const navigationRef = this.navigationRef.current;\n\n if (navigationRef == null) {\n throw new Error(\n \"Couldn't find a navigation object. Is your component inside NavigationContainer?\"\n );\n }\n\n if (!this.linking) {\n throw new Error('Attempted to link to route when no routes are present');\n }\n\n if (href === '..' || href === '../') {\n navigationRef.goBack();\n return;\n }\n\n const rootState = navigationRef.getRootState();\n\n if (href.startsWith('.')) {\n // Resolve base path by merging the current segments with the params\n let base =\n this.routeInfo?.segments\n ?.map((segment) => {\n if (!segment.startsWith('[')) return segment;\n\n if (segment.startsWith('[...')) {\n segment = segment.slice(4, -1);\n const params = this.routeInfo?.params?.[segment];\n if (Array.isArray(params)) {\n return params.join('/');\n } else {\n return params?.split(',')?.join('/') ?? '';\n }\n } else {\n segment = segment.slice(1, -1);\n return this.routeInfo?.params?.[segment];\n }\n })\n .filter(Boolean)\n .join('/') ?? '/';\n\n if (!this.routeInfo?.isIndex) {\n base += '/..';\n }\n\n href = resolve(base, href);\n }\n\n const state = this.linking.getStateFromPath!(href, this.linking.config);\n\n if (!state || state.routes.length === 0) {\n console.error('Could not generate a valid navigation state for the given path: ' + href);\n return;\n }\n\n return navigationRef.dispatch(getNavigateAction(state, rootState, event));\n}\n\nfunction getNavigateAction(\n actionState: ResultState,\n navigationState: NavigationState,\n type = 'NAVIGATE'\n) {\n /**\n * We need to find the deepest navigator where the action and current state diverge, If they do not diverge, the\n * lowest navigator is the target.\n *\n * By default React Navigation will target the current navigator, but this doesn't work for all actions\n * For example:\n * - /deeply/nested/route -> /top-level-route the target needs to be the top-level navigator\n * - /stack/nestedStack/page -> /stack1/nestedStack/other-page needs to target the nestedStack navigator\n *\n * This matching needs to done by comparing the route names and the dynamic path, for example\n * - /1/page -> /2/anotherPage needs to target the /[id] navigator\n *\n * Other parameters such as search params and hash are not evaluated.\n *\n */\n let actionStateRoute: PartialRoute<any> | undefined;\n\n // Traverse the state tree comparing the current state and the action state until we find where they diverge\n while (actionState && navigationState) {\n const stateRoute = navigationState.routes[navigationState.index];\n\n actionStateRoute = actionState.routes[actionState.routes.length - 1];\n\n const childState = actionStateRoute.state;\n const nextNavigationState = stateRoute.state;\n\n const dynamicName = matchDynamicName(actionStateRoute.name);\n\n const didActionAndCurrentStateDiverge =\n actionStateRoute.name !== stateRoute.name ||\n !childState ||\n !nextNavigationState ||\n (dynamicName && actionStateRoute.params?.[dynamicName] !== stateRoute.params?.[dynamicName]);\n\n if (didActionAndCurrentStateDiverge) {\n break;\n }\n\n actionState = childState;\n navigationState = nextNavigationState as NavigationState;\n }\n\n /*\n * We found the target navigator, but the payload is in the incorrect format\n * We need to convert the action state to a payload that can be dispatched\n */\n const rootPayload: Record<string, any> = { params: {} };\n let payload = rootPayload;\n let params = payload.params;\n\n // The root level of payload is a bit weird, its params are in the child object\n while (actionStateRoute) {\n Object.assign(params, { ...actionStateRoute.params });\n payload.screen = actionStateRoute.name;\n\n actionStateRoute = actionStateRoute.state?.routes[actionStateRoute.state?.routes.length - 1];\n\n payload.params ??= {};\n payload = payload.params;\n params = payload;\n }\n\n // Expo Router uses only three actions, but these don't directly translate to all navigator actions\n if (type === 'PUSH') {\n // Only stack navigators have a push action, and even then we want to use NAVIGATE (see below)\n type = 'NAVIGATE';\n\n /*\n * The StackAction.PUSH does not work correctly with Expo Router.\n *\n * Expo Router provides a getId() function for every route, altering how React Navigation handles stack routing.\n * Ordinarily, PUSH always adds a new screen to the stack. However, with getId() present, it navigates to the screen with the matching ID instead (by moving the screen to the top of the stack)\n * When you try and push to a screen with the same ID, no navigation will occur\n * Refer to: https://github.com/react-navigation/react-navigation/blob/13d4aa270b301faf07960b4cd861ffc91e9b2c46/packages/routers/src/StackRouter.tsx#L279-L290\n *\n * Expo Router needs to retain the default behavior of PUSH, consistently adding new screens to the stack, even if their IDs are identical.\n *\n * To resolve this issue, we switch to using a NAVIGATE action with a new key. In the navigate action, screens are matched by either key or getId() function.\n * By generating a unique new key, we ensure that the screen is always pushed onto the stack.\n *\n */\n if (navigationState.type === 'stack') {\n rootPayload.key = `${rootPayload.name}-${nanoid()}`; // @see https://github.com/react-navigation/react-navigation/blob/13d4aa270b301faf07960b4cd861ffc91e9b2c46/packages/routers/src/StackRouter.tsx#L406-L407\n }\n }\n\n if (type === 'REPLACE' && navigationState.type === 'tab') {\n type = 'JUMP_TO';\n }\n\n return {\n type,\n target: navigationState.key,\n payload: {\n key: rootPayload.key,\n name: rootPayload.screen,\n params: rootPayload.params,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"routing.js","sourceRoot":"","sources":["../../src/global-state/routing.ts"],"names":[],"mappings":"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","sourcesContent":["import { StackActions, type NavigationState, PartialRoute } from '@react-navigation/native';\nimport * as Linking from 'expo-linking';\nimport { nanoid } from 'nanoid/non-secure';\n\nimport { type RouterStore } from './router-store';\nimport { ExpoRouter } from '../../types/expo-router';\nimport { ResultState } from '../fork/getStateFromPath';\nimport { resolveHref } from '../link/href';\nimport { resolve } from '../link/path';\nimport { matchDynamicName } from '../matchers';\nimport { shouldLinkExternally } from '../utils/url';\n\nfunction assertIsReady(store: RouterStore) {\n if (!store.navigationRef.isReady()) {\n throw new Error(\n 'Attempted to navigate before mounting the Root Layout component. Ensure the Root Layout component is rendering a Slot, or other navigator on the first render.'\n );\n }\n}\n\nexport function navigate(this: RouterStore, url: ExpoRouter.Href) {\n return this.linkTo(resolveHref(url), 'NAVIGATE');\n}\n\nexport function push(this: RouterStore, url: ExpoRouter.Href) {\n return this.linkTo(resolveHref(url), 'PUSH');\n}\n\nexport function dismiss(this: RouterStore, count?: number) {\n this.navigationRef?.dispatch(StackActions.pop(count));\n}\n\nexport function replace(this: RouterStore, url: ExpoRouter.Href) {\n return this.linkTo(resolveHref(url), 'REPLACE');\n}\n\nexport function dismissAll(this: RouterStore) {\n this.navigationRef?.dispatch(StackActions.popToTop());\n}\n\nexport function goBack(this: RouterStore) {\n assertIsReady(this);\n this.navigationRef?.current?.goBack();\n}\n\nexport function canGoBack(this: RouterStore): boolean {\n // Return a default value here if the navigation hasn't mounted yet.\n // This can happen if the user calls `canGoBack` from the Root Layout route\n // before mounting a navigator. This behavior exists due to React Navigation being dynamically\n // constructed at runtime. We can get rid of this in the future if we use\n // the static configuration internally.\n if (!this.navigationRef.isReady()) {\n return false;\n }\n return this.navigationRef?.current?.canGoBack() ?? false;\n}\n\nexport function canDismiss(this: RouterStore): boolean {\n let state = this.rootState;\n\n // Keep traversing down the state tree until we find a stack navigator that we can pop\n while (state) {\n if (state.type === 'stack' && state.routes.length > 1) {\n return true;\n }\n if (state.index === undefined) return false;\n\n state = state.routes?.[state.index]?.state as any;\n }\n\n return false;\n}\n\nexport function setParams(this: RouterStore, params: Record<string, string | number> = {}) {\n assertIsReady(this);\n return (this.navigationRef?.current?.setParams as any)(params);\n}\n\nexport function linkTo(this: RouterStore, href: string, event?: string) {\n if (shouldLinkExternally(href)) {\n Linking.openURL(href);\n return;\n }\n\n assertIsReady(this);\n const navigationRef = this.navigationRef.current;\n\n if (navigationRef == null) {\n throw new Error(\n \"Couldn't find a navigation object. Is your component inside NavigationContainer?\"\n );\n }\n\n if (!this.linking) {\n throw new Error('Attempted to link to route when no routes are present');\n }\n\n if (href === '..' || href === '../') {\n navigationRef.goBack();\n return;\n }\n\n const rootState = navigationRef.getRootState();\n\n if (href.startsWith('.')) {\n // Resolve base path by merging the current segments with the params\n let base =\n this.routeInfo?.segments\n ?.map((segment) => {\n if (!segment.startsWith('[')) return segment;\n\n if (segment.startsWith('[...')) {\n segment = segment.slice(4, -1);\n const params = this.routeInfo?.params?.[segment];\n if (Array.isArray(params)) {\n return params.join('/');\n } else {\n return params?.split(',')?.join('/') ?? '';\n }\n } else {\n segment = segment.slice(1, -1);\n return this.routeInfo?.params?.[segment];\n }\n })\n .filter(Boolean)\n .join('/') ?? '/';\n\n if (!this.routeInfo?.isIndex) {\n base += '/..';\n }\n\n href = resolve(base, href);\n }\n\n const state = this.linking.getStateFromPath!(href, this.linking.config);\n\n if (!state || state.routes.length === 0) {\n console.error('Could not generate a valid navigation state for the given path: ' + href);\n return;\n }\n\n return navigationRef.dispatch(getNavigateAction(state, rootState, event));\n}\n\nfunction getNavigateAction(\n actionState: ResultState,\n navigationState: NavigationState,\n type = 'NAVIGATE'\n) {\n /**\n * We need to find the deepest navigator where the action and current state diverge, If they do not diverge, the\n * lowest navigator is the target.\n *\n * By default React Navigation will target the current navigator, but this doesn't work for all actions\n * For example:\n * - /deeply/nested/route -> /top-level-route the target needs to be the top-level navigator\n * - /stack/nestedStack/page -> /stack1/nestedStack/other-page needs to target the nestedStack navigator\n *\n * This matching needs to done by comparing the route names and the dynamic path, for example\n * - /1/page -> /2/anotherPage needs to target the /[id] navigator\n *\n * Other parameters such as search params and hash are not evaluated.\n */\n let actionStateRoute: PartialRoute<any> | undefined;\n\n // Traverse the state tree comparing the current state and the action state until we find where they diverge\n while (actionState && navigationState) {\n const stateRoute = navigationState.routes[navigationState.index];\n\n actionStateRoute = actionState.routes[actionState.routes.length - 1];\n\n const childState = actionStateRoute.state;\n const nextNavigationState = stateRoute.state;\n\n const dynamicName = matchDynamicName(actionStateRoute.name);\n\n const didActionAndCurrentStateDiverge =\n actionStateRoute.name !== stateRoute.name ||\n !childState ||\n !nextNavigationState ||\n (dynamicName && actionStateRoute.params?.[dynamicName] !== stateRoute.params?.[dynamicName]);\n\n if (didActionAndCurrentStateDiverge) {\n break;\n }\n\n actionState = childState;\n navigationState = nextNavigationState as NavigationState;\n }\n\n /*\n * We found the target navigator, but the payload is in the incorrect format\n * We need to convert the action state to a payload that can be dispatched\n */\n const rootPayload: Record<string, any> = { params: {} };\n let payload = rootPayload;\n let params = payload.params;\n\n // The root level of payload is a bit weird, its params are in the child object\n while (actionStateRoute) {\n Object.assign(params, { ...payload.params, ...actionStateRoute.params });\n // Assign the screen name to the payload\n payload.screen = actionStateRoute.name;\n // Merge the params, ensuring that we create a new object\n payload.params = { ...params };\n // Params don't include the screen, thats a separate attribute\n delete payload.params['screen'];\n\n // Continue down the payload tree\n // Initially these values are separate, but React Nav merges them after the first layer\n payload = payload.params;\n params = payload;\n\n actionStateRoute = actionStateRoute.state?.routes[actionStateRoute.state?.routes.length - 1];\n }\n\n // Expo Router uses only three actions, but these don't directly translate to all navigator actions\n if (type === 'PUSH') {\n // Only stack navigators have a push action, and even then we want to use NAVIGATE (see below)\n type = 'NAVIGATE';\n\n /*\n * The StackAction.PUSH does not work correctly with Expo Router.\n *\n * Expo Router provides a getId() function for every route, altering how React Navigation handles stack routing.\n * Ordinarily, PUSH always adds a new screen to the stack. However, with getId() present, it navigates to the screen with the matching ID instead (by moving the screen to the top of the stack)\n * When you try and push to a screen with the same ID, no navigation will occur\n * Refer to: https://github.com/react-navigation/react-navigation/blob/13d4aa270b301faf07960b4cd861ffc91e9b2c46/packages/routers/src/StackRouter.tsx#L279-L290\n *\n * Expo Router needs to retain the default behavior of PUSH, consistently adding new screens to the stack, even if their IDs are identical.\n *\n * To resolve this issue, we switch to using a NAVIGATE action with a new key. In the navigate action, screens are matched by either key or getId() function.\n * By generating a unique new key, we ensure that the screen is always pushed onto the stack.\n *\n */\n if (navigationState.type === 'stack') {\n rootPayload.key = `${rootPayload.name}-${nanoid()}`; // @see https://github.com/react-navigation/react-navigation/blob/13d4aa270b301faf07960b4cd861ffc91e9b2c46/packages/routers/src/StackRouter.tsx#L406-L407\n }\n }\n\n if (type === 'REPLACE' && navigationState.type === 'tab') {\n type = 'JUMP_TO';\n }\n\n return {\n type,\n target: navigationState.key,\n payload: {\n key: rootPayload.key,\n name: rootPayload.screen,\n params: rootPayload.params,\n },\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { HelmetProvider } from 'react-helmet-async';
2
+ import { HelmetProvider } from 'react-native-helmet-async';
3
3
  export declare const Head: React.FC<{
4
4
  children?: React.ReactNode;
5
5
  }> & {
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoHead.d.ts","sourceRoot":"","sources":["../../src/head/ExpoHead.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAU,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAE5D,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC,GAAG;IAC5D,QAAQ,EAAE,OAAO,cAAc,CAAC;CAGjC,CAAC"}
1
+ {"version":3,"file":"ExpoHead.d.ts","sourceRoot":"","sources":["../../src/head/ExpoHead.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAU,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEnE,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,CAAC,GAAG;IAC5D,QAAQ,EAAE,OAAO,cAAc,CAAC;CAGjC,CAAC"}
@@ -5,10 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.Head = void 0;
7
7
  const react_1 = __importDefault(require("react"));
8
- const react_helmet_async_1 = require("react-helmet-async");
8
+ const react_native_helmet_async_1 = require("react-native-helmet-async");
9
9
  const Head = ({ children }) => {
10
- return <react_helmet_async_1.Helmet>{children}</react_helmet_async_1.Helmet>;
10
+ return <react_native_helmet_async_1.Helmet>{children}</react_native_helmet_async_1.Helmet>;
11
11
  };
12
12
  exports.Head = Head;
13
- exports.Head.Provider = react_helmet_async_1.HelmetProvider;
13
+ exports.Head.Provider = react_native_helmet_async_1.HelmetProvider;
14
14
  //# sourceMappingURL=ExpoHead.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoHead.js","sourceRoot":"","sources":["../../src/head/ExpoHead.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,2DAA4D;AAErD,MAAM,IAAI,GAEb,CAAC,EAAE,QAAQ,EAAsB,EAAE,EAAE;IACvC,OAAO,CAAC,2BAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,2BAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAJW,QAAA,IAAI,QAIf;AAEF,YAAI,CAAC,QAAQ,GAAG,mCAAc,CAAC","sourcesContent":["import React from 'react';\nimport { Helmet, HelmetProvider } from 'react-helmet-async';\n\nexport const Head: React.FC<{ children?: React.ReactNode }> & {\n Provider: typeof HelmetProvider;\n} = ({ children }: { children?: any }) => {\n return <Helmet>{children}</Helmet>;\n};\n\nHead.Provider = HelmetProvider;\n"]}
1
+ {"version":3,"file":"ExpoHead.js","sourceRoot":"","sources":["../../src/head/ExpoHead.tsx"],"names":[],"mappings":";;;;;;AAAA,kDAA0B;AAC1B,yEAAmE;AAE5D,MAAM,IAAI,GAEb,CAAC,EAAE,QAAQ,EAAsB,EAAE,EAAE;IACvC,OAAO,CAAC,kCAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,kCAAM,CAAC,CAAC;AACrC,CAAC,CAAC;AAJW,QAAA,IAAI,QAIf;AAEF,YAAI,CAAC,QAAQ,GAAG,0CAAc,CAAC","sourcesContent":["import React from 'react';\nimport { Helmet, HelmetProvider } from 'react-native-helmet-async';\n\nexport const Head: React.FC<{ children?: React.ReactNode }> & {\n Provider: typeof HelmetProvider;\n} = ({ children }: { children?: any }) => {\n return <Helmet>{children}</Helmet>;\n};\n\nHead.Provider = HelmetProvider;\n"]}
@@ -1,3 +1,5 @@
1
+ import { Options } from './getRoutes';
2
+ export { Options } from './getRoutes';
1
3
  export type RouteInfo<TRegex = string> = {
2
4
  file: string;
3
5
  page: string;
@@ -9,5 +11,5 @@ export type ExpoRoutesManifestV1<TRegex = string> = {
9
11
  htmlRoutes: RouteInfo<TRegex>[];
10
12
  notFoundRoutes: RouteInfo<TRegex>[];
11
13
  };
12
- export declare function createRoutesManifest(paths: string[]): ExpoRoutesManifestV1 | null;
14
+ export declare function createRoutesManifest(paths: string[], options: Options): ExpoRoutesManifestV1 | null;
13
15
  //# sourceMappingURL=routes-manifest.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"routes-manifest.d.ts","sourceRoot":"","sources":["../src/routes-manifest.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,SAAS,CAAC,MAAM,GAAG,MAAM,IAAI;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,CAAC,MAAM,GAAG,MAAM,IAAI;IAClD,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;IAC/B,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;IAChC,cAAc,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;CACrC,CAAC;AAYF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,oBAAoB,GAAG,IAAI,CAYjF"}
1
+ {"version":3,"file":"routes-manifest.d.ts","sourceRoot":"","sources":["../src/routes-manifest.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAa,MAAM,aAAa,CAAC;AAIjD,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,MAAM,MAAM,SAAS,CAAC,MAAM,GAAG,MAAM,IAAI;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,CAAC,MAAM,GAAG,MAAM,IAAI;IAClD,SAAS,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;IAC/B,UAAU,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;IAChC,cAAc,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;CACrC,CAAC;AAYF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EAAE,EACf,OAAO,EAAE,OAAO,GACf,oBAAoB,GAAG,IAAI,CAc7B"}
@@ -12,12 +12,14 @@ function createMockContextModule(map = []) {
12
12
  });
13
13
  return contextModule;
14
14
  }
15
- function createRoutesManifest(paths) {
15
+ function createRoutesManifest(paths, options) {
16
16
  // TODO: Drop this part for Node.js
17
17
  const routeTree = (0, getRoutes_1.getRoutes)(createMockContextModule(paths), {
18
+ ...options,
18
19
  preserveApiRoutes: true,
19
20
  ignoreRequireErrors: true,
20
21
  ignoreEntryPoints: true,
22
+ platform: 'web',
21
23
  });
22
24
  if (!routeTree) {
23
25
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"routes-manifest.js","sourceRoot":"","sources":["../src/routes-manifest.ts"],"names":[],"mappings":";;;AAAA,0CAA0C;AAC1C,sBAAsB;AACtB,2CAAwC;AACxC,2DAAwD;AAgBxD,SAAS,uBAAuB,CAAC,MAAgB,EAAE;IACjD,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,KAAI,CAAC,EAAE,CAAC,CAAC;IAElD,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE;QAC3C,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG;KACjB,CAAC,CAAC;IAEH,OAAO,aAA+B,CAAC;AACzC,CAAC;AAED,SAAgB,oBAAoB,CAAC,KAAe;IAClD,mCAAmC;IACnC,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE;QAC1D,iBAAiB,EAAE,IAAI;QACvB,mBAAmB,EAAE,IAAI;QACzB,iBAAiB,EAAE,IAAI;KACxB,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE;QACd,OAAO,IAAI,CAAC;KACb;IACD,OAAO,IAAA,qCAAiB,EAAC,SAAS,CAAC,CAAC;AACtC,CAAC;AAZD,oDAYC","sourcesContent":["// This file runs in Node.js environments.\n// no relative imports\nimport { getRoutes } from './getRoutes';\nimport { getServerManifest } from './getServerManifest';\nimport { RequireContext } from './types';\n\nexport type RouteInfo<TRegex = string> = {\n file: string;\n page: string;\n namedRegex: TRegex;\n routeKeys: Record<string, string>;\n};\n\nexport type ExpoRoutesManifestV1<TRegex = string> = {\n apiRoutes: RouteInfo<TRegex>[];\n htmlRoutes: RouteInfo<TRegex>[];\n notFoundRoutes: RouteInfo<TRegex>[];\n};\n\nfunction createMockContextModule(map: string[] = []) {\n const contextModule = (key) => ({ default() {} });\n\n Object.defineProperty(contextModule, 'keys', {\n value: () => map,\n });\n\n return contextModule as RequireContext;\n}\n\nexport function createRoutesManifest(paths: string[]): ExpoRoutesManifestV1 | null {\n // TODO: Drop this part for Node.js\n const routeTree = getRoutes(createMockContextModule(paths), {\n preserveApiRoutes: true,\n ignoreRequireErrors: true,\n ignoreEntryPoints: true,\n });\n\n if (!routeTree) {\n return null;\n }\n return getServerManifest(routeTree);\n}\n"]}
1
+ {"version":3,"file":"routes-manifest.js","sourceRoot":"","sources":["../src/routes-manifest.ts"],"names":[],"mappings":";;;AAAA,0CAA0C;AAC1C,sBAAsB;AACtB,2CAAiD;AACjD,2DAAwD;AAkBxD,SAAS,uBAAuB,CAAC,MAAgB,EAAE;IACjD,MAAM,aAAa,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,KAAI,CAAC,EAAE,CAAC,CAAC;IAElD,MAAM,CAAC,cAAc,CAAC,aAAa,EAAE,MAAM,EAAE;QAC3C,KAAK,EAAE,GAAG,EAAE,CAAC,GAAG;KACjB,CAAC,CAAC;IAEH,OAAO,aAA+B,CAAC;AACzC,CAAC;AAED,SAAgB,oBAAoB,CAClC,KAAe,EACf,OAAgB;IAEhB,mCAAmC;IACnC,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,uBAAuB,CAAC,KAAK,CAAC,EAAE;QAC1D,GAAG,OAAO;QACV,iBAAiB,EAAE,IAAI;QACvB,mBAAmB,EAAE,IAAI;QACzB,iBAAiB,EAAE,IAAI;QACvB,QAAQ,EAAE,KAAK;KAChB,CAAC,CAAC;IAEH,IAAI,CAAC,SAAS,EAAE;QACd,OAAO,IAAI,CAAC;KACb;IACD,OAAO,IAAA,qCAAiB,EAAC,SAAS,CAAC,CAAC;AACtC,CAAC;AAjBD,oDAiBC","sourcesContent":["// This file runs in Node.js environments.\n// no relative imports\nimport { Options, getRoutes } from './getRoutes';\nimport { getServerManifest } from './getServerManifest';\nimport { RequireContext } from './types';\n\nexport { Options } from './getRoutes';\n\nexport type RouteInfo<TRegex = string> = {\n file: string;\n page: string;\n namedRegex: TRegex;\n routeKeys: Record<string, string>;\n};\n\nexport type ExpoRoutesManifestV1<TRegex = string> = {\n apiRoutes: RouteInfo<TRegex>[];\n htmlRoutes: RouteInfo<TRegex>[];\n notFoundRoutes: RouteInfo<TRegex>[];\n};\n\nfunction createMockContextModule(map: string[] = []) {\n const contextModule = (key) => ({ default() {} });\n\n Object.defineProperty(contextModule, 'keys', {\n value: () => map,\n });\n\n return contextModule as RequireContext;\n}\n\nexport function createRoutesManifest(\n paths: string[],\n options: Options\n): ExpoRoutesManifestV1 | null {\n // TODO: Drop this part for Node.js\n const routeTree = getRoutes(createMockContextModule(paths), {\n ...options,\n preserveApiRoutes: true,\n ignoreRequireErrors: true,\n ignoreEntryPoints: true,\n platform: 'web',\n });\n\n if (!routeTree) {\n return null;\n }\n return getServerManifest(routeTree);\n}\n"]}
@@ -5,10 +5,10 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import '@expo/metro-runtime';
8
- import { getRoutes } from '../getRoutes';
8
+ import { Options } from '../getRoutes';
9
9
  import { ExpoRouterServerManifestV1 } from '../getServerManifest';
10
10
  /** Get the linking manifest from a Node.js process. */
11
- declare function getManifest(options?: Parameters<typeof getRoutes>[1]): Promise<{
11
+ declare function getManifest(options?: Options): Promise<{
12
12
  initialRouteName?: string | undefined;
13
13
  screens: Record<string, import("../getReactNavigationConfig").Screen>;
14
14
  }>;
@@ -19,7 +19,7 @@ declare function getManifest(options?: Parameters<typeof getRoutes>[1]): Promise
19
19
  *
20
20
  * This is used for the production manifest where we pre-render certain pages and should no longer treat them as dynamic.
21
21
  */
22
- declare function getBuildTimeServerManifestAsync(options?: Parameters<typeof getRoutes>[1]): Promise<ExpoRouterServerManifestV1>;
22
+ declare function getBuildTimeServerManifestAsync(options?: Options): Promise<ExpoRouterServerManifestV1>;
23
23
  export declare function getStaticContent(location: URL): Promise<string>;
24
24
  export { getManifest, getBuildTimeServerManifestAsync };
25
25
  //# sourceMappingURL=renderStaticContent.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"renderStaticContent.d.ts","sourceRoot":"","sources":["../../src/static/renderStaticContent.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,qBAAqB,CAAC;AAY7B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,0BAA0B,EAAqB,MAAM,sBAAsB,CAAC;AAQrF,uDAAuD;AACvD,iBAAe,WAAW,CAAC,OAAO,GAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAM;;;GAWvE;AAED;;;;;;GAMG;AACH,iBAAe,+BAA+B,CAC5C,OAAO,GAAE,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAM,GAC5C,OAAO,CAAC,0BAA0B,CAAC,CAWrC;AAYD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CA0DrE;AAmBD,OAAO,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC"}
1
+ {"version":3,"file":"renderStaticContent.d.ts","sourceRoot":"","sources":["../../src/static/renderStaticContent.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,qBAAqB,CAAC;AAY7B,OAAO,EAAa,OAAO,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAqB,MAAM,sBAAsB,CAAC;AAQrF,uDAAuD;AACvD,iBAAe,WAAW,CAAC,OAAO,GAAE,OAAY;;;GAe/C;AAED;;;;;;GAMG;AACH,iBAAe,+BAA+B,CAC5C,OAAO,GAAE,OAAY,GACpB,OAAO,CAAC,0BAA0B,CAAC,CAcrC;AAYD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CA0DrE;AAmBD,OAAO,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC"}
@@ -51,7 +51,11 @@ const debug = require('debug')('expo:router:renderStaticContent');
51
51
  react_native_web_1.AppRegistry.registerComponent('App', () => ExpoRoot_1.ExpoRoot);
52
52
  /** Get the linking manifest from a Node.js process. */
53
53
  async function getManifest(options = {}) {
54
- const routeTree = (0, getRoutes_1.getRoutes)(_ctx_1.ctx, { preserveApiRoutes: true, ...options });
54
+ const routeTree = (0, getRoutes_1.getRoutes)(_ctx_1.ctx, {
55
+ preserveApiRoutes: true,
56
+ platform: 'web',
57
+ ...options,
58
+ });
55
59
  if (!routeTree) {
56
60
  throw new Error('No routes found');
57
61
  }
@@ -68,7 +72,10 @@ exports.getManifest = getManifest;
68
72
  * This is used for the production manifest where we pre-render certain pages and should no longer treat them as dynamic.
69
73
  */
70
74
  async function getBuildTimeServerManifestAsync(options = {}) {
71
- const routeTree = (0, getRoutes_1.getRoutes)(_ctx_1.ctx, options);
75
+ const routeTree = (0, getRoutes_1.getRoutes)(_ctx_1.ctx, {
76
+ platform: 'web',
77
+ ...options,
78
+ });
72
79
  if (!routeTree) {
73
80
  throw new Error('No routes found');
74
81
  }
@@ -1 +1 @@
1
- {"version":3,"file":"renderStaticContent.js","sourceRoot":"","sources":["../../src/static/renderStaticContent.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;;;;;GAKG;AACH,+BAA6B;AAE7B,qDAA+E;AAC/E,6DAA+C;AAC/C,kDAA0B;AAC1B,wEAAmD;AACnD,uDAA+C;AAE/C,yDAAsD;AACtD,qCAAiC;AACjC,0CAAuC;AACvC,0EAAuE;AACvE,4CAAyC;AACzC,4DAAqF;AACrF,kCAA+B;AAC/B,oEAAiE;AAEjE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,iCAAiC,CAAC,CAAC;AAElE,8BAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,mBAAQ,CAAC,CAAC;AAErD,uDAAuD;AACvD,KAAK,UAAU,WAAW,CAAC,UAA2C,EAAE;IACtE,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,UAAG,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAE1E,IAAI,CAAC,SAAS,EAAE;QACd,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;KACpC;IAED,6BAA6B;IAC7B,MAAM,IAAA,6CAAqB,EAAC,SAAS,CAAC,CAAC;IAEvC,OAAO,IAAA,mDAAwB,EAAC,SAAS,EAAE,KAAK,CAAC,CAAC;AACpD,CAAC;AA+GQ,kCAAW;AA7GpB;;;;;;GAMG;AACH,KAAK,UAAU,+BAA+B,CAC5C,UAA2C,EAAE;IAE7C,MAAM,SAAS,GAAG,IAAA,qBAAS,EAAC,UAAG,EAAE,OAAO,CAAC,CAAC;IAE1C,IAAI,CAAC,SAAS,EAAE;QACd,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;KACpC;IAED,6BAA6B;IAC7B,MAAM,IAAA,6CAAqB,EAAC,SAAS,CAAC,CAAC;IAEvC,OAAO,IAAA,qCAAiB,EAAC,SAAS,CAAC,CAAC;AACtC,CAAC;AAyFqB,0EAA+B;AAvFrD,SAAS,4BAA4B;IACnC,iDAAiD;IACjD,0JAA0J;IAE1J,8FAA8F;IAC9F,yJAAyJ;IACzJ,MAAM,QAAQ,GAAG,uCAAuC,CAAC;IACzD,MAAM,CAAC,QAAQ,CAAC,GAAG,IAAI,GAAG,EAA8B,CAAC;AAC3D,CAAC;AAEM,KAAK,UAAU,gBAAgB,CAAC,QAAa;IAClD,MAAM,WAAW,GAAqB,EAAE,CAAC;IAEzC,MAAM,GAAG,GAAG,eAAK,CAAC,SAAS,EAAsB,CAAC;IAElD,MAAM;IACJ,+DAA+D;IAC/D,kDAAkD;IAClD,OAAO,EACP,eAAe,GAChB,GAAG,8BAAW,CAAC,cAAc,CAAC,KAAK,EAAE;QACpC,YAAY,EAAE;YACZ,QAAQ;YACR,OAAO,EAAE,UAAG;YACZ,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CACzB,CAAC,IAAI,CACH;UAAA,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,GAAG,CAChC;QAAA,EAAE,IAAI,CAAC,CACR;SACF;KACF,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,IAAA,mCAAgB,GAAE,CAAC;IAEhC,yGAAyG;IACzG,sGAAsG;IACtG,IAAI,CAAC,kBAAkB,EAAE,CAAC;IAE1B,qEAAqE;IACrE,0HAA0H;IAC1H,4BAA4B,EAAE,CAAC;IAE/B,MAAM,MAAM,GAAG,MAAM,qBAAc,CAAC,wBAAwB,CAC1D,CAAC,WAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAClC;MAAA,CAAC,wBAAe,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,wBAAe,CACvD;IAAA,EAAE,WAAI,CAAC,QAAQ,CAAC,CACjB,CAAC;IAEF,IAAI,IAAI,GAAG,EAAE,CAAC;IAEd,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,MAAM,EAAE;QAChC,IAAI,IAAI,KAAK,CAAC;KACf;IAED,+EAA+E;IAC/E,MAAM,GAAG,GAAG,qBAAc,CAAC,oBAAoB,CAAC,eAAe,EAAE,CAAC,CAAC;IAEnE,IAAI,MAAM,GAAG,kCAAkC,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE1E,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,GAAG,SAAS,CAAC,CAAC;IAEpD,MAAM,KAAK,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAC;IACxC,KAAK,CAAC,iCAAiC,KAAK,CAAC,MAAM,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/D,qCAAqC;IACrC,4CAA4C;IAC5C,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;IAE/D,OAAO,iBAAiB,GAAG,MAAM,CAAC;AACpC,CAAC;AA1DD,4CA0DC;AAED,SAAS,kCAAkC,CAAC,MAAW,EAAE,IAAY;IACnE,kBAAkB;IAClB,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACpF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC;QACzC,IAAI,MAAM,EAAE;YACV,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC;SAClD;KACF;IAED,aAAa;IACb,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAC7E,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAE7E,OAAO,IAAI,CAAC;AACd,CAAC","sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport '@expo/metro-runtime';\n\nimport { ServerContainer, ServerContainerRef } from '@react-navigation/native';\nimport * as Font from 'expo-font/build/server';\nimport React from 'react';\nimport ReactDOMServer from 'react-dom/server.node';\nimport { AppRegistry } from 'react-native-web';\n\nimport { getRootComponent } from './getRootComponent';\nimport { ctx } from '../../_ctx';\nimport { ExpoRoot } from '../ExpoRoot';\nimport { getReactNavigationConfig } from '../getReactNavigationConfig';\nimport { getRoutes } from '../getRoutes';\nimport { ExpoRouterServerManifestV1, getServerManifest } from '../getServerManifest';\nimport { Head } from '../head';\nimport { loadStaticParamsAsync } from '../loadStaticParamsAsync';\n\nconst debug = require('debug')('expo:router:renderStaticContent');\n\nAppRegistry.registerComponent('App', () => ExpoRoot);\n\n/** Get the linking manifest from a Node.js process. */\nasync function getManifest(options: Parameters<typeof getRoutes>[1] = {}) {\n const routeTree = getRoutes(ctx, { preserveApiRoutes: true, ...options });\n\n if (!routeTree) {\n throw new Error('No routes found');\n }\n\n // Evaluate all static params\n await loadStaticParamsAsync(routeTree);\n\n return getReactNavigationConfig(routeTree, false);\n}\n\n/**\n * Get the server manifest with all dynamic routes loaded with `generateStaticParams`.\n * Unlike the `expo-router/src/routes-manifest.ts` method, this requires loading the entire app in-memory, which\n * takes substantially longer and requires Metro bundling.\n *\n * This is used for the production manifest where we pre-render certain pages and should no longer treat them as dynamic.\n */\nasync function getBuildTimeServerManifestAsync(\n options: Parameters<typeof getRoutes>[1] = {}\n): Promise<ExpoRouterServerManifestV1> {\n const routeTree = getRoutes(ctx, options);\n\n if (!routeTree) {\n throw new Error('No routes found');\n }\n\n // Evaluate all static params\n await loadStaticParamsAsync(routeTree);\n\n return getServerManifest(routeTree);\n}\n\nfunction resetReactNavigationContexts() {\n // https://github.com/expo/router/discussions/588\n // https://github.com/react-navigation/react-navigation/blob/9fe34b445fcb86e5666f61e144007d7540f014fa/packages/elements/src/getNamedContext.tsx#LL3C1-L4C1\n\n // React Navigation is storing providers in a global, this is fine for the first static render\n // but subsequent static renders of Stack or Tabs will cause React to throw a warning. To prevent this warning, we'll reset the globals before rendering.\n const contexts = '__react_navigation__elements_contexts';\n global[contexts] = new Map<string, React.Context<any>>();\n}\n\nexport async function getStaticContent(location: URL): Promise<string> {\n const headContext: { helmet?: any } = {};\n\n const ref = React.createRef<ServerContainerRef>();\n\n const {\n // NOTE: The `element` that's returned adds two extra Views and\n // the seemingly unused `RootTagContext.Provider`.\n element,\n getStyleElement,\n } = AppRegistry.getApplication('App', {\n initialProps: {\n location,\n context: ctx,\n wrapper: ({ children }) => (\n <Root>\n <div id=\"root\">{children}</div>\n </Root>\n ),\n },\n });\n\n const Root = getRootComponent();\n\n // Clear any existing static resources from the global scope to attempt to prevent leaking between pages.\n // This could break if pages are rendered in parallel or if fonts are loaded outside of the React tree\n Font.resetServerContext();\n\n // This MUST be run before `ReactDOMServer.renderToString` to prevent\n // \"Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.\"\n resetReactNavigationContexts();\n\n const stream = await ReactDOMServer.renderToStaticNodeStream(\n <Head.Provider context={headContext}>\n <ServerContainer ref={ref}>{element}</ServerContainer>\n </Head.Provider>\n );\n\n let html = '';\n\n for await (const chunk of stream) {\n html += chunk;\n }\n\n // Eval the CSS after the HTML is rendered so that the CSS is in the same order\n const css = ReactDOMServer.renderToStaticMarkup(getStyleElement());\n\n let output = mixHeadComponentsWithStaticResults(headContext.helmet, html);\n\n output = output.replace('</head>', `${css}</head>`);\n\n const fonts = Font.getServerResources();\n debug(`Pushing static fonts: (count: ${fonts.length})`, fonts);\n // debug('Push static fonts:', fonts)\n // Inject static fonts loaded with expo-font\n output = output.replace('</head>', `${fonts.join('')}</head>`);\n\n return '<!DOCTYPE html>' + output;\n}\n\nfunction mixHeadComponentsWithStaticResults(helmet: any, html: string) {\n // Head components\n for (const key of ['title', 'priority', 'meta', 'link', 'script', 'style'].reverse()) {\n const result = helmet?.[key]?.toString();\n if (result) {\n html = html.replace('<head>', `<head>${result}`);\n }\n }\n\n // attributes\n html = html.replace('<html ', `<html ${helmet?.htmlAttributes.toString()} `);\n html = html.replace('<body ', `<body ${helmet?.bodyAttributes.toString()} `);\n\n return html;\n}\n\n// Re-export for use in server\nexport { getManifest, getBuildTimeServerManifestAsync };\n"]}
1
+ {"version":3,"file":"renderStaticContent.js","sourceRoot":"","sources":["../../src/static/renderStaticContent.tsx"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright © 2023 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\nimport '@expo/metro-runtime';\n\nimport { ServerContainer, ServerContainerRef } from '@react-navigation/native';\nimport * as Font from 'expo-font/build/server';\nimport React from 'react';\nimport ReactDOMServer from 'react-dom/server.node';\nimport { AppRegistry } from 'react-native-web';\n\nimport { getRootComponent } from './getRootComponent';\nimport { ctx } from '../../_ctx';\nimport { ExpoRoot } from '../ExpoRoot';\nimport { getReactNavigationConfig } from '../getReactNavigationConfig';\nimport { getRoutes, Options } from '../getRoutes';\nimport { ExpoRouterServerManifestV1, getServerManifest } from '../getServerManifest';\nimport { Head } from '../head';\nimport { loadStaticParamsAsync } from '../loadStaticParamsAsync';\n\nconst debug = require('debug')('expo:router:renderStaticContent');\n\nAppRegistry.registerComponent('App', () => ExpoRoot);\n\n/** Get the linking manifest from a Node.js process. */\nasync function getManifest(options: Options = {}) {\n const routeTree = getRoutes(ctx, {\n preserveApiRoutes: true,\n platform: 'web',\n ...options,\n });\n\n if (!routeTree) {\n throw new Error('No routes found');\n }\n\n // Evaluate all static params\n await loadStaticParamsAsync(routeTree);\n\n return getReactNavigationConfig(routeTree, false);\n}\n\n/**\n * Get the server manifest with all dynamic routes loaded with `generateStaticParams`.\n * Unlike the `expo-router/src/routes-manifest.ts` method, this requires loading the entire app in-memory, which\n * takes substantially longer and requires Metro bundling.\n *\n * This is used for the production manifest where we pre-render certain pages and should no longer treat them as dynamic.\n */\nasync function getBuildTimeServerManifestAsync(\n options: Options = {}\n): Promise<ExpoRouterServerManifestV1> {\n const routeTree = getRoutes(ctx, {\n platform: 'web',\n ...options,\n });\n\n if (!routeTree) {\n throw new Error('No routes found');\n }\n\n // Evaluate all static params\n await loadStaticParamsAsync(routeTree);\n\n return getServerManifest(routeTree);\n}\n\nfunction resetReactNavigationContexts() {\n // https://github.com/expo/router/discussions/588\n // https://github.com/react-navigation/react-navigation/blob/9fe34b445fcb86e5666f61e144007d7540f014fa/packages/elements/src/getNamedContext.tsx#LL3C1-L4C1\n\n // React Navigation is storing providers in a global, this is fine for the first static render\n // but subsequent static renders of Stack or Tabs will cause React to throw a warning. To prevent this warning, we'll reset the globals before rendering.\n const contexts = '__react_navigation__elements_contexts';\n global[contexts] = new Map<string, React.Context<any>>();\n}\n\nexport async function getStaticContent(location: URL): Promise<string> {\n const headContext: { helmet?: any } = {};\n\n const ref = React.createRef<ServerContainerRef>();\n\n const {\n // NOTE: The `element` that's returned adds two extra Views and\n // the seemingly unused `RootTagContext.Provider`.\n element,\n getStyleElement,\n } = AppRegistry.getApplication('App', {\n initialProps: {\n location,\n context: ctx,\n wrapper: ({ children }) => (\n <Root>\n <div id=\"root\">{children}</div>\n </Root>\n ),\n },\n });\n\n const Root = getRootComponent();\n\n // Clear any existing static resources from the global scope to attempt to prevent leaking between pages.\n // This could break if pages are rendered in parallel or if fonts are loaded outside of the React tree\n Font.resetServerContext();\n\n // This MUST be run before `ReactDOMServer.renderToString` to prevent\n // \"Warning: Detected multiple renderers concurrently rendering the same context provider. This is currently unsupported.\"\n resetReactNavigationContexts();\n\n const stream = await ReactDOMServer.renderToStaticNodeStream(\n <Head.Provider context={headContext}>\n <ServerContainer ref={ref}>{element}</ServerContainer>\n </Head.Provider>\n );\n\n let html = '';\n\n for await (const chunk of stream) {\n html += chunk;\n }\n\n // Eval the CSS after the HTML is rendered so that the CSS is in the same order\n const css = ReactDOMServer.renderToStaticMarkup(getStyleElement());\n\n let output = mixHeadComponentsWithStaticResults(headContext.helmet, html);\n\n output = output.replace('</head>', `${css}</head>`);\n\n const fonts = Font.getServerResources();\n debug(`Pushing static fonts: (count: ${fonts.length})`, fonts);\n // debug('Push static fonts:', fonts)\n // Inject static fonts loaded with expo-font\n output = output.replace('</head>', `${fonts.join('')}</head>`);\n\n return '<!DOCTYPE html>' + output;\n}\n\nfunction mixHeadComponentsWithStaticResults(helmet: any, html: string) {\n // Head components\n for (const key of ['title', 'priority', 'meta', 'link', 'script', 'style'].reverse()) {\n const result = helmet?.[key]?.toString();\n if (result) {\n html = html.replace('<head>', `<head>${result}`);\n }\n }\n\n // attributes\n html = html.replace('<html ', `<html ${helmet?.htmlAttributes.toString()} `);\n html = html.replace('<body ', `<body ${helmet?.bodyAttributes.toString()} `);\n\n return html;\n}\n\n// Re-export for use in server\nexport { getManifest, getBuildTimeServerManifestAsync };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/typed-routes/generate.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAO1C,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,cAAc,UAoChE"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/typed-routes/generate.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAO1C,wBAAgB,6BAA6B,CAAC,GAAG,EAAE,cAAc,UAqChE"}
@@ -17,6 +17,7 @@ function getTypedRoutesDeclarationFile(ctx) {
17
17
  const dynamicRoutes = new Set();
18
18
  const dynamicRouteContextKeys = new Set();
19
19
  walkRouteNode((0, getRoutes_1.getRoutes)(ctx, {
20
+ platformRoutes: false,
20
21
  ignoreEntryPoints: true,
21
22
  ignoreRequireErrors: true,
22
23
  importMode: 'async',
@@ -1 +1 @@
1
- {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/typed-routes/generate.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'path';\n\nimport { RouteNode } from '../Route';\nimport { getRoutes } from '../getRoutes';\nimport { isTypedRoute, removeSupportedExtensions } from '../matchers';\nimport { RequireContext } from '../types';\n\n// /[...param1]/ - Match [...param1]\nconst CATCH_ALL = /\\[\\.\\.\\..+?\\]/g;\n// /[param1] - Match [param1]\nconst SLUG = /\\[.+?\\]/g;\n\nexport function getTypedRoutesDeclarationFile(ctx: RequireContext) {\n const staticRoutes = new Set<string>();\n const dynamicRoutes = new Set<string>();\n const dynamicRouteContextKeys = new Set<string>();\n\n walkRouteNode(\n getRoutes(ctx, {\n ignoreEntryPoints: true,\n ignoreRequireErrors: true,\n importMode: 'async',\n }),\n staticRoutes,\n dynamicRoutes,\n dynamicRouteContextKeys\n );\n\n // If the user has expo-router v3+ installed, we can use the types from the package\n return (\n fs\n .readFileSync(path.join(__dirname, '../../types/expo-router.d.ts'), 'utf-8')\n // Swap from being a namespace to a module\n .replace('declare namespace ExpoRouter {', `declare module \"expo-router\" {`)\n // Add the route values\n .replace(\n 'type StaticRoutes = string;',\n `type StaticRoutes = ${setToUnionType(staticRoutes)};`\n )\n .replace(\n 'type DynamicRoutes<T extends string> = string;',\n `type DynamicRoutes<T extends string> = ${setToUnionType(dynamicRoutes)};`\n )\n .replace(\n 'type DynamicRouteTemplate = never;',\n `type DynamicRouteTemplate = ${setToUnionType(dynamicRouteContextKeys)};`\n )\n );\n}\n\n/**\n * Walks a RouteNode tree and adds the routes to the provided sets\n */\nfunction walkRouteNode(\n routeNode: RouteNode | null,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteContextKeys: Set<string>\n) {\n if (!routeNode) return;\n\n addRouteNode(routeNode, staticRoutes, dynamicRoutes, dynamicRouteContextKeys);\n\n for (const child of routeNode.children) {\n walkRouteNode(child, staticRoutes, dynamicRoutes, dynamicRouteContextKeys);\n }\n}\n\n/**\n * Given a RouteNode, adds the route to the correct sets\n * Modifies the RouteNode.route to be a typed-route string\n */\nfunction addRouteNode(\n routeNode: RouteNode | null,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteContextKeys: Set<string>\n) {\n if (!routeNode?.route) return;\n if (!isTypedRoute(routeNode.route)) return;\n\n let routePath = `${removeSupportedExtensions(routeNode.route).replace(/\\/?index$/, '')}`; // replace /index with /\n\n if (!routePath.startsWith('/')) {\n routePath = `/${routePath}`;\n }\n\n if (routeNode.dynamic) {\n for (const path of generateCombinations(routePath)) {\n dynamicRouteContextKeys.add(path);\n dynamicRoutes.add(\n `${path\n .replaceAll(CATCH_ALL, '${CatchAllRoutePart<T>}')\n .replaceAll(SLUG, '${SingleRoutePart<T>}')}`\n );\n }\n } else {\n for (const combination of generateCombinations(routePath)) {\n staticRoutes.add(combination);\n }\n }\n}\n\n/**\n * Converts a Set to a TypeScript union type\n */\nconst setToUnionType = <T>(set: Set<T>) => {\n return set.size > 0 ? [...set].map((s) => `\\`${s}\\``).join(' | ') : 'never';\n};\n\nfunction generateCombinations(pathname) {\n const groups = pathname.split('/').filter((part) => part.startsWith('(') && part.endsWith(')'));\n const combinations: string[] = [];\n\n function generate(currentIndex, currentPath) {\n if (currentIndex === groups.length) {\n combinations.push(currentPath.replace(/\\/{2,}/g, '/'));\n return;\n }\n\n const group = groups[currentIndex];\n const withoutGroup = currentPath.replace(group, '');\n generate(currentIndex + 1, withoutGroup);\n generate(currentIndex + 1, currentPath);\n }\n\n generate(0, pathname);\n return combinations;\n}\n"]}
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/typed-routes/generate.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'node:fs';\nimport path from 'path';\n\nimport { RouteNode } from '../Route';\nimport { getRoutes } from '../getRoutes';\nimport { isTypedRoute, removeSupportedExtensions } from '../matchers';\nimport { RequireContext } from '../types';\n\n// /[...param1]/ - Match [...param1]\nconst CATCH_ALL = /\\[\\.\\.\\..+?\\]/g;\n// /[param1] - Match [param1]\nconst SLUG = /\\[.+?\\]/g;\n\nexport function getTypedRoutesDeclarationFile(ctx: RequireContext) {\n const staticRoutes = new Set<string>();\n const dynamicRoutes = new Set<string>();\n const dynamicRouteContextKeys = new Set<string>();\n\n walkRouteNode(\n getRoutes(ctx, {\n platformRoutes: false, // We don't need to generate platform specific routes\n ignoreEntryPoints: true,\n ignoreRequireErrors: true,\n importMode: 'async',\n }),\n staticRoutes,\n dynamicRoutes,\n dynamicRouteContextKeys\n );\n\n // If the user has expo-router v3+ installed, we can use the types from the package\n return (\n fs\n .readFileSync(path.join(__dirname, '../../types/expo-router.d.ts'), 'utf-8')\n // Swap from being a namespace to a module\n .replace('declare namespace ExpoRouter {', `declare module \"expo-router\" {`)\n // Add the route values\n .replace(\n 'type StaticRoutes = string;',\n `type StaticRoutes = ${setToUnionType(staticRoutes)};`\n )\n .replace(\n 'type DynamicRoutes<T extends string> = string;',\n `type DynamicRoutes<T extends string> = ${setToUnionType(dynamicRoutes)};`\n )\n .replace(\n 'type DynamicRouteTemplate = never;',\n `type DynamicRouteTemplate = ${setToUnionType(dynamicRouteContextKeys)};`\n )\n );\n}\n\n/**\n * Walks a RouteNode tree and adds the routes to the provided sets\n */\nfunction walkRouteNode(\n routeNode: RouteNode | null,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteContextKeys: Set<string>\n) {\n if (!routeNode) return;\n\n addRouteNode(routeNode, staticRoutes, dynamicRoutes, dynamicRouteContextKeys);\n\n for (const child of routeNode.children) {\n walkRouteNode(child, staticRoutes, dynamicRoutes, dynamicRouteContextKeys);\n }\n}\n\n/**\n * Given a RouteNode, adds the route to the correct sets\n * Modifies the RouteNode.route to be a typed-route string\n */\nfunction addRouteNode(\n routeNode: RouteNode | null,\n staticRoutes: Set<string>,\n dynamicRoutes: Set<string>,\n dynamicRouteContextKeys: Set<string>\n) {\n if (!routeNode?.route) return;\n if (!isTypedRoute(routeNode.route)) return;\n\n let routePath = `${removeSupportedExtensions(routeNode.route).replace(/\\/?index$/, '')}`; // replace /index with /\n\n if (!routePath.startsWith('/')) {\n routePath = `/${routePath}`;\n }\n\n if (routeNode.dynamic) {\n for (const path of generateCombinations(routePath)) {\n dynamicRouteContextKeys.add(path);\n dynamicRoutes.add(\n `${path\n .replaceAll(CATCH_ALL, '${CatchAllRoutePart<T>}')\n .replaceAll(SLUG, '${SingleRoutePart<T>}')}`\n );\n }\n } else {\n for (const combination of generateCombinations(routePath)) {\n staticRoutes.add(combination);\n }\n }\n}\n\n/**\n * Converts a Set to a TypeScript union type\n */\nconst setToUnionType = <T>(set: Set<T>) => {\n return set.size > 0 ? [...set].map((s) => `\\`${s}\\``).join(' | ') : 'never';\n};\n\nfunction generateCombinations(pathname) {\n const groups = pathname.split('/').filter((part) => part.startsWith('(') && part.endsWith(')'));\n const combinations: string[] = [];\n\n function generate(currentIndex, currentPath) {\n if (currentIndex === groups.length) {\n combinations.push(currentPath.replace(/\\/{2,}/g, '/'));\n return;\n }\n\n const group = groups[currentIndex];\n const withoutGroup = currentPath.replace(group, '');\n generate(currentIndex + 1, withoutGroup);\n generate(currentIndex + 1, currentPath);\n }\n\n generate(0, pathname);\n return combinations;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-router",
3
- "version": "3.5.3",
3
+ "version": "3.5.5",
4
4
  "description": "Expo Router is a file-based router for React Native and web applications.",
5
5
  "author": "650 Industries, Inc.",
6
6
  "license": "MIT",
@@ -99,8 +99,8 @@
99
99
  "@react-navigation/native": "~6.1.6",
100
100
  "@react-navigation/native-stack": "~6.9.12",
101
101
  "expo-splash-screen": "0.27.2",
102
- "react-helmet-async": "^1.3.0",
102
+ "react-native-helmet-async": "2.0.4",
103
103
  "schema-utils": "^4.0.1"
104
104
  },
105
- "gitHead": "f47e3af17a790a34b95fe10dda8383389e7d74e2"
105
+ "gitHead": "4a7cf0d0baf6dfc595d93f604945d2142e705a36"
106
106
  }
@@ -40,6 +40,10 @@
40
40
  "description": "Changes the routes directory from `app` to another value. Defaults to `app`. Avoid using this property.",
41
41
  "type": "string"
42
42
  },
43
+ "platformRoutes": {
44
+ "description": "Enable or disable platform-specific routes. Defaults to `true`.",
45
+ "type": "boolean"
46
+ },
43
47
  "asyncRoutes": {
44
48
  "description": "Should Async Routes be enabled. `production` is currently web-only and will be disabled on native.",
45
49
  "oneOf": [