inspector-ng 0.0.7 → 0.0.9
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/README.md +15 -28
- package/esm2022/lib/checkpoint-search.mjs +50 -0
- package/esm2022/lib/checkpoints.mjs +254 -198
- package/esm2022/lib/inspector.component.mjs +199 -20
- package/esm2022/public-api.mjs +2 -2
- package/fesm2022/inspector-ng.mjs +502 -218
- package/fesm2022/inspector-ng.mjs.map +1 -1
- package/lib/checkpoint-search.d.ts +3 -0
- package/lib/checkpoints.d.ts +46 -46
- package/lib/inspector.component.d.ts +29 -8
- package/package.json +2 -1
- package/public-api.d.ts +1 -1
package/README.md
CHANGED
|
@@ -11,9 +11,11 @@ Inspired by [ibelick](https://github.com/ibelick)'s original design.
|
|
|
11
11
|
## Installation
|
|
12
12
|
|
|
13
13
|
```bash
|
|
14
|
-
npm install inspector-ng
|
|
14
|
+
npm install inspector-ng@0.0.8 @ngrx/store@^17.2.0
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
For a complete new-project walkthrough with copy-paste Store, Router, Redux DevTools, state, local-package, and troubleshooting examples, see the [setup guide](https://github.com/destx0/inspector/blob/main/SETUP_GUIDE.md).
|
|
18
|
+
|
|
17
19
|
## Getting Started
|
|
18
20
|
|
|
19
21
|
### Step 1: Import the component
|
|
@@ -58,43 +60,25 @@ That's it. Press **`M`** in your browser to open the inspector toolbar. No furth
|
|
|
58
60
|
|
|
59
61
|
### Developer checkpoints
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
Add `@ngrx/store` and provide a single root Store before `provideInspectorCheckpoints()`:
|
|
62
64
|
|
|
63
65
|
```ts
|
|
64
66
|
import { ApplicationConfig } from '@angular/core';
|
|
65
|
-
import {
|
|
66
|
-
import {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
provideInspectorCheckpoints,
|
|
70
|
-
} from 'inspector-ng';
|
|
67
|
+
import { provideRouter } from '@angular/router';
|
|
68
|
+
import { provideStore } from '@ngrx/store';
|
|
69
|
+
import { provideInspectorCheckpoints } from 'inspector-ng';
|
|
70
|
+
import { routes } from './app.routes';
|
|
71
71
|
|
|
72
72
|
export const appConfig: ApplicationConfig = {
|
|
73
|
-
providers: [provideInspectorCheckpoints()],
|
|
73
|
+
providers: [provideRouter(routes), provideStore(), provideInspectorCheckpoints()],
|
|
74
74
|
};
|
|
75
75
|
```
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
const application = new BehaviorSubject({ customerName: '', amount: 0 });
|
|
81
|
-
const unregister = checkpointRegistry.register(
|
|
82
|
-
createBehaviorSubjectCheckpointAdapter('workflow:application', application),
|
|
83
|
-
);
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Open the inspector and use the checkpoint button to save, restore, rename, or delete snapshots. Checkpoints use `localStorage`; when the browser quota is reached, the oldest checkpoint is removed to make room. Do not register sensitive values.
|
|
87
|
-
|
|
88
|
-
For Native Federation, the shell owns `provideInspectorCheckpoints()`. Remotes receive the shell's `InspectorCheckpointRegistry` and register namespaced adapters such as `workflow:application`. The shell should register a remote loader for each scope so remotes are loaded before state is restored:
|
|
77
|
+
Use the compact toolbar button to save the current JSON-serializable NgRx root state immediately. Use `Ctrl/Cmd+Shift+P` to open the fuzzy checkpoint finder. `F2` renames the selected record and `Delete` opens inline confirmation.
|
|
89
78
|
|
|
90
|
-
|
|
91
|
-
checkpointRegistry.registerRemoteScope('workflow', async () => {
|
|
92
|
-
const remote = await loadRemoteModule('workflow', './CheckpointAdapters');
|
|
93
|
-
remote.registerInspectorCheckpointAdapters(checkpointRegistry);
|
|
94
|
-
});
|
|
95
|
-
```
|
|
79
|
+
Records are stored per origin in IndexedDB database `inspector-ng`, object store `checkpoints`. This needs no browser permission prompt and does not map to a visible or fixed OS path. Nothing is evicted automatically. Existing `inspector-checkpoints-v1` localStorage records are deliberately ignored.
|
|
96
80
|
|
|
97
|
-
|
|
81
|
+
A checkpoint contains the root Store value and current route. Restore dispatches `[Inspector Checkpoints] Restore`, then navigates through Angular Router to the saved route, so NgRx Store DevTools records the state change normally. It does not restore action history, component-local state, HTTP activity, or backend state. Native Redux DevTools Import/Export files remain separate and cannot be searched from the Inspector command bar.
|
|
98
82
|
|
|
99
83
|
### Inputs
|
|
100
84
|
|
|
@@ -129,6 +113,7 @@ Repeated remote adapter registration is safe, so a bridge may run before every r
|
|
|
129
113
|
| `Ctrl/Cmd + Z` | Undo last guide change |
|
|
130
114
|
| `Ctrl/Cmd + Shift + Z` | Redo guide change |
|
|
131
115
|
| `Backspace` / `Delete` | Delete the selected guide |
|
|
116
|
+
| `Ctrl/Cmd + Shift + P` | Search and restore checkpoints when configured |
|
|
132
117
|
|
|
133
118
|
## Features
|
|
134
119
|
|
|
@@ -148,6 +133,8 @@ Repeated remote adapter registration is safe, so a bridge may run before every r
|
|
|
148
133
|
|---|---|
|
|
149
134
|
| `@angular/core` | `^17.3.0` |
|
|
150
135
|
| `@angular/common` | `^17.3.0` |
|
|
136
|
+
| `@angular/router` | `^17.3.0` |
|
|
137
|
+
| `@ngrx/store` | `^17.2.0` (peer dependency used only for checkpoints) |
|
|
151
138
|
|
|
152
139
|
Built as a standalone component with signal-based reactivity and `OnPush` change detection.
|
|
153
140
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export function fuzzyCheckpoints(checkpoints, query) {
|
|
2
|
+
const normalizedQuery = normalize(query.trim());
|
|
3
|
+
if (!normalizedQuery)
|
|
4
|
+
return [...checkpoints].sort(newestFirst);
|
|
5
|
+
return checkpoints
|
|
6
|
+
.map((checkpoint) => {
|
|
7
|
+
const score = fuzzyScore(checkpoint.name, normalizedQuery);
|
|
8
|
+
return score === null ? null : { checkpoint, score };
|
|
9
|
+
})
|
|
10
|
+
.filter((item) => item !== null)
|
|
11
|
+
.sort((a, b) => b.score - a.score || newestFirst(a.checkpoint, b.checkpoint))
|
|
12
|
+
.map(({ checkpoint }) => checkpoint);
|
|
13
|
+
}
|
|
14
|
+
export function fuzzyScore(value, normalizedQuery) {
|
|
15
|
+
const candidate = normalize(value);
|
|
16
|
+
if (candidate === normalizedQuery)
|
|
17
|
+
return 10_000;
|
|
18
|
+
if (candidate.startsWith(normalizedQuery))
|
|
19
|
+
return 8_000 - candidate.length;
|
|
20
|
+
const substringIndex = candidate.indexOf(normalizedQuery);
|
|
21
|
+
if (substringIndex >= 0)
|
|
22
|
+
return 6_000 - substringIndex * 10 - candidate.length;
|
|
23
|
+
let queryIndex = 0;
|
|
24
|
+
let firstIndex = -1;
|
|
25
|
+
let lastIndex = -1;
|
|
26
|
+
let gapPenalty = 0;
|
|
27
|
+
for (let index = 0; index < candidate.length && queryIndex < normalizedQuery.length; index += 1) {
|
|
28
|
+
if (candidate[index] !== normalizedQuery[queryIndex])
|
|
29
|
+
continue;
|
|
30
|
+
if (firstIndex < 0)
|
|
31
|
+
firstIndex = index;
|
|
32
|
+
if (lastIndex >= 0)
|
|
33
|
+
gapPenalty += index - lastIndex - 1;
|
|
34
|
+
lastIndex = index;
|
|
35
|
+
queryIndex += 1;
|
|
36
|
+
}
|
|
37
|
+
if (queryIndex !== normalizedQuery.length)
|
|
38
|
+
return null;
|
|
39
|
+
return 4_000 - firstIndex * 10 - gapPenalty * 20 - candidate.length;
|
|
40
|
+
}
|
|
41
|
+
function normalize(value) {
|
|
42
|
+
return value
|
|
43
|
+
.normalize('NFKD')
|
|
44
|
+
.replace(/[\u0300-\u036f]/g, '')
|
|
45
|
+
.toLocaleLowerCase();
|
|
46
|
+
}
|
|
47
|
+
function newestFirst(a, b) {
|
|
48
|
+
return b.createdAt.localeCompare(a.createdAt) || b.id.localeCompare(a.id);
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hlY2twb2ludC1zZWFyY2guanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9pbnNwZWN0b3Itbmcvc3JjL2xpYi9jaGVja3BvaW50LXNlYXJjaC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFPQSxNQUFNLFVBQVUsZ0JBQWdCLENBQzlCLFdBQXdDLEVBQ3hDLEtBQWE7SUFFYixNQUFNLGVBQWUsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDaEQsSUFBSSxDQUFDLGVBQWU7UUFBRSxPQUFPLENBQUMsR0FBRyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFFaEUsT0FBTyxXQUFXO1NBQ2YsR0FBRyxDQUFDLENBQUMsVUFBVSxFQUEyQixFQUFFO1FBQzNDLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBQzNELE9BQU8sS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUN2RCxDQUFDLENBQUM7U0FDRCxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQTRCLEVBQUUsQ0FBQyxJQUFJLEtBQUssSUFBSSxDQUFDO1NBQ3pELElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEtBQUssSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUM7U0FDNUUsR0FBRyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsRUFBRSxFQUFFLENBQUMsVUFBVSxDQUFDLENBQUM7QUFDekMsQ0FBQztBQUVELE1BQU0sVUFBVSxVQUFVLENBQUMsS0FBYSxFQUFFLGVBQXVCO0lBQy9ELE1BQU0sU0FBUyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNuQyxJQUFJLFNBQVMsS0FBSyxlQUFlO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDakQsSUFBSSxTQUFTLENBQUMsVUFBVSxDQUFDLGVBQWUsQ0FBQztRQUFFLE9BQU8sS0FBSyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUM7SUFFM0UsTUFBTSxjQUFjLEdBQUcsU0FBUyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQztJQUMxRCxJQUFJLGNBQWMsSUFBSSxDQUFDO1FBQUUsT0FBTyxLQUFLLEdBQUcsY0FBYyxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO0lBRS9FLElBQUksVUFBVSxHQUFHLENBQUMsQ0FBQztJQUNuQixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwQixJQUFJLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNuQixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUM7SUFDbkIsS0FBSyxJQUFJLEtBQUssR0FBRyxDQUFDLEVBQUUsS0FBSyxHQUFHLFNBQVMsQ0FBQyxNQUFNLElBQUksVUFBVSxHQUFHLGVBQWUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ2hHLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxLQUFLLGVBQWUsQ0FBQyxVQUFVLENBQUM7WUFBRSxTQUFTO1FBQy9ELElBQUksVUFBVSxHQUFHLENBQUM7WUFBRSxVQUFVLEdBQUcsS0FBSyxDQUFDO1FBQ3ZDLElBQUksU0FBUyxJQUFJLENBQUM7WUFBRSxVQUFVLElBQUksS0FBSyxHQUFHLFNBQVMsR0FBRyxDQUFDLENBQUM7UUFDeEQsU0FBUyxHQUFHLEtBQUssQ0FBQztRQUNsQixVQUFVLElBQUksQ0FBQyxDQUFDO0lBQ2xCLENBQUM7SUFDRCxJQUFJLFVBQVUsS0FBSyxlQUFlLENBQUMsTUFBTTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3ZELE9BQU8sS0FBSyxHQUFHLFVBQVUsR0FBRyxFQUFFLEdBQUcsVUFBVSxHQUFHLEVBQUUsR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO0FBQ3RFLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxLQUFhO0lBQzlCLE9BQU8sS0FBSztTQUNULFNBQVMsQ0FBQyxNQUFNLENBQUM7U0FDakIsT0FBTyxDQUFDLGtCQUFrQixFQUFFLEVBQUUsQ0FBQztTQUMvQixpQkFBaUIsRUFBRSxDQUFDO0FBQ3pCLENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxDQUE0QixFQUFFLENBQTRCO0lBQzdFLE9BQU8sQ0FBQyxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUM1RSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5zcGVjdG9yQ2hlY2twb2ludFJlY29yZCB9IGZyb20gJy4vY2hlY2twb2ludHMnO1xuXG5pbnRlcmZhY2UgUmFua2VkQ2hlY2twb2ludCB7XG4gIGNoZWNrcG9pbnQ6IEluc3BlY3RvckNoZWNrcG9pbnRSZWNvcmQ7XG4gIHNjb3JlOiBudW1iZXI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmdXp6eUNoZWNrcG9pbnRzKFxuICBjaGVja3BvaW50czogSW5zcGVjdG9yQ2hlY2twb2ludFJlY29yZFtdLFxuICBxdWVyeTogc3RyaW5nLFxuKTogSW5zcGVjdG9yQ2hlY2twb2ludFJlY29yZFtdIHtcbiAgY29uc3Qgbm9ybWFsaXplZFF1ZXJ5ID0gbm9ybWFsaXplKHF1ZXJ5LnRyaW0oKSk7XG4gIGlmICghbm9ybWFsaXplZFF1ZXJ5KSByZXR1cm4gWy4uLmNoZWNrcG9pbnRzXS5zb3J0KG5ld2VzdEZpcnN0KTtcblxuICByZXR1cm4gY2hlY2twb2ludHNcbiAgICAubWFwKChjaGVja3BvaW50KTogUmFua2VkQ2hlY2twb2ludCB8IG51bGwgPT4ge1xuICAgICAgY29uc3Qgc2NvcmUgPSBmdXp6eVNjb3JlKGNoZWNrcG9pbnQubmFtZSwgbm9ybWFsaXplZFF1ZXJ5KTtcbiAgICAgIHJldHVybiBzY29yZSA9PT0gbnVsbCA/IG51bGwgOiB7IGNoZWNrcG9pbnQsIHNjb3JlIH07XG4gICAgfSlcbiAgICAuZmlsdGVyKChpdGVtKTogaXRlbSBpcyBSYW5rZWRDaGVja3BvaW50ID0+IGl0ZW0gIT09IG51bGwpXG4gICAgLnNvcnQoKGEsIGIpID0+IGIuc2NvcmUgLSBhLnNjb3JlIHx8IG5ld2VzdEZpcnN0KGEuY2hlY2twb2ludCwgYi5jaGVja3BvaW50KSlcbiAgICAubWFwKCh7IGNoZWNrcG9pbnQgfSkgPT4gY2hlY2twb2ludCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmdXp6eVNjb3JlKHZhbHVlOiBzdHJpbmcsIG5vcm1hbGl6ZWRRdWVyeTogc3RyaW5nKTogbnVtYmVyIHwgbnVsbCB7XG4gIGNvbnN0IGNhbmRpZGF0ZSA9IG5vcm1hbGl6ZSh2YWx1ZSk7XG4gIGlmIChjYW5kaWRhdGUgPT09IG5vcm1hbGl6ZWRRdWVyeSkgcmV0dXJuIDEwXzAwMDtcbiAgaWYgKGNhbmRpZGF0ZS5zdGFydHNXaXRoKG5vcm1hbGl6ZWRRdWVyeSkpIHJldHVybiA4XzAwMCAtIGNhbmRpZGF0ZS5sZW5ndGg7XG5cbiAgY29uc3Qgc3Vic3RyaW5nSW5kZXggPSBjYW5kaWRhdGUuaW5kZXhPZihub3JtYWxpemVkUXVlcnkpO1xuICBpZiAoc3Vic3RyaW5nSW5kZXggPj0gMCkgcmV0dXJuIDZfMDAwIC0gc3Vic3RyaW5nSW5kZXggKiAxMCAtIGNhbmRpZGF0ZS5sZW5ndGg7XG5cbiAgbGV0IHF1ZXJ5SW5kZXggPSAwO1xuICBsZXQgZmlyc3RJbmRleCA9IC0xO1xuICBsZXQgbGFzdEluZGV4ID0gLTE7XG4gIGxldCBnYXBQZW5hbHR5ID0gMDtcbiAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGNhbmRpZGF0ZS5sZW5ndGggJiYgcXVlcnlJbmRleCA8IG5vcm1hbGl6ZWRRdWVyeS5sZW5ndGg7IGluZGV4ICs9IDEpIHtcbiAgICBpZiAoY2FuZGlkYXRlW2luZGV4XSAhPT0gbm9ybWFsaXplZFF1ZXJ5W3F1ZXJ5SW5kZXhdKSBjb250aW51ZTtcbiAgICBpZiAoZmlyc3RJbmRleCA8IDApIGZpcnN0SW5kZXggPSBpbmRleDtcbiAgICBpZiAobGFzdEluZGV4ID49IDApIGdhcFBlbmFsdHkgKz0gaW5kZXggLSBsYXN0SW5kZXggLSAxO1xuICAgIGxhc3RJbmRleCA9IGluZGV4O1xuICAgIHF1ZXJ5SW5kZXggKz0gMTtcbiAgfVxuICBpZiAocXVlcnlJbmRleCAhPT0gbm9ybWFsaXplZFF1ZXJ5Lmxlbmd0aCkgcmV0dXJuIG51bGw7XG4gIHJldHVybiA0XzAwMCAtIGZpcnN0SW5kZXggKiAxMCAtIGdhcFBlbmFsdHkgKiAyMCAtIGNhbmRpZGF0ZS5sZW5ndGg7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZSh2YWx1ZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIHZhbHVlXG4gICAgLm5vcm1hbGl6ZSgnTkZLRCcpXG4gICAgLnJlcGxhY2UoL1tcXHUwMzAwLVxcdTAzNmZdL2csICcnKVxuICAgIC50b0xvY2FsZUxvd2VyQ2FzZSgpO1xufVxuXG5mdW5jdGlvbiBuZXdlc3RGaXJzdChhOiBJbnNwZWN0b3JDaGVja3BvaW50UmVjb3JkLCBiOiBJbnNwZWN0b3JDaGVja3BvaW50UmVjb3JkKTogbnVtYmVyIHtcbiAgcmV0dXJuIGIuY3JlYXRlZEF0LmxvY2FsZUNvbXBhcmUoYS5jcmVhdGVkQXQpIHx8IGIuaWQubG9jYWxlQ29tcGFyZShhLmlkKTtcbn1cbiJdfQ==
|