@hybridly/core 0.4.1 → 0.4.3

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/dist/index.cjs CHANGED
@@ -1,16 +1,14 @@
1
1
  'use strict';
2
2
 
3
- Object.defineProperty(exports, '__esModule', { value: true });
4
-
3
+ const qs = require('qs');
5
4
  const utils = require('@hybridly/utils');
6
5
  const axios = require('axios');
7
6
  const superjson = require('superjson');
8
- const qs = require('qs');
9
7
 
10
- function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
8
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
11
9
 
12
- const axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
13
- const qs__default = /*#__PURE__*/_interopDefaultLegacy(qs);
10
+ const qs__default = /*#__PURE__*/_interopDefaultCompat(qs);
11
+ const axios__default = /*#__PURE__*/_interopDefaultCompat(axios);
14
12
 
15
13
  const STORAGE_EXTERNAL_KEY = "hybridly:external";
16
14
  const HYBRIDLY_HEADER = "x-hybrid";
@@ -27,18 +25,18 @@ const SCROLL_REGION_ATTRIBUTE = "scroll-region";
27
25
 
28
26
  const constants = {
29
27
  __proto__: null,
30
- STORAGE_EXTERNAL_KEY: STORAGE_EXTERNAL_KEY,
31
- HYBRIDLY_HEADER: HYBRIDLY_HEADER,
32
- EXTERNAL_NAVIGATION_HEADER: EXTERNAL_NAVIGATION_HEADER,
33
- PARTIAL_COMPONENT_HEADER: PARTIAL_COMPONENT_HEADER,
34
- ONLY_DATA_HEADER: ONLY_DATA_HEADER,
28
+ CONTEXT_HEADER: CONTEXT_HEADER,
35
29
  DIALOG_KEY_HEADER: DIALOG_KEY_HEADER,
36
30
  DIALOG_REDIRECT_HEADER: DIALOG_REDIRECT_HEADER,
37
- EXCEPT_DATA_HEADER: EXCEPT_DATA_HEADER,
38
- CONTEXT_HEADER: CONTEXT_HEADER,
39
- VERSION_HEADER: VERSION_HEADER,
40
31
  ERROR_BAG_HEADER: ERROR_BAG_HEADER,
41
- SCROLL_REGION_ATTRIBUTE: SCROLL_REGION_ATTRIBUTE
32
+ EXCEPT_DATA_HEADER: EXCEPT_DATA_HEADER,
33
+ EXTERNAL_NAVIGATION_HEADER: EXTERNAL_NAVIGATION_HEADER,
34
+ HYBRIDLY_HEADER: HYBRIDLY_HEADER,
35
+ ONLY_DATA_HEADER: ONLY_DATA_HEADER,
36
+ PARTIAL_COMPONENT_HEADER: PARTIAL_COMPONENT_HEADER,
37
+ SCROLL_REGION_ATTRIBUTE: SCROLL_REGION_ATTRIBUTE,
38
+ STORAGE_EXTERNAL_KEY: STORAGE_EXTERNAL_KEY,
39
+ VERSION_HEADER: VERSION_HEADER
42
40
  };
43
41
 
