driggsby 0.2.3 → 0.2.4
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/dev/host-page.js +69 -8
- package/package.json +3 -3
package/dist/dev/host-page.js
CHANGED
|
@@ -82,12 +82,56 @@ export const HOST_PAGE_JS = [
|
|
|
82
82
|
"",
|
|
83
83
|
"let appRoute = sanitizeAppRoute(window.location.hash);",
|
|
84
84
|
"",
|
|
85
|
-
"// URL writes are bounded
|
|
86
|
-
"//
|
|
87
|
-
"//
|
|
88
|
-
"
|
|
85
|
+
"// URL writes are bounded because the frame controls their rate, but",
|
|
86
|
+
"// ordinary clicking should not feel the bound — a token bucket does",
|
|
87
|
+
"// both, matching the production host: a flurry of up to 15",
|
|
88
|
+
"// navigations writes instantly, sustained clicking faster than one",
|
|
89
|
+
"// per 600ms then paces at 600ms, and a frame spamming routes drains",
|
|
90
|
+
"// the bucket and degrades to paced trailing writes that still land",
|
|
91
|
+
"// the final state. Burst (15) plus refills (one per 600ms = 50 per",
|
|
92
|
+
"// 30s) tops out at 65 writes per 30s, leaving at least ~35 of",
|
|
93
|
+
"// Safari's ~100-per-30s per-document replaceState budget for the",
|
|
94
|
+
"// host page's own writes. Keep these two constants identical to the",
|
|
95
|
+
"// production host's; nothing pins them across the two codebases.",
|
|
96
|
+
"const ROUTE_WRITE_BUCKET_CAPACITY = 15;",
|
|
97
|
+
"const ROUTE_WRITE_REFILL_MS = 600;",
|
|
98
|
+
"let routeTokens = ROUTE_WRITE_BUCKET_CAPACITY;",
|
|
99
|
+
"let routeLastRefillMs = Date.now();",
|
|
89
100
|
"let routeWriteTimer = null;",
|
|
90
101
|
"",
|
|
102
|
+
"function refillRouteTokens() {",
|
|
103
|
+
" const now = Date.now();",
|
|
104
|
+
" // A backward clock step would otherwise strand the refill mark in",
|
|
105
|
+
" // the future and stall every write until the clock caught back up.",
|
|
106
|
+
" if (now < routeLastRefillMs) {",
|
|
107
|
+
" routeLastRefillMs = now;",
|
|
108
|
+
" }",
|
|
109
|
+
" const earned = Math.floor((now - routeLastRefillMs) / ROUTE_WRITE_REFILL_MS);",
|
|
110
|
+
" if (earned < 1) {",
|
|
111
|
+
" return;",
|
|
112
|
+
" }",
|
|
113
|
+
" routeTokens = Math.min(ROUTE_WRITE_BUCKET_CAPACITY, routeTokens + earned);",
|
|
114
|
+
" routeLastRefillMs += earned * ROUTE_WRITE_REFILL_MS;",
|
|
115
|
+
"}",
|
|
116
|
+
"",
|
|
117
|
+
"function takeRouteToken() {",
|
|
118
|
+
" refillRouteTokens();",
|
|
119
|
+
" if (routeTokens < 1) {",
|
|
120
|
+
" return false;",
|
|
121
|
+
" }",
|
|
122
|
+
" routeTokens -= 1;",
|
|
123
|
+
" return true;",
|
|
124
|
+
"}",
|
|
125
|
+
"",
|
|
126
|
+
"function routeRetryDelayMs() {",
|
|
127
|
+
" refillRouteTokens();",
|
|
128
|
+
" if (routeTokens >= 1) {",
|
|
129
|
+
" return 1;",
|
|
130
|
+
" }",
|
|
131
|
+
" const sinceRefill = Date.now() - routeLastRefillMs;",
|
|
132
|
+
" return Math.min(ROUTE_WRITE_REFILL_MS, Math.max(1, ROUTE_WRITE_REFILL_MS - sinceRefill));",
|
|
133
|
+
"}",
|
|
134
|
+
"",
|
|
91
135
|
"function writeRouteToUrl() {",
|
|
92
136
|
" if (window.location.hash === appRoute) {",
|
|
93
137
|
" return;",
|
|
@@ -100,16 +144,33 @@ export const HOST_PAGE_JS = [
|
|
|
100
144
|
" }",
|
|
101
145
|
"}",
|
|
102
146
|
"",
|
|
147
|
+
"function scheduleTrailingRouteWrite() {",
|
|
148
|
+
" routeWriteTimer = setTimeout(() => {",
|
|
149
|
+
" routeWriteTimer = null;",
|
|
150
|
+
" if (takeRouteToken()) {",
|
|
151
|
+
" writeRouteToUrl();",
|
|
152
|
+
" } else {",
|
|
153
|
+
" // The clock can land a hair before the token accrues; wait out",
|
|
154
|
+
" // the remainder rather than writing over budget.",
|
|
155
|
+
" scheduleTrailingRouteWrite();",
|
|
156
|
+
" }",
|
|
157
|
+
" }, routeRetryDelayMs());",
|
|
158
|
+
"}",
|
|
159
|
+
"",
|
|
103
160
|
"function applyRoute(hash) {",
|
|
104
161
|
" appRoute = hash;",
|
|
105
162
|
" if (routeWriteTimer !== null) {",
|
|
163
|
+
" return; // the trailing write reads appRoute",
|
|
164
|
+
" }",
|
|
165
|
+
" // Already mirrored: nothing to write, no token spent on nothing.",
|
|
166
|
+
" if (window.location.hash === hash) {",
|
|
106
167
|
" return;",
|
|
107
168
|
" }",
|
|
108
|
-
"
|
|
109
|
-
" routeWriteTimer = setTimeout(() => {",
|
|
110
|
-
" routeWriteTimer = null;",
|
|
169
|
+
" if (takeRouteToken()) {",
|
|
111
170
|
" writeRouteToUrl();",
|
|
112
|
-
"
|
|
171
|
+
" return;",
|
|
172
|
+
" }",
|
|
173
|
+
" scheduleTrailingRouteWrite();",
|
|
113
174
|
"}",
|
|
114
175
|
"",
|
|
115
176
|
"function postToApp(message) {",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "driggsby",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Set up and build on Driggsby, the MCP server for personal finance.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"node": ">=18"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@driggsby/deploy": "0.2.
|
|
32
|
-
"@driggsby/sdk": "0.2.
|
|
31
|
+
"@driggsby/deploy": "0.2.4",
|
|
32
|
+
"@driggsby/sdk": "0.2.4"
|
|
33
33
|
}
|
|
34
34
|
}
|