@real-router/memory-plugin 0.1.1 → 0.1.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.
@@ -17,7 +17,7 @@ declare module "@real-router/core" {
17
17
  canGoBack: () => boolean;
18
18
  canGoForward: () => boolean;
19
19
  }
20
- }
20
+ } //# sourceMappingURL=index.d.ts.map
21
21
  //#endregion
22
22
  export { type MemoryPluginOptions, memoryPluginFactory };
23
23
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;UAEiB,mBAAA;EACf,gBAAA;AAAA;;;iBCIc,mBAAA,CACd,OAAA,GAAS,mBAAA,GACR,aAAA;;;;YCJS,MAAA;IACR,IAAA;IACA,OAAA;IACA,EAAA,GAAK,KAAA;IACL,SAAA;IACA,YAAA;EAAA;AAAA"}
@@ -17,7 +17,7 @@ declare module "@real-router/core" {
17
17
  canGoBack: () => boolean;
18
18
  canGoForward: () => boolean;
19
19
  }
20
- }
20
+ } //# sourceMappingURL=index.d.ts.map
21
21
  //#endregion
22
22
  export { type MemoryPluginOptions, memoryPluginFactory };
23
23
  //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../src/types.ts","../../src/factory.ts","../../src/index.ts"],"mappings":";;;UAEiB,mBAAA;EACf,gBAAA;AAAA;;;iBCIc,mBAAA,CACd,OAAA,GAAS,mBAAA,GACR,aAAA;;;;YCJS,MAAA;IACR,IAAA;IACA,OAAA;IACA,EAAA,GAAK,KAAA;IACL,SAAA;IACA,YAAA;EAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@real-router/memory-plugin",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "type": "commonjs",
5
5
  "description": "In-memory history engine for Real-Router — non-browser environments and benchmarks",
6
6
  "main": "./dist/cjs/index.js",
@@ -8,7 +8,6 @@
8
8
  "types": "./dist/esm/index.d.mts",
