@native-router/core 1.0.1 → 1.0.2

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 ADDED
@@ -0,0 +1,396 @@
1
+ 'use strict';
2
+
3
+ var history = require('history');
4
+ var pathToRegexp = require('path-to-regexp');
5
+ var util = require('./util.cjs');
6
+
7
+ /* eslint-disable max-classes-per-file */
8
+
9
+ class NativeRouterError extends Error {}
10
+ class NotFoundError extends NativeRouterError {
11
+ constructor(pathname) {
12
+ super(`Can't find the path: ${pathname}`);
13
+ }
14
+ }
15
+
16
+ /**
17
+ * Create a router instance.
18
+ * @group Methods
19
+ * @category Router
20
+ * @param routes routes config
21
+ * @param history {@link https://www.npmjs.com/package/history history} instance
22
+ * @param resolveView a callback to resolve view. see {@link defaultResolveView}
23
+ * @param options options
24
+ * @returns a router instance
25
+ */
26
+ function create(routes, history, resolveView, options) {
27
+ const [currentGuard, cancelAll] = util.createCurrentGuard();
28
+ const {
29
+ index,
30
+ locationStack
31
+ } = getHistoryState({
32
+ history: history
33
+ });
34
+ const viewStack = new Array(locationStack.length).fill(null);
35
+ if (options?.currentView) {
36
+ viewStack[index] = options.currentView;
37
+ }
38
+ return {
39
+ routes: Array.isArray(routes) ? routes : [routes],
40
+ resolveView,
41
+ history: history,
42
+ locationStack,
43
+ viewStack,
44
+ currentGuard,
45
+ cancelAll,
46
+ errorHandler: util.reject,
47
+ ...options,
48
+ baseUrl: options?.baseUrl || ''
49
+ };
50
+ }
51
+ function setOptions(router, options) {
52
+ return Object.assign(router, options);
53
+ }
54
+ function getLocation({
55
+ history
56
+ }) {
57
+ const state = history.location.state || {};
58
+ return {
59
+ ...history.location,
60
+ state: state.state
61
+ };
62
+ }
63
+ function getHistoryState(router) {
64
+ const {
65
+ location
66
+ } = router.history;
67
+ const state = location.state || {};
68
+ return {
69
+ index: state.index || 0,
70
+ locationStack: state.locationStack || [getLocation(router)]
71
+ };
72
+ }
73
+ function getCurrentView(router) {
74
+ return router.viewStack[getHistoryState(router).index];
75
+ }
76
+
77
+ /**
78
+ * Match a path.
79
+ * @group Methods
80
+ * @category Router
81
+ * @param router router instance
82
+ * @param pathname the pathname
83
+ * @returns the matched result
84
+ */
85
+ function match(router, pathname) {
86
+ function matchRoutes(routes, baseUrl,
87
+ // eslint-disable-next-line @typescript-eslint/no-shadow
88
+ pathname) {
89
+ for (let i = 0; i < routes.length; i++) {
90
+ const route = routes[i];
91
+ const end = !route.children;
92
+ const matched = route.path ? pathToRegexp.match(route.path, {
93
+ strict: true,
94
+ sensitive: true,
95
+ decode: typeof decodeURIComponent === 'function' ? decodeURIComponent : undefined,
96
+ end
97
+ })(pathname) : {
98
+ path: '',
99
+ index: 0,
100
+ params: {}
101
+ };
102
+ if (matched) {
103
+ const result = {
104
+ route,
105
+ ...matched
106
+ };
107
+ if (end) return [result];
108
+ const children = matchRoutes(route.children, `${baseUrl}${route.path || ''}`, pathname.slice(matched.path.length));
109
+ if (children) return [result, ...children];
110
+ return undefined;
111
+ }
112
+ }
113
+ return undefined;
114
+ }
115
+ return matchRoutes(router.routes, router.baseUrl, pathname.slice(router.baseUrl.length));
116
+ }
117
+
118
+ /**
119
+ * Path to Location.
120
+ * @group Methods
121
+ * @category Router
122
+ * @param router router instance
123
+ * @param to path string
124
+ * @param state the state of location
125
+ * @returns location
126
+ */
127
+ function toLocation(router, to, state) {
128
+ const {
129
+ baseUrl
130
+ } = router;
131
+ return {
132
+ pathname: '',
133
+ search: '',
134
+ hash: '',
135
+ ...history.parsePath(baseUrl + to),
136
+ state
137
+ };
138
+ }
139
+
140
+ /**
141
+ * Resolve a location.
142
+ * @group Methods
143
+ * @category Router
144
+ * @param router router instance
145
+ * @param location history instance
146
+ * @returns resolve task(a promise)
147
+ */
148
+ function resolve(router, location) {
149
+ const matched = match(router, location.pathname);
150
+ const {
151
+ resolveView,
152
+ errorHandler
153
+ } = router;
154
+ return (matched ? resolveView(matched, {
155
+ router,
156
+ location
157
+ }) : Promise.reject(new NotFoundError(location.pathname))).catch(errorHandler);
158
+ }
159
+
160
+ /**
161
+ * Resolve a path.
162
+ * @group Methods
163
+ * @category Router
164
+ * @param router router instance
165
+ * @param to the path
166
+ * @param state state of the path location
167
+ * @returns resolve task(a promise)
168
+ */
169
+ function resolveTo(router, to, state) {
170
+ const location = toLocation(router, to, state);
171
+ return resolve(router, location);
172
+ }
173
+
174
+ /**
175
+ * Commit the resolve task and push history.
176
+ * @group Methods
177
+ * @category Router
178
+ * @param router router instance
179
+ * @param resolvePromise resolve task(a promise)
180
+ * @param location the location to resolved
181
+ */
182
+ function commit(router, resolvePromise, location) {
183
+ const {
184
+ history
185
+ } = router;
186
+ const nextIndex = getHistoryState(router).index + 1;
187
+ return commitBase(router, resolvePromise, location, resolvedView => {
188
+ router.locationStack = [...router.locationStack.slice(0, nextIndex), location];
189
+ router.viewStack = [...router.viewStack.slice(0, nextIndex), resolvedView];
190
+ history.push(location, {
191
+ index: nextIndex,
192
+ locationStack: router.locationStack,
193
+ state: location.state
194
+ });
195
+ });
196
+ }
197
+
198
+ /**
199
+ * Commit the resolve task and replace history.
200
+ * @group Methods
201
+ * @category Router
202
+ * @param router router instance
203
+ * @param resolvePromise resolve task(a promise)
204
+ * @param location the location to resolved
205
+ */
206
+ function commitReplace(router, resolvePromise, location) {
207
+ const {
208
+ history
209
+ } = router;
210
+ const {
211
+ index
212
+ } = getHistoryState(router);
213
+ return commitBase(router, resolvePromise, location, resolvedView => {
214
+ router.locationStack[index] = location;
215
+ router.viewStack[index] = resolvedView;
216
+ history.replace(location, {
217
+ index,
218
+ locationStack: router.locationStack,
219
+ state: location.state
220
+ });
221
+ });
222
+ }
223
+ function commitBase(router, resolvePromise, location, onResolved) {
224
+ const {
225
+ currentGuard,
226
+ onLoadingChange = util.noop
227
+ } = router;
228
+ if (router.resolving) {
229
+ // Cancel current resolve
230
+ onLoadingChange();
231
+ }
232
+ router.resolving = location;
233
+ onLoadingChange('pending');
234
+ return currentGuard(resolvePromise).then(onResolved)
235
+ // eslint-disable-next-line no-void
236
+ .then(() => void onLoadingChange('resolved')).catch(e => {
237
+ onLoadingChange('rejected');
238
+ throw e;
239
+ });
240
+ }
241
+
242
+ /**
243
+ * Navigate to a new path.
244
+ * @group Methods
245
+ * @category Router
246
+ * @param router router instance
247
+ * @param to path string
248
+ * @param state location state
249
+ */
250
+ function navigate(router, to, state) {
251
+ const location = toLocation(router, to, state);
252
+ const viewPromise = resolve(router, location);
253
+ return commit(router, viewPromise, location);
254
+ }
255
+
256
+ /**
257
+ * Refresh the page.
258
+ * @group Methods
259
+ * @category Router
260
+ * @param router router instance
261
+ */
262
+ function refresh(router) {
263
+ const location = getLocation(router);
264
+ const viewPromise = resolve(router, location);
265
+ return commitReplace(router, viewPromise, location);
266
+ }
267
+
268
+ /**
269
+ * Navigate in history stack.
270
+ * @group Methods
271
+ * @category Router
272
+ * @param router router instance
273
+ * @param delta history stack index
274
+ */
275
+ function go(router, delta) {
276
+ router.history.go(delta);
277
+ }
278
+
279
+ /**
280
+ * Forward in history stack.
281
+ * @group Methods
282
+ * @category Router
283
+ * @param router router instance
284
+ */
285
+ function forward(router) {
286
+ router.history.forward();
287
+ }
288
+
289
+ /**
290
+ * Back in history stack.
291
+ * @group Methods
292
+ * @category Router
293
+ * @param router router instance
294
+ */
295
+ function back(router) {
296
+ router.history.back();
297
+ }
298
+
299
+ /**
300
+ * Create href of a route path. For {@link Link Link Component} hover url preview.
301
+ * @group Methods
302
+ * @category Router
303
+ * @param router router instance
304
+ * @param to route path
305
+ * @returns href
306
+ */
307
+ function createHref({
308
+ baseUrl,
309
+ history
310
+ }, to) {
311
+ return baseUrl + history.createHref(to);
312
+ }
313
+
314
+ /**
315
+ * Cancel the current navigate.
316
+ * @group Methods
317
+ * @category Router
318
+ * @param router router instance
319
+ */
320
+ function cancel({
321
+ cancelAll,
322
+ onLoadingChange = util.noop
323
+ }) {
324
+ cancelAll();
325
+ onLoadingChange();
326
+ }
327
+ function initHistoryStack(router) {
328
+ const {
329
+ history: history$1
330
+ } = router;
331
+ const {
332
+ locationStack
333
+ } = getHistoryState(router);
334
+ return Promise.all(locationStack.map(l => resolve(router, l))).then(views => {
335
+ router.viewStack = views;
336
+ history$1.replace(history.createPath(history$1.location), history$1.location.state);
337
+ });
338
+ }
339
+
340
+ /**
341
+ * Listen the history change.
342
+ * @group Methods
343
+ * @category Router
344
+ * @param router router instance
345
+ * @param onViewChange a callback function will be call when view changed
346
+ * @returns unlisten - A function that may be used to stop listening
347
+ */
348
+ function listen(router, onViewChange) {
349
+ const {
350
+ history: history$1
351
+ } = router;
352
+ const rmListener = history$1.listen(({
353
+ action,
354
+ location
355
+ }) => {
356
+ cancel(router);
357
+ const state = location.state;
358
+ const index = state?.index || 0;
359
+ const view = router.viewStack[index];
360
+ onViewChange(view);
361
+ if (!view) refresh(router);
362
+ if (action === 'POP') {
363
+ history$1.replace(history.createPath(history$1.location), {
364
+ ...state,
365
+ locationStack: router.locationStack
366
+ });
367
+ }
368
+ });
369
+ history$1.replace(history.createPath(history$1.location), history$1.location.state);
370
+ return () => {
371
+ cancel(router);
372
+ rmListener();
373
+ };
374
+ }
375
+
376
+ exports.NativeRouterError = NativeRouterError;
377
+ exports.NotFoundError = NotFoundError;
378
+ exports.back = back;
379
+ exports.cancel = cancel;
380
+ exports.commit = commit;
381
+ exports.commitReplace = commitReplace;
382
+ exports.create = create;
383
+ exports.createHref = createHref;
384
+ exports.forward = forward;
385
+ exports.getCurrentView = getCurrentView;
386
+ exports.getLocation = getLocation;
387
+ exports.go = go;
388
+ exports.initHistoryStack = initHistoryStack;
389
+ exports.listen = listen;
390
+ exports.match = match;
391
+ exports.navigate = navigate;
392
+ exports.refresh = refresh;
393
+ exports.resolve = resolve;
394
+ exports.resolveTo = resolveTo;
395
+ exports.setOptions = setOptions;
396
+ exports.toLocation = toLocation;
package/dist/util.cjs ADDED
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ let i = 1;
4
+ function uniqId() {
5
+ return i++;
6
+ }
7
+ function noop() {}
8
+ const resolve = /* @__PURE__ */Promise.resolve.bind(Promise);
9
+ const reject = /* @__PURE__ */Promise.reject.bind(Promise);
10
+ function cancelPromise() {
11
+ return new Promise(noop);
12
+ }
13
+ function createCurrentGuard() {
14
+ let current;
15
+ return [function currentGuard(promise) {
16
+ const cur = uniqId();
17
+ current = cur;
18
+ return promise.then(result => current === cur ? result : cancelPromise()).catch(err => current === cur ? Promise.reject(err) : cancelPromise());
19
+ }, function cancel() {
20
+ current = undefined;
21
+ }];
22
+ }
23
+ function splitProps(obj, keys) {
24
+ const picked = {};
25
+ const rest = {
26
+ ...obj
27
+ };
28
+ keys.forEach(key => {
29
+ picked[key] = rest[key];
30
+ delete rest[key];
31
+ });
32
+ return [picked, rest];
33
+ }
34
+ function isString(maybeString) {
35
+ return typeof maybeString === 'string';
36
+ }
37
+
38
+ exports.cancelPromise = cancelPromise;
39
+ exports.createCurrentGuard = createCurrentGuard;
40
+ exports.isString = isString;
41
+ exports.noop = noop;
42
+ exports.reject = reject;
43
+ exports.resolve = resolve;
44
+ exports.splitProps = splitProps;
45
+ exports.uniqId = uniqId;
package/package.json CHANGED
@@ -1,22 +1,21 @@
1
1
  {
2
2
  "name": "@native-router/core",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "exports": {
5
5
  ".": {
6
6
  "import": "./dist/index.mjs",
7
+ "require": "./dist/index.cjs",
7
8
  "types": "./dist/types/index.d.ts"
8
9
  },
9
10
  "./util": {
10
11
  "import": "./dist/util.mjs",
12
+ "require": "./dist/util.cjs",
11
13
  "types": "./dist/types/util.d.ts"
12
14
  }
13
15
  },
14
16
  "types": "./dist/types/index.d.ts",
15
17
  "keywords": [
16
- "react",
17
18
  "router",
18
- "react router",
19
- "react-router",
20
19
  "async",
21
20
  "tiny",
22
21
  "data-fetching",