44
42
  class NotAHybridResponseError extends Error {
@@ -245,6 +243,7 @@ function setHistoryState(options = {}) {
245
243
  utils.debug.history("Setting history state:", {
246
244
  method,
247
245
  context
246
+ // serialized,
248
247
  });
249
248
  try {
250
249
  window.history[method](serialized, "", context.url);
@@ -360,10 +359,59 @@ function createSerializer(options) {
360
359
  };
361
360
  }
362
361
 
362
+ function getUrlRegexForRoute(name) {
363
+ const routing = getRouting();
364
+ const definition = getRouteDefinition(name);
365
+ const path = definition.uri.replaceAll("/", "\\/");
366
+ const domain = definition.domain;
367
+ const protocolPrefix = routing.url.match(/^\w+:\/\//)?.[0];
368
+ const origin = domain ? `${protocolPrefix}${domain}${routing.port ? `:${routing.port}` : ""}`.replaceAll("/", "\\/") : routing.url.replaceAll("/", "\\/");
369
+ const urlPathRegexPattern = path.length > 0 ? `\\/${path.replace(/\/$/g, "")}` : "";
370
+ let urlRegexPattern = `^${origin.replaceAll(".", "\\.")}${urlPathRegexPattern}\\/?(\\?.*)?$`;
371
+ urlRegexPattern = urlRegexPattern.replace(/(\\\/?){([^}?]+)(\??)}/g, (_, slash, parameterName, optional) => {
372
+ const where = definition.wheres?.[parameterName];
373
+ let regexTemplate = where?.replace(/(^\^)|(\$$)/g, "") || "[^/?]+";
374
+ regexTemplate = `(?<${parameterName}>${regexTemplate})`;
375
+ if (optional) {
376
+ return `(${slash ? "\\/?" : ""}${regexTemplate})?`;
377
+ }
378
+ return (slash ? "\\/" : "") + regexTemplate;
379
+ });
380
+ return RegExp(urlRegexPattern);
381
+ }
382
+ function urlMatchesRoute(url, name, routeParameters) {
383
+ const parameters = routeParameters || {};
384
+ const definition = getRouting().routes[name];
385
+ if (!definition) {
386
+ return false;
387
+ }
388
+ const matches = getUrlRegexForRoute(name).exec(url);
389
+ if (!matches) {
390
+ return false;
391
+ }
392
+ for (const k in matches.groups) {
393
+ matches.groups[k] = typeof matches.groups[k] === "string" ? decodeURIComponent(matches.groups[k]) : matches.groups[k];
394
+ }
395
+ return Object.keys(parameters).every((parameterName) => {
396
+ let value = parameters[parameterName];
397
+ const bindingProperty = definition.bindings?.[parameterName];
398
+ if (bindingProperty && typeof value === "object") {
399
+ value = value[bindingProperty];
400
+ }
401
+ return matches.groups?.[parameterName] === value.toString();
402
+ });
403
+ }
363
404
  function generateRouteFromName(name, parameters, absolute, shouldThrow) {
364
405
  const url = getUrlFromName(name, parameters, shouldThrow);
365
406
  return absolute === false ? url.toString().replace(url.origin, "") : url.toString();
366
407
  }
408
+ function getNameFromUrl(url, parameters) {
409
+ const routing = getRouting();
410
+ const routes = Object.values(routing.routes).map((x) => x.name);
411
+ return routes.find((routeName) => {
412
+ return urlMatchesRoute(url, routeName, parameters);
413
+ });
414
+ }
367
415
  function getUrlFromName(name, parameters, shouldThrow) {
368
416
  const routing = getRouting();
369
417
  const definition = getRouteDefinition(name);
@@ -376,32 +424,39 @@ function getUrlFromName(name, parameters, shouldThrow) {
376
424
  }));
377
425
  return url;
378
426
  }