9
9
  "exports": {
10
10
  ".": {
11
- "development": "./src/index.ts",
12
11
  "types": {
13
12
  "import": "./dist/esm/index.d.mts",
14
13
  "require": "./dist/cjs/index.d.ts"
@@ -18,7 +17,8 @@
18
17
  }
19
18
  },
20
19
  "files": [
21
- "dist"
20
+ "dist",
21
+ "src"
22
22
  ],
23
23
  "repository": {
24
24
  "type": "git",
@@ -44,7 +44,7 @@
44
44
  "homepage": "https://github.com/greydragon888/real-router",
45
45
  "sideEffects": false,
46
46
  "dependencies": {
47
- "@real-router/core": "^0.45.1"
47
+ "@real-router/core": "^0.46.0"
48
48
  },
49
49
  "scripts": {
50
50
  "test": "vitest",
@@ -52,7 +52,7 @@
52
52
  "build": "tsdown --config-loader unrun",
53
53
  "type-check": "tsc --noEmit",
54
54
  "lint": "eslint --cache --ext .ts src/ tests/ --fix --max-warnings 0",
55
- "lint:package": "bash ../../scripts/publint-filter.sh",
55
+ "lint:package": "publint",
56
56
  "lint:types": "attw --pack .",
57
57
  "build:dist-only": "tsdown --config-loader unrun"
58
58
  }
package/src/factory.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { getPluginApi } from "@real-router/core/api";
2
+
3
+ import { MemoryPlugin } from "./plugin";
4
+
5
+ import type { MemoryPluginOptions } from "./types";
6
+ import type { PluginFactory, Plugin, Router } from "@real-router/core";
7
+
8
+ export function memoryPluginFactory(
9
+ options: MemoryPluginOptions = {},
10
+ ): PluginFactory {
11
+ if (
12
+ options.maxHistoryLength !== undefined &&
13
+ (typeof options.maxHistoryLength !== "number" ||
14
+ options.maxHistoryLength < 0)
15
+ ) {
16
+ throw new TypeError(
17
+ `[memory-plugin] Invalid maxHistoryLength: expected non-negative number, got ${String(options.maxHistoryLength)}.`,
18
+ );
19
+ }
20
+
21
+ const frozenOptions: MemoryPluginOptions = Object.freeze({ ...options });
22
+
23
+ return (router): Plugin => {
24
+ const api = getPluginApi(router);
25
+ const plugin = new MemoryPlugin(router as Router, api, frozenOptions);
26
+
27
+ return plugin.getPlugin();
28
+ };
29
+ }
package/src/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export { memoryPluginFactory } from "./factory";
2
+
3
+ export type { MemoryPluginOptions } from "./types";
4
+
5
+ declare module "@real-router/core" {
6
+ interface Router {
7
+ back: () => void;
8
+ forward: () => void;
9
+ go: (delta: number) => void;
10
+ canGoBack: () => boolean;
11
+ canGoForward: () => boolean;
12
+ }
13
+ }
package/src/plugin.ts ADDED
@@ -0,0 +1,128 @@
1
+ import type { HistoryEntry, MemoryPluginOptions } from "./types";
2
+ import type {
3
+ NavigationOptions,
4
+ Plugin,
5
+ Router,
6
+ State,
7
+ } from "@real-router/core";
8
+ import type { PluginApi } from "@real-router/core/api";
9
+
10
+ const DEFAULT_MAX_HISTORY = 1000;
11
+
12
+ export class MemoryPlugin {
13
+ readonly #router: Router;
14
+ readonly #maxHistory: number;
15
+ readonly #entries: HistoryEntry[] = [];
16
+ readonly #removeExtensions: () => void;
17
+ #index = -1;
18
+ #navigatingFromHistory = false;
19
+ #goGeneration = 0;
20
+
21
+ constructor(router: Router, api: PluginApi, options: MemoryPluginOptions) {
22
+ this.#router = router;
23
+ this.#maxHistory = options.maxHistoryLength ?? DEFAULT_MAX_HISTORY;
24
+
25
+ this.#removeExtensions = api.extendRouter({
26
+ back: () => {
27
+ this.#go(-1);
28
+ },
29
+ forward: () => {
30
+ this.#go(1);
31
+ },
32
+ go: (delta: number) => {
33
+ this.#go(delta);
34
+ },
35
+ canGoBack: () => this.#index > 0,
36
+ canGoForward: () => this.#index < this.#entries.length - 1,
37
+ });
38
+ }
39
+
40
+ getPlugin(): Plugin {
41
+ return {
42
+ onTransitionSuccess: (
43
+ toState: State,
44
+ _fromState: State | undefined,
45
+ opts: NavigationOptions,
46
+ ) => {
47
+ if (this.#navigatingFromHistory) {
48
+ return;
49
+ }
50
+
51
+ const entry: HistoryEntry = {
52
+ name: toState.name,
53
+ params: toState.params,
54
+ path: toState.path,
55
+ };
56
+
57
+ if (opts.replace && this.#index >= 0) {
58
+ this.#entries[this.#index] = entry;
59
+ } else {
60
+ this.#entries.splice(this.#index + 1);
61
+ this.#entries.push(entry);
62
+ this.#index = this.#entries.length - 1;
63
+
64
+ if (this.#maxHistory > 0 && this.#entries.length > this.#maxHistory) {
65
+ const overflow = this.#entries.length - this.#maxHistory;
66
+
67
+ this.#entries.splice(0, overflow);
68
+ this.#index = Math.max(0, this.#index - overflow);
69
+ }
70
+ }
71
+ },
72
+
73
+ onStop: () => {
74
+ this.#clear();
75
+ },
76
+
77
+ teardown: () => {
78
+ this.#removeExtensions();
79
+ this.#clear();
80
+ },
81
+ };
82
+ }
83
+
84
+ #go(delta: number): void {
85
+ if (delta === 0) {
86
+ return;
87
+ }
88
+
89
+ const targetIndex = this.#index + delta;
90
+
91
+ if (targetIndex < 0 || targetIndex >= this.#entries.length) {
92
+ return;
93
+ }
94
+
95
+ const entry = this.#entries[targetIndex];
96
+ const currentState = this.#router.getState();
97
+
98
+ if (entry.path === currentState?.path) {
99
+ this.#index = targetIndex;
100
+
101
+ return;
102
+ }
103
+
104
+ const previousIndex = this.#index;
105
+ const generation = ++this.#goGeneration;
106
+
107
+ this.#navigatingFromHistory = true;
108
+ this.#index = targetIndex;
109
+
110
+ void this.#router
111
+ .navigate(entry.name, entry.params, { replace: true })
112
+ .catch(() => {
113
+ if (this.#goGeneration === generation) {
114
+ this.#index = previousIndex;
115
+ }
116
+ })
117
+ .finally(() => {
118
+ if (this.#goGeneration === generation) {
119
+ this.#navigatingFromHistory = false;
120
+ }
121
+ });
122
+ }
123
+
124
+ #clear(): void {
125
+ this.#entries.length = 0;
126
+ this.#index = -1;
127
+ }
128
+ }
package/src/types.ts ADDED
@@ -0,0 +1,11 @@
1
+ import type { Params } from "@real-router/core";
2
+
3
+ export interface MemoryPluginOptions {
4
+ maxHistoryLength?: number;
5
+ }
6
+
7
+ export interface HistoryEntry {
8
+ readonly name: string;
9
+ readonly params: Params;
10
+ readonly path: string;
11
+ }