379
- function getRouteTransformable(routeName, routeParameters, shouldThrow) {
427
+ function getRouteParameterValue(routeName, parameterName, routeParameters) {
380
428
  const routing = getRouting();
429
+ const definition = getRouteDefinition(routeName);
430
+ const parameters = routeParameters || {};
431
+ const value = (() => {
432
+ const value2 = parameters[parameterName];
433
+ const bindingProperty = definition.bindings?.[parameterName];
434
+ if (bindingProperty && value2 != null && typeof value2 === "object") {
435
+ return value2[bindingProperty];
436
+ }
437
+ return value2;
438
+ })();
439
+ if (value) {
440
+ const where = definition.wheres?.[parameterName];
441
+ if (where && !new RegExp(where).test(value)) {
442
+ console.warn(`[hybridly:routing] Parameter [${parameterName}] does not match the required format [${where}] for route [${routeName}].`);
443
+ }
444
+ return value;
445
+ }
446
+ if (routing.defaults?.[parameterName]) {
447
+ return routing.defaults?.[parameterName];
448
+ }
449
+ }
450
+ function getRouteTransformable(routeName, routeParameters, shouldThrow) {
381
451
  const definition = getRouteDefinition(routeName);
382
452
  const parameters = routeParameters || {};
383
453
  const missing = Object.keys(parameters);
384
- const replaceParameter = (match, parameterName) => {
385
- const optional = /\?}$/.test(match);
386
- const value = (() => {
387
- const value2 = parameters[parameterName];
388
- const bindingProperty = definition.bindings?.[parameterName];
389
- if (bindingProperty && typeof value2 === "object") {
390
- return value2[bindingProperty];
391
- }
392
- return value2;
393
- })();
454
+ const replaceParameter = (match, parameterName, optional) => {
455
+ const value = getRouteParameterValue(routeName, parameterName, parameters);
394
456
  missing.splice(missing.indexOf(parameterName), 1);
395
457
  if (value) {
396
- const where = definition.wheres?.[parameterName];
397
- if (where && !new RegExp(where).test(value)) {
398
- console.warn(`[hybridly:routing] Parameter [${parameterName}] does not match the required format [${where}] for route [${routeName}].`);
399
- }
400
458
  return value;
401
459
  }
402
- if (routing.defaults?.[parameterName]) {
403
- return routing.defaults?.[parameterName];
404
- }
405
460
  if (optional) {
406
461
  return "";
407
462
  }
@@ -410,8 +465,8 @@ function getRouteTransformable(routeName, routeParameters, shouldThrow) {
410
465
  }
411
466
  throw new MissingRouteParameter(parameterName, routeName);
412
467
  };
413
- const path = definition.uri.replace(/{([^}?]+)\??}/g, replaceParameter);
414
- const domain = definition.domain?.replace(/{([^}?]+)\??}/g, replaceParameter);
468
+ const path = definition.uri.replace(/{([^}?]+)(\??)}/g, replaceParameter);
469
+ const domain = definition.domain?.replace(/{([^}?]+)(\??)}/g, replaceParameter);
415
470
  const remaining = Object.keys(parameters).filter((key) => missing.includes(key)).reduce((obj, key) => ({
416
471
  ...obj,
417
472
  [key]: parameters[key]
@@ -441,30 +496,28 @@ function getRouting() {
441
496
  }
442
497
  return routing;
443
498
  }
444
-
445
- function isCurrentFromName(name, parameters, mode = "loose") {
446
- const location = window.location;
447
- const matchee = (() => {
448
- try {
449
- return makeUrl(generateRouteFromName(name, parameters, true, false));
450
- } catch (error) {
451
- }
452
- })();
453
- if (!matchee) {
454
- return false;
455
- }
456
- if (mode === "strict") {
457
- return location.href === matchee.href;
458
- }
459
- return location.href.startsWith(matchee.href);
460
- }
461
-
462
499
  function route(name, parameters, absolute) {
463
500
  return generateRouteFromName(name, parameters, absolute);
464
501
  }
465
- function current(name, parameters, mode = "loose") {
466
- return isCurrentFromName(name, parameters, mode);
502
+
503
+ function getCurrentUrl() {
504
+ if (typeof window === "undefined") {
505
+ return getInternalRouterContext().url;
506
+ }
507
+ return window.location.toString();
508
+ }
509
+ function currentRouteMatches(name, parameters) {
510
+ const namePattern = name.replaceAll(".", "\\.").replaceAll("*", ".*");
511
+ const possibleRoutes = Object.values(getRouting().routes).filter((x) => x.method.includes("GET") && RegExp(namePattern).test(x.name)).map((x) => x.name);
512
+ const currentUrl = getCurrentUrl();
513
+ return possibleRoutes.some((routeName) => {
514
+ return urlMatchesRoute(currentUrl, routeName, parameters);
515
+ });
516
+ }
517
+ function getCurrentRouteName() {
518
+ return getNameFromUrl(getCurrentUrl());
467
519
  }
520
+
468
521
  function updateRoutingConfiguration(routing) {
469
522
  if (!routing) {
470
523
  return;
@@ -655,6 +708,8 @@ const router = {
655
708
  const method = getRouteDefinition(name).method.at(0);
656
709
  return await performHybridNavigation({ url, ...options, method });
657
710
  },
711
+ matches: (name, parameters) => currentRouteMatches(name, parameters),
712
+ current: () => getCurrentRouteName(),
658
713
  dialog: {
659
714
  close: (options) => closeDialog(options)
660
715
  },
@@ -956,7 +1011,6 @@ function can(resource, action) {
956
1011
  exports.can = can;
957
1012
  exports.constants = constants;
958
1013
  exports.createRouter = createRouter;
959
- exports.current = current;
960
1014
  exports.definePlugin = definePlugin;
961
1015
  exports.getRouterContext = getRouterContext;
962
1016
  exports.makeUrl = makeUrl;