react-state-basis 0.4.2 → 0.5.1
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 +73 -321
- package/dist/index.d.mts +31 -23
- package/dist/index.d.ts +31 -23
- package/dist/index.js +353 -327
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +355 -332
- package/dist/index.mjs.map +1 -1
- package/dist/plugin.js +48 -22
- package/dist/production.d.mts +15 -6
- package/dist/production.d.ts +15 -6
- package/dist/production.js +21 -6
- package/dist/production.js.map +1 -1
- package/dist/production.mjs +19 -6
- package/dist/production.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,12 +33,14 @@ __export(index_exports, {
|
|
|
33
33
|
BasisProvider: () => BasisProvider,
|
|
34
34
|
basis: () => basis,
|
|
35
35
|
configureBasis: () => configureBasis,
|
|
36
|
+
createContext: () => createContext,
|
|
36
37
|
getBasisMetrics: () => getBasisMetrics,
|
|
37
38
|
printBasisHealthReport: () => printBasisHealthReport,
|
|
38
39
|
use: () => use,
|
|
39
|
-
useActionState: () =>
|
|
40
|
+
useActionState: () => useActionState,
|
|
40
41
|
useBasisConfig: () => useBasisConfig,
|
|
41
42
|
useCallback: () => useCallback,
|
|
43
|
+
useContext: () => useContext,
|
|
42
44
|
useDebugValue: () => useDebugValue2,
|
|
43
45
|
useDeferredValue: () => useDeferredValue,
|
|
44
46
|
useEffect: () => useEffect,
|
|
@@ -47,7 +49,7 @@ __export(index_exports, {
|
|
|
47
49
|
useInsertionEffect: () => useInsertionEffect2,
|
|
48
50
|
useLayoutEffect: () => useLayoutEffect,
|
|
49
51
|
useMemo: () => useMemo,
|
|
50
|
-
useOptimistic: () =>
|
|
52
|
+
useOptimistic: () => useOptimistic,
|
|
51
53
|
useReducer: () => useReducer,
|
|
52
54
|
useRef: () => useRef,
|
|
53
55
|
useState: () => useState,
|
|
@@ -63,15 +65,14 @@ var import_react = require("react");
|
|
|
63
65
|
// src/core/math.ts
|
|
64
66
|
var calculateSimilarityCircular = (bufferA, headA, bufferB, headB, offset) => {
|
|
65
67
|
const L = bufferA.length;
|
|
66
|
-
let dot = 0;
|
|
67
|
-
|
|
68
|
-
let magB = 0;
|
|
69
|
-
const headOffset = headB - headA + offset;
|
|
68
|
+
let dot = 0, magA = 0, magB = 0;
|
|
69
|
+
const baseOffset = ((headB - headA + offset) % L + L) % L;
|
|
70
70
|
for (let i = 0; i < L; i++) {
|
|
71
71
|
const valA = bufferA[i];
|
|
72
|
-
let iB = i +
|
|
73
|
-
if (iB
|
|
74
|
-
|
|
72
|
+
let iB = i + baseOffset;
|
|
73
|
+
if (iB >= L) {
|
|
74
|
+
iB -= L;
|
|
75
|
+
}
|
|
75
76
|
const valB = bufferB[iB];
|
|
76
77
|
dot += valA * valB;
|
|
77
78
|
magA += valA * valA;
|
|
@@ -93,7 +94,7 @@ var calculateCosineSimilarity = (A, B) => {
|
|
|
93
94
|
// src/core/logger.ts
|
|
94
95
|
var isWeb = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
95
96
|
var LAST_LOG_TIMES = /* @__PURE__ */ new Map();
|
|
96
|
-
var LOG_COOLDOWN =
|
|
97
|
+
var LOG_COOLDOWN = 3e3;
|
|
97
98
|
var STYLES = {
|
|
98
99
|
basis: "background: #6c5ce7; color: white; font-weight: bold; padding: 2px 6px; border-radius: 3px;",
|
|
99
100
|
version: "background: #a29bfe; color: #2d3436; padding: 2px 6px; border-radius: 3px; margin-left: -4px;",
|
|
@@ -102,11 +103,10 @@ var STYLES = {
|
|
|
102
103
|
headerGreen: "background: #00b894; color: white; font-weight: bold; padding: 4px 8px; border-radius: 4px;",
|
|
103
104
|
label: "background: #dfe6e9; color: #2d3436; padding: 0 4px; border-radius: 3px; font-family: monospace; font-weight: bold; border: 1px solid #b2bec3;",
|
|
104
105
|
location: "color: #0984e3; font-family: monospace; font-weight: bold;",
|
|
105
|
-
impact: "background: #f1f2f6; color: #2f3542; padding: 0 4px; border-radius: 3px; font-weight: bold;",
|
|
106
106
|
subText: "color: #636e72; font-size: 11px;",
|
|
107
107
|
bold: "font-weight: bold;",
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
action: "color: #00b894; font-weight: bold; border: 1px solid #00b894; padding: 0 4px; border-radius: 3px;",
|
|
109
|
+
warning: "color: #d63031; font-weight: bold; border: 1px solid #d63031; padding: 0 4px; border-radius: 3px;"
|
|
110
110
|
};
|
|
111
111
|
var parseLabel = (label) => {
|
|
112
112
|
const parts = label.split(" -> ");
|
|
@@ -117,129 +117,58 @@ var shouldLog = (key) => {
|
|
|
117
117
|
const last = LAST_LOG_TIMES.get(key) || 0;
|
|
118
118
|
if (now - last > LOG_COOLDOWN) {
|
|
119
119
|
LAST_LOG_TIMES.set(key, now);
|
|
120
|
-
if (LAST_LOG_TIMES.size > 100) {
|
|
121
|
-
const cutoff = now - 36e5;
|
|
122
|
-
for (const [k, v] of LAST_LOG_TIMES.entries()) {
|
|
123
|
-
if (v < cutoff) LAST_LOG_TIMES.delete(k);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
120
|
return true;
|
|
127
121
|
}
|
|
128
122
|
return false;
|
|
129
123
|
};
|
|
130
|
-
var
|
|
131
|
-
if (!isWeb) return;
|
|
132
|
-
console.log(
|
|
133
|
-
`%cBasis%cAuditor%c | Temporal Analysis Active (Window: ${windowSize})`,
|
|
134
|
-
STYLES.basis,
|
|
135
|
-
STYLES.version,
|
|
136
|
-
"color: #636e72; font-style: italic; margin-left: 8px;"
|
|
137
|
-
);
|
|
138
|
-
};
|
|
139
|
-
var displayRedundancyAlert = (labelA, labelB, sim) => {
|
|
124
|
+
var displayRedundancyAlert = (labelA, metaA, labelB, metaB, sim) => {
|
|
140
125
|
if (!isWeb || !shouldLog(`redundant-${labelA}-${labelB}`)) return;
|
|
141
126
|
const infoA = parseLabel(labelA);
|
|
142
127
|
const infoB = parseLabel(labelB);
|
|
143
|
-
|
|
128
|
+
const isContextMirror = metaA.role === "local" && metaB.role === "context" || metaB.role === "local" && metaA.role === "context";
|
|
129
|
+
const local = metaA.role === "local" ? infoA : infoB;
|
|
130
|
+
const context = metaA.role === "context" ? infoA : infoB;
|
|
131
|
+
console.group(`%c \u264A BASIS | ${isContextMirror ? "CONTEXT MIRRORING" : "DUPLICATE STATE"} `, STYLES.headerRed);
|
|
144
132
|
console.log(`%c\u{1F4CD} Location: %c${infoA.file}`, STYLES.bold, STYLES.location);
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
`%
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
"",
|
|
181
|
-
STYLES.label,
|
|
182
|
-
"",
|
|
183
|
-
STYLES.label,
|
|
184
|
-
""
|
|
185
|
-
);
|
|
186
|
-
console.log(
|
|
187
|
-
`%cThe Impact:%c You are forcing %c2 render passes%c for a single logical change.`,
|
|
188
|
-
STYLES.bold,
|
|
189
|
-
"",
|
|
190
|
-
STYLES.impact,
|
|
191
|
-
""
|
|
192
|
-
);
|
|
193
|
-
console.log(
|
|
194
|
-
`%cRecommended Fix:%c Remove the useEffect. Calculate %c${target.name}%c as a derived value or projection.`,
|
|
195
|
-
STYLES.bold,
|
|
196
|
-
"",
|
|
197
|
-
STYLES.actionDelete,
|
|
198
|
-
""
|
|
199
|
-
);
|
|
200
|
-
console.groupEnd();
|
|
201
|
-
};
|
|
202
|
-
var displayViolentBreaker = (label, count, threshold) => {
|
|
203
|
-
if (!isWeb) return;
|
|
204
|
-
const parts = label.split(" -> ");
|
|
205
|
-
console.group(
|
|
206
|
-
`%c \u26A0\uFE0F CRITICAL SYSTEM ALERT | BASIS ENGINE `,
|
|
207
|
-
"background: #dc2626; color: white; font-weight: bold; padding: 8px 16px; font-size: 14px;"
|
|
208
|
-
);
|
|
209
|
-
console.error(
|
|
210
|
-
`%c\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
211
|
-
"color: #dc2626; font-weight: bold;"
|
|
212
|
-
);
|
|
213
|
-
console.error(
|
|
214
|
-
`%cINFINITE LOOP DETECTED
|
|
215
|
-
|
|
216
|
-
%cVariable: %c${parts[1] || label}
|
|
217
|
-
%cUpdate Frequency: %c${count} updates/sec
|
|
218
|
-
%cExpected Maximum: %c${threshold} updates
|
|
219
|
-
|
|
220
|
-
%c\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
221
|
-
"color: #dc2626; font-size: 16px; font-weight: bold;",
|
|
222
|
-
"color: #71717a; font-weight: bold;",
|
|
223
|
-
`color: white; background: #dc2626; padding: 2px 8px;`,
|
|
224
|
-
"color: #71717a; font-weight: bold;",
|
|
225
|
-
`color: #fbbf24; font-weight: bold;`,
|
|
226
|
-
"color: #71717a; font-weight: bold;",
|
|
227
|
-
`color: #fbbf24; font-weight: bold;`,
|
|
228
|
-
"color: #dc2626; font-weight: bold;"
|
|
229
|
-
);
|
|
230
|
-
console.log(
|
|
231
|
-
`%cDIAGNOSTICS:
|
|
232
|
-
1. Check for setState inside the render body.
|
|
233
|
-
2. Verify useEffect dependencies (missing or unstable refs).
|
|
234
|
-
3. Look for circular chains (State A -> B -> A).
|
|
235
|
-
|
|
236
|
-
%cSYSTEM ACTION: Update BLOCKED. Fix your code to resume monitoring.`,
|
|
237
|
-
"color: #71717a;",
|
|
238
|
-
"color: #dc2626; font-weight: bold;"
|
|
239
|
-
);
|
|
133
|
+
if (isContextMirror) {
|
|
134
|
+
console.log(
|
|
135
|
+
`%cIssue:%c Local variable %c${local.name}%c is just a copy of Global Context %c${context.name}%c.
|
|
136
|
+
%cConfidence: ${(sim * 100).toFixed(0)}%`,
|
|
137
|
+
STYLES.bold,
|
|
138
|
+
"",
|
|
139
|
+
STYLES.label,
|
|
140
|
+
"",
|
|
141
|
+
STYLES.label,
|
|
142
|
+
"",
|
|
143
|
+
STYLES.subText
|
|
144
|
+
);
|
|
145
|
+
console.log(`%cFix:%c Use the context value directly to avoid state drift.`, STYLES.bold, STYLES.warning);
|
|
146
|
+
} else {
|
|
147
|
+
console.log(
|
|
148
|
+
`%cIssue:%c %c${infoA.name}%c and %c${infoB.name}%c are synchronized (${(sim * 100).toFixed(0)}% correlation).`,
|
|
149
|
+
STYLES.bold,
|
|
150
|
+
"",
|
|
151
|
+
STYLES.label,
|
|
152
|
+
"",
|
|
153
|
+
STYLES.label,
|
|
154
|
+
""
|
|
155
|
+
);
|
|
156
|
+
console.log(
|
|
157
|
+
`%cFix:%c Merge states or calculate %c${infoB.name}%c from %c${infoA.name}%c via %cuseMemo%c.`,
|
|
158
|
+
STYLES.bold,
|
|
159
|
+
"",
|
|
160
|
+
STYLES.label,
|
|
161
|
+
"",
|
|
162
|
+
STYLES.label,
|
|
163
|
+
"",
|
|
164
|
+
STYLES.action,
|
|
165
|
+
""
|
|
166
|
+
);
|
|
167
|
+
}
|
|
240
168
|
console.groupEnd();
|
|
241
169
|
};
|
|
242
170
|
var displayHealthReport = (history2, threshold) => {
|
|
171
|
+
if (!isWeb) return;
|
|
243
172
|
const entries = Array.from(history2.entries());
|
|
244
173
|
const totalVars = entries.length;
|
|
245
174
|
if (totalVars === 0) return;
|
|
@@ -254,6 +183,7 @@ var displayHealthReport = (history2, threshold) => {
|
|
|
254
183
|
if (labelA === labelB || processed.has(labelB)) return;
|
|
255
184
|
const sim = calculateCosineSimilarity(metaA.buffer, metaB.buffer);
|
|
256
185
|
if (sim > threshold) {
|
|
186
|
+
if (metaA.role === "context" && metaB.role === "context") return;
|
|
257
187
|
currentCluster.push(labelB);
|
|
258
188
|
processed.add(labelB);
|
|
259
189
|
}
|
|
@@ -263,52 +193,141 @@ var displayHealthReport = (history2, threshold) => {
|
|
|
263
193
|
});
|
|
264
194
|
const systemRank = independentCount + clusters.length;
|
|
265
195
|
const healthScore = systemRank / totalVars * 100;
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
});
|
|
280
|
-
console.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
});
|
|
296
|
-
console.table(matrix);
|
|
196
|
+
console.group(`%c \u{1F4CA} BASIS | ARCHITECTURAL HEALTH REPORT `, STYLES.headerGreen);
|
|
197
|
+
console.log(
|
|
198
|
+
`%cEfficiency: %c${healthScore.toFixed(1)}% %c(${systemRank}/${totalVars} Sources of Truth)`,
|
|
199
|
+
STYLES.bold,
|
|
200
|
+
`color: ${healthScore > 85 ? "#00b894" : "#d63031"}; font-weight: bold;`,
|
|
201
|
+
STYLES.subText
|
|
202
|
+
);
|
|
203
|
+
if (clusters.length > 0) {
|
|
204
|
+
console.log(`%cDetected ${clusters.length} Sync Issues:`, "font-weight: bold; color: #e17055; margin-top: 10px;");
|
|
205
|
+
clusters.forEach((cluster, idx) => {
|
|
206
|
+
const clusterMetas = cluster.map((l) => ({ label: l, meta: history2.get(l), info: parseLabel(l) }));
|
|
207
|
+
const contexts = clusterMetas.filter((c) => c.meta.role === "context");
|
|
208
|
+
const locals = clusterMetas.filter((c) => c.meta.role === "local");
|
|
209
|
+
const names = clusterMetas.map((c) => `${c.meta.role === "context" ? "\u03A9 " : ""}${c.info.name}`).join(" \u27F7 ");
|
|
210
|
+
console.group(` %c${idx + 1}%c ${names}`, "background: #e17055; color: white; border-radius: 50%; padding: 0 5px;", "font-family: monospace; font-weight: bold;");
|
|
211
|
+
if (contexts.length > 0) {
|
|
212
|
+
const ctxNames = contexts.map((c) => c.info.name).join(", ");
|
|
213
|
+
console.log(`%cDiagnosis:%c Context Mirroring. Variables are copying from %c${ctxNames}%c.`, STYLES.bold, "", STYLES.label, "");
|
|
214
|
+
console.log(`%cSolution:%c Use the context directly to avoid state drift.`, STYLES.bold, STYLES.action);
|
|
215
|
+
} else {
|
|
216
|
+
const isExplosion = locals.length > 2;
|
|
217
|
+
if (isExplosion) {
|
|
218
|
+
console.log(`%cDiagnosis:%c Boolean Explosion. Multiple states updating in sync.`, STYLES.bold, "");
|
|
219
|
+
console.log(`%cSolution:%c Combine into a single %cstatus%c string or a %creducer%c.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
|
|
220
|
+
} else {
|
|
221
|
+
console.log(`%cDiagnosis:%c Redundant State. Variables always change together.`, STYLES.bold, "");
|
|
222
|
+
console.log(`%cSolution:%c Derive one from the other via %cuseMemo%c.`, STYLES.bold, "", STYLES.label, "");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
297
225
|
console.groupEnd();
|
|
298
|
-
}
|
|
299
|
-
|
|
226
|
+
});
|
|
227
|
+
} else {
|
|
228
|
+
console.log("%c\u2728 Your architecture is clean. No redundant state detected.", "color: #00b894; font-weight: bold;");
|
|
229
|
+
}
|
|
230
|
+
console.groupEnd();
|
|
231
|
+
};
|
|
232
|
+
var displayCausalHint = (targetLabel, targetMeta, sourceLabel, sourceMeta) => {
|
|
233
|
+
if (!isWeb || !shouldLog(`causal-${sourceLabel}-${targetLabel}`)) return;
|
|
234
|
+
const target = parseLabel(targetLabel);
|
|
235
|
+
const source = parseLabel(sourceLabel);
|
|
236
|
+
const isContextTrigger = sourceMeta.role === "context";
|
|
237
|
+
console.groupCollapsed(`%c \u26A1 BASIS | ${isContextTrigger ? "CONTEXT SYNC LEAK" : "DOUBLE RENDER"} `, STYLES.headerBlue);
|
|
238
|
+
console.log(`%c\u{1F4CD} Location: %c${target.file}`, STYLES.bold, STYLES.location);
|
|
239
|
+
if (isContextTrigger) {
|
|
240
|
+
console.log(`%cIssue:%c Context %c${source.name}%c updated, then local %c${target.name}%c followed 1 frame later.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
|
|
241
|
+
console.log(`%cImpact: This forces React to render the component twice for every change.`, STYLES.subText);
|
|
242
|
+
} else {
|
|
243
|
+
console.log(`%cIssue:%c %c${source.name}%c triggers %c${target.name}%c in a separate frame.`, STYLES.bold, "", STYLES.label, "", STYLES.label, "");
|
|
300
244
|
}
|
|
245
|
+
console.log(`%cFix:%c Derive %c${target.name}%c during the first render.`, STYLES.bold, STYLES.action, STYLES.label, "");
|
|
246
|
+
console.groupEnd();
|
|
247
|
+
};
|
|
248
|
+
var displayViolentBreaker = (label, count, threshold) => {
|
|
249
|
+
if (!isWeb) return;
|
|
250
|
+
const parts = label.split(" -> ");
|
|
251
|
+
console.group(`%c \u{1F6D1} BASIS CRITICAL | CIRCUIT BREAKER `, "background: #dc2626; color: white; font-weight: bold; padding: 8px 16px;");
|
|
252
|
+
console.error(`INFINITE LOOP DETECTED
|
|
253
|
+
Variable: ${parts[1] || label}
|
|
254
|
+
Frequency: ${count} updates/sec`);
|
|
255
|
+
console.log(`%cACTION: Update BLOCKED to prevent browser freeze.`, "color: #dc2626; font-weight: bold;");
|
|
256
|
+
console.groupEnd();
|
|
257
|
+
};
|
|
258
|
+
var displayBootLog = (windowSize) => {
|
|
259
|
+
if (!isWeb) return;
|
|
260
|
+
console.log(`%cBasis%cAuditor%c | v0.5.x Architectural Forensics Active (Window: ${windowSize})`, STYLES.basis, STYLES.version, "color: #636e72; font-style: italic; margin-left: 8px;");
|
|
301
261
|
};
|
|
302
262
|
|
|
303
263
|
// src/core/constants.ts
|
|
304
264
|
var WINDOW_SIZE = 50;
|
|
305
265
|
var SIMILARITY_THRESHOLD = 0.88;
|
|
306
266
|
var LOOP_THRESHOLD = 150;
|
|
307
|
-
var ANALYSIS_INTERVAL = 5;
|
|
308
267
|
var VOLATILITY_THRESHOLD = 25;
|
|
309
268
|
|
|
269
|
+
// src/core/analysis.ts
|
|
270
|
+
var calculateAllSimilarities = (entryA, entryB) => {
|
|
271
|
+
const sync = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, 0);
|
|
272
|
+
const bA = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, 1);
|
|
273
|
+
const aB = calculateSimilarityCircular(entryA.meta.buffer, entryA.meta.head, entryB.meta.buffer, entryB.meta.head, -1);
|
|
274
|
+
return { sync, bA, aB, max: Math.max(sync, bA, aB) };
|
|
275
|
+
};
|
|
276
|
+
var shouldSkipComparison = (entryA, entryB, dirtyLabels2) => {
|
|
277
|
+
if (entryA.label === entryB.label) return true;
|
|
278
|
+
if (dirtyLabels2.has(entryB.label) && entryA.label > entryB.label) return true;
|
|
279
|
+
return false;
|
|
280
|
+
};
|
|
281
|
+
var detectRedundancy = (entryA, entryB, similarities, redundantSet) => {
|
|
282
|
+
const roleA = entryA.meta.role;
|
|
283
|
+
const roleB = entryB.meta.role;
|
|
284
|
+
if (roleA === "context" /* CONTEXT */ && roleB === "context" /* CONTEXT */) return;
|
|
285
|
+
if (entryA.meta.density < 2 || entryB.meta.density < 2) return;
|
|
286
|
+
if (roleA === "local" /* LOCAL */ && roleB === "context" /* CONTEXT */) {
|
|
287
|
+
redundantSet.add(entryA.label);
|
|
288
|
+
displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
|
|
289
|
+
} else if (roleA === "context" /* CONTEXT */ && roleB === "local" /* LOCAL */) {
|
|
290
|
+
redundantSet.add(entryB.label);
|
|
291
|
+
displayRedundancyAlert(entryB.label, entryB.meta, entryA.label, entryA.meta, similarities.max);
|
|
292
|
+
} else if (roleA === "local" /* LOCAL */ && roleB === "local" /* LOCAL */) {
|
|
293
|
+
redundantSet.add(entryA.label);
|
|
294
|
+
redundantSet.add(entryB.label);
|
|
295
|
+
displayRedundancyAlert(entryA.label, entryA.meta, entryB.label, entryB.meta, similarities.max);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
var detectCausalLeak = (entryA, entryB, similarities) => {
|
|
299
|
+
if (entryA.isVolatile || entryB.isVolatile) return;
|
|
300
|
+
if (similarities.bA === similarities.max) {
|
|
301
|
+
displayCausalHint(entryB.label, entryB.meta, entryA.label, entryA.meta);
|
|
302
|
+
} else if (similarities.aB === similarities.max) {
|
|
303
|
+
displayCausalHint(entryA.label, entryA.meta, entryB.label, entryB.meta);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
var detectSubspaceOverlap = (dirtyEntries, allEntries, redundantSet, dirtyLabels2) => {
|
|
307
|
+
let compCount = 0;
|
|
308
|
+
for (const entryA of dirtyEntries) {
|
|
309
|
+
for (const entryB of allEntries) {
|
|
310
|
+
if (shouldSkipComparison(entryA, entryB, dirtyLabels2)) continue;
|
|
311
|
+
compCount++;
|
|
312
|
+
const similarities = calculateAllSimilarities(entryA, entryB);
|
|
313
|
+
if (similarities.max > SIMILARITY_THRESHOLD) {
|
|
314
|
+
detectRedundancy(entryA, entryB, similarities, redundantSet);
|
|
315
|
+
detectCausalLeak(entryA, entryB, similarities);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return compCount;
|
|
320
|
+
};
|
|
321
|
+
|
|
310
322
|
// src/engine.ts
|
|
311
323
|
var BASIS_INSTANCE_KEY = /* @__PURE__ */ Symbol.for("__basis_engine_instance__");
|
|
324
|
+
var NULL_SIGNAL = {
|
|
325
|
+
role: "proj" /* PROJECTION */,
|
|
326
|
+
buffer: new Uint8Array(0),
|
|
327
|
+
head: 0,
|
|
328
|
+
density: 0,
|
|
329
|
+
options: {}
|
|
330
|
+
};
|
|
312
331
|
var getGlobalInstance = () => {
|
|
313
332
|
const root = globalThis;
|
|
314
333
|
if (!root[BASIS_INSTANCE_KEY]) {
|
|
@@ -322,7 +341,12 @@ var getGlobalInstance = () => {
|
|
|
322
341
|
isBatching: false,
|
|
323
342
|
currentEffectSource: null,
|
|
324
343
|
pausedVariables: /* @__PURE__ */ new Set(),
|
|
325
|
-
metrics: {
|
|
344
|
+
metrics: {
|
|
345
|
+
lastAnalysisTimeMs: 0,
|
|
346
|
+
comparisonCount: 0,
|
|
347
|
+
lastAnalysisTimestamp: 0,
|
|
348
|
+
systemEntropy: 0
|
|
349
|
+
},
|
|
326
350
|
alertCount: 0,
|
|
327
351
|
loopCounters: /* @__PURE__ */ new Map(),
|
|
328
352
|
lastCleanup: Date.now()
|
|
@@ -331,62 +355,61 @@ var getGlobalInstance = () => {
|
|
|
331
355
|
return root[BASIS_INSTANCE_KEY];
|
|
332
356
|
};
|
|
333
357
|
var instance = getGlobalInstance();
|
|
334
|
-
var
|
|
358
|
+
var config = instance.config;
|
|
359
|
+
var history = instance.history;
|
|
360
|
+
var redundantLabels = instance.redundantLabels;
|
|
361
|
+
var currentTickBatch = instance.currentTickBatch;
|
|
335
362
|
var currentTickRegistry = {};
|
|
336
363
|
var dirtyLabels = /* @__PURE__ */ new Set();
|
|
364
|
+
var calculateTickEntropy = (tickIdx) => {
|
|
365
|
+
let activeCount = 0;
|
|
366
|
+
const total = instance.history.size;
|
|
367
|
+
if (total === 0) return 1;
|
|
368
|
+
instance.history.forEach((meta) => {
|
|
369
|
+
if (meta.buffer[tickIdx] === 1) activeCount++;
|
|
370
|
+
});
|
|
371
|
+
return 1 - activeCount / total;
|
|
372
|
+
};
|
|
337
373
|
var analyzeBasis = () => {
|
|
338
|
-
if (!instance.config.debug) {
|
|
339
|
-
instance.redundantLabels.clear();
|
|
374
|
+
if (!instance.config.debug || dirtyLabels.size === 0) {
|
|
340
375
|
return;
|
|
341
376
|
}
|
|
342
377
|
const scheduler = globalThis.requestIdleCallback || ((cb) => setTimeout(cb, 1));
|
|
378
|
+
const snapshot = new Set(dirtyLabels);
|
|
379
|
+
dirtyLabels.clear();
|
|
343
380
|
scheduler(() => {
|
|
344
381
|
const analysisStart = performance.now();
|
|
345
|
-
if (dirtyLabels.size === 0) return;
|
|
346
382
|
const allEntries = [];
|
|
347
383
|
const dirtyEntries = [];
|
|
348
384
|
instance.history.forEach((meta, label) => {
|
|
349
|
-
if (meta.options.suppressAll) return;
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
385
|
+
if (meta.options.suppressAll || meta.density === 0) return;
|
|
386
|
+
const entry = {
|
|
387
|
+
label,
|
|
388
|
+
meta,
|
|
389
|
+
isVolatile: meta.density > VOLATILITY_THRESHOLD
|
|
390
|
+
};
|
|
391
|
+
allEntries.push(entry);
|
|
392
|
+
if (snapshot.has(label)) {
|
|
393
|
+
dirtyEntries.push(entry);
|
|
356
394
|
}
|
|
357
395
|
});
|
|
358
|
-
if (dirtyEntries.length === 0 || allEntries.length < 2)
|
|
359
|
-
dirtyLabels.clear();
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
396
|
+
if (dirtyEntries.length === 0 || allEntries.length < 2) return;
|
|
362
397
|
const nextRedundant = /* @__PURE__ */ new Set();
|
|
363
|
-
let compCount = 0;
|
|
364
398
|
instance.redundantLabels.forEach((l) => {
|
|
365
|
-
if (!
|
|
366
|
-
|
|
367
|
-
for (const dirtyEntry of dirtyEntries) {
|
|
368
|
-
for (const otherEntry of allEntries) {
|
|
369
|
-
if (dirtyEntry.label === otherEntry.label) continue;
|
|
370
|
-
if (dirtyLabels.has(otherEntry.label) && dirtyEntry.label > otherEntry.label) continue;
|
|
371
|
-
compCount++;
|
|
372
|
-
const sync = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, 0);
|
|
373
|
-
const bA = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, 1);
|
|
374
|
-
const aB = calculateSimilarityCircular(dirtyEntry.meta.buffer, dirtyEntry.meta.head, otherEntry.meta.buffer, otherEntry.meta.head, -1);
|
|
375
|
-
const maxSim = Math.max(sync, bA, aB);
|
|
376
|
-
if (maxSim > SIMILARITY_THRESHOLD) {
|
|
377
|
-
const bothVolatile = dirtyEntry.density > VOLATILITY_THRESHOLD && otherEntry.density > VOLATILITY_THRESHOLD;
|
|
378
|
-
if (sync === maxSim && !bothVolatile) {
|
|
379
|
-
nextRedundant.add(dirtyEntry.label);
|
|
380
|
-
nextRedundant.add(otherEntry.label);
|
|
381
|
-
displayRedundancyAlert(dirtyEntry.label, otherEntry.label, sync);
|
|
382
|
-
} else if (bA === maxSim) displayCausalHint(otherEntry.label, dirtyEntry.label, "math");
|
|
383
|
-
else if (aB === maxSim) displayCausalHint(dirtyEntry.label, otherEntry.label, "math");
|
|
384
|
-
}
|
|
399
|
+
if (!snapshot.has(l)) {
|
|
400
|
+
nextRedundant.add(l);
|
|
385
401
|
}
|
|
386
|
-
}
|
|
387
|
-
|
|
402
|
+
});
|
|
403
|
+
const compCount = detectSubspaceOverlap(
|
|
404
|
+
dirtyEntries,
|
|
405
|
+
allEntries,
|
|
406
|
+
nextRedundant,
|
|
407
|
+
snapshot
|
|
408
|
+
);
|
|
388
409
|
instance.redundantLabels.clear();
|
|
389
|
-
nextRedundant.forEach((l) =>
|
|
410
|
+
nextRedundant.forEach((l) => {
|
|
411
|
+
instance.redundantLabels.add(l);
|
|
412
|
+
});
|
|
390
413
|
instance.metrics.lastAnalysisTimeMs = performance.now() - analysisStart;
|
|
391
414
|
instance.metrics.comparisonCount = compCount;
|
|
392
415
|
instance.metrics.lastAnalysisTimestamp = Date.now();
|
|
@@ -395,13 +418,22 @@ var analyzeBasis = () => {
|
|
|
395
418
|
var processHeartbeat = () => {
|
|
396
419
|
instance.tick++;
|
|
397
420
|
instance.history.forEach((meta, label) => {
|
|
398
|
-
meta.buffer[meta.head]
|
|
421
|
+
const oldValue = meta.buffer[meta.head];
|
|
422
|
+
const newValue = instance.currentTickBatch.has(label) ? 1 : 0;
|
|
423
|
+
meta.buffer[meta.head] = newValue;
|
|
424
|
+
if (oldValue !== newValue) {
|
|
425
|
+
meta.density += newValue - oldValue;
|
|
426
|
+
}
|
|
399
427
|
meta.head = (meta.head + 1) % WINDOW_SIZE;
|
|
400
428
|
});
|
|
429
|
+
const lastHead = instance.history.size > 0 ? instance.tick % WINDOW_SIZE : 0;
|
|
430
|
+
instance.metrics.systemEntropy = calculateTickEntropy(lastHead);
|
|
401
431
|
instance.currentTickBatch.clear();
|
|
402
432
|
currentTickRegistry = {};
|
|
403
433
|
instance.isBatching = false;
|
|
404
|
-
if (
|
|
434
|
+
if (dirtyLabels.size > 0) {
|
|
435
|
+
analyzeBasis();
|
|
436
|
+
}
|
|
405
437
|
};
|
|
406
438
|
var recordUpdate = (label) => {
|
|
407
439
|
if (!instance.config.debug) return true;
|
|
@@ -419,7 +451,15 @@ var recordUpdate = (label) => {
|
|
|
419
451
|
return false;
|
|
420
452
|
}
|
|
421
453
|
if (instance.currentEffectSource && instance.currentEffectSource !== label) {
|
|
422
|
-
|
|
454
|
+
const targetMeta = instance.history.get(label);
|
|
455
|
+
const sourceMeta = instance.history.get(instance.currentEffectSource);
|
|
456
|
+
if (targetMeta) {
|
|
457
|
+
const sourceDensity = sourceMeta?.density || 0;
|
|
458
|
+
const isVolatile = targetMeta.density > VOLATILITY_THRESHOLD || sourceDensity > VOLATILITY_THRESHOLD;
|
|
459
|
+
if (!isVolatile) {
|
|
460
|
+
displayCausalHint(label, targetMeta, instance.currentEffectSource, sourceMeta || NULL_SIGNAL);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
423
463
|
}
|
|
424
464
|
if (currentTickRegistry[label]) return true;
|
|
425
465
|
currentTickRegistry[label] = true;
|
|
@@ -441,11 +481,20 @@ var configureBasis = (c) => {
|
|
|
441
481
|
var registerVariable = (l, o = {}) => {
|
|
442
482
|
if (!instance.config.debug || o.suppressAll) return;
|
|
443
483
|
if (!instance.history.has(l)) {
|
|
444
|
-
instance.history.set(l, {
|
|
484
|
+
instance.history.set(l, {
|
|
485
|
+
buffer: new Uint8Array(WINDOW_SIZE),
|
|
486
|
+
head: 0,
|
|
487
|
+
density: 0,
|
|
488
|
+
options: o,
|
|
489
|
+
role: o.role || "local" /* LOCAL */
|
|
490
|
+
});
|
|
445
491
|
}
|
|
446
492
|
};
|
|
447
493
|
var unregisterVariable = (l) => {
|
|
448
494
|
instance.history.delete(l);
|
|
495
|
+
instance.loopCounters.delete(l);
|
|
496
|
+
instance.pausedVariables.delete(l);
|
|
497
|
+
instance.redundantLabels.delete(l);
|
|
449
498
|
};
|
|
450
499
|
var beginEffectTracking = (l) => {
|
|
451
500
|
if (instance.config.debug) instance.currentEffectSource = l;
|
|
@@ -454,67 +503,47 @@ var endEffectTracking = () => {
|
|
|
454
503
|
instance.currentEffectSource = null;
|
|
455
504
|
};
|
|
456
505
|
var printBasisHealthReport = (threshold = 0.5) => {
|
|
457
|
-
if (!instance.config.debug)
|
|
458
|
-
console.warn("[Basis] Cannot generate report. Debug mode is OFF.");
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
506
|
+
if (!instance.config.debug) return;
|
|
461
507
|
displayHealthReport(instance.history, threshold);
|
|
462
508
|
};
|
|
463
509
|
var getBasisMetrics = () => ({
|
|
464
|
-
engine: "v0.
|
|
510
|
+
engine: "v0.5.x",
|
|
465
511
|
hooks: instance.history.size,
|
|
466
|
-
|
|
467
|
-
|
|
512
|
+
analysis_ms: instance.metrics.lastAnalysisTimeMs.toFixed(3),
|
|
513
|
+
entropy: instance.metrics.systemEntropy.toFixed(3)
|
|
468
514
|
});
|
|
469
515
|
if (typeof window !== "undefined") {
|
|
470
516
|
window.printBasisReport = printBasisHealthReport;
|
|
471
517
|
window.getBasisMetrics = getBasisMetrics;
|
|
472
518
|
}
|
|
473
|
-
var __testEngine__ = {
|
|
474
|
-
instance,
|
|
475
|
-
history: instance.history,
|
|
476
|
-
configureBasis,
|
|
477
|
-
registerVariable,
|
|
478
|
-
unregisterVariable,
|
|
479
|
-
recordUpdate,
|
|
480
|
-
printBasisHealthReport,
|
|
481
|
-
beginEffectTracking,
|
|
482
|
-
endEffectTracking
|
|
483
|
-
};
|
|
484
519
|
|
|
485
520
|
// src/hooks.ts
|
|
486
521
|
var anonCount = 0;
|
|
487
522
|
var getFallbackLabel = (type) => `anon_${type}_${anonCount++}`;
|
|
523
|
+
var React19 = React;
|
|
488
524
|
function useState(initialState, label) {
|
|
489
525
|
const [val, setVal] = (0, import_react.useState)(initialState);
|
|
490
526
|
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("state")).current;
|
|
491
527
|
(0, import_react.useEffect)(() => {
|
|
492
|
-
registerVariable(effectiveLabel);
|
|
528
|
+
registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
|
|
493
529
|
return () => {
|
|
494
530
|
unregisterVariable(effectiveLabel);
|
|
495
531
|
};
|
|
496
532
|
}, [effectiveLabel]);
|
|
497
|
-
const setter = (0, import_react.useCallback)((
|
|
533
|
+
const setter = (0, import_react.useCallback)((value) => {
|
|
498
534
|
if (recordUpdate(effectiveLabel)) {
|
|
499
|
-
setVal(
|
|
535
|
+
setVal(value);
|
|
500
536
|
}
|
|
501
537
|
}, [effectiveLabel]);
|
|
502
538
|
return [val, setter];
|
|
503
539
|
}
|
|
504
|
-
function useRef(initialValue, _label) {
|
|
505
|
-
return (0, import_react.useRef)(initialValue);
|
|
506
|
-
}
|
|
507
540
|
function useReducer(reducer, initialArg, init, label) {
|
|
508
|
-
const
|
|
509
|
-
const providedLabel =
|
|
541
|
+
const isLazy = typeof init === "function";
|
|
542
|
+
const providedLabel = label || (typeof init === "string" ? init : void 0);
|
|
510
543
|
const effectiveLabel = (0, import_react.useRef)(providedLabel || getFallbackLabel("reducer")).current;
|
|
511
|
-
const [state, dispatch] = (0, import_react.useReducer)(
|
|
512
|
-
reducer,
|
|
513
|
-
initialArg,
|
|
514
|
-
isLazyInit ? init : void 0
|
|
515
|
-
);
|
|
544
|
+
const [state, dispatch] = isLazy ? (0, import_react.useReducer)(reducer, initialArg, init) : (0, import_react.useReducer)(reducer, initialArg);
|
|
516
545
|
(0, import_react.useEffect)(() => {
|
|
517
|
-
registerVariable(effectiveLabel);
|
|
546
|
+
registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
|
|
518
547
|
return () => {
|
|
519
548
|
unregisterVariable(effectiveLabel);
|
|
520
549
|
};
|
|
@@ -523,20 +552,47 @@ function useReducer(reducer, initialArg, init, label) {
|
|
|
523
552
|
if (recordUpdate(effectiveLabel)) {
|
|
524
553
|
dispatch(action);
|
|
525
554
|
}
|
|
526
|
-
}, [effectiveLabel]);
|
|
555
|
+
}, [effectiveLabel, dispatch]);
|
|
527
556
|
return [state, basisDispatch];
|
|
528
557
|
}
|
|
558
|
+
function createContext(defaultValue, label) {
|
|
559
|
+
const context = (0, import_react.createContext)(defaultValue);
|
|
560
|
+
const effectiveLabel = label || getFallbackLabel("context");
|
|
561
|
+
Object.defineProperty(context, "_basis_label", {
|
|
562
|
+
value: effectiveLabel,
|
|
563
|
+
writable: false,
|
|
564
|
+
enumerable: false
|
|
565
|
+
});
|
|
566
|
+
return context;
|
|
567
|
+
}
|
|
568
|
+
function useContext(context) {
|
|
569
|
+
const val = (0, import_react.useContext)(context);
|
|
570
|
+
const label = context._basis_label;
|
|
571
|
+
(0, import_react.useLayoutEffect)(() => {
|
|
572
|
+
if (label) {
|
|
573
|
+
registerVariable(label, { role: "context" /* CONTEXT */ });
|
|
574
|
+
recordUpdate(label);
|
|
575
|
+
}
|
|
576
|
+
}, [val, label]);
|
|
577
|
+
return val;
|
|
578
|
+
}
|
|
529
579
|
function useMemo(factory, deps, label) {
|
|
530
|
-
const effectiveLabel = label || "
|
|
580
|
+
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("proj")).current;
|
|
531
581
|
(0, import_react.useEffect)(() => {
|
|
532
|
-
|
|
582
|
+
registerVariable(effectiveLabel, { role: "proj" /* PROJECTION */ });
|
|
583
|
+
return () => {
|
|
584
|
+
unregisterVariable(effectiveLabel);
|
|
585
|
+
};
|
|
533
586
|
}, [effectiveLabel]);
|
|
534
587
|
return (0, import_react.useMemo)(factory, deps || []);
|
|
535
588
|
}
|
|
536
589
|
function useCallback(callback, deps, label) {
|
|
537
|
-
const effectiveLabel = label || "
|
|
590
|
+
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("cb")).current;
|
|
538
591
|
(0, import_react.useEffect)(() => {
|
|
539
|
-
|
|
592
|
+
registerVariable(effectiveLabel, { role: "proj" /* PROJECTION */ });
|
|
593
|
+
return () => {
|
|
594
|
+
unregisterVariable(effectiveLabel);
|
|
595
|
+
};
|
|
540
596
|
}, [effectiveLabel]);
|
|
541
597
|
return (0, import_react.useCallback)(callback, deps);
|
|
542
598
|
}
|
|
@@ -544,56 +600,29 @@ function useEffect(effect, deps, label) {
|
|
|
544
600
|
const effectiveLabel = label || "anonymous_effect";
|
|
545
601
|
(0, import_react.useEffect)(() => {
|
|
546
602
|
beginEffectTracking(effectiveLabel);
|
|
547
|
-
const
|
|
603
|
+
const destructor = effect();
|
|
548
604
|
endEffectTracking();
|
|
549
|
-
return
|
|
605
|
+
return typeof destructor === "function" ? destructor : void 0;
|
|
550
606
|
}, deps);
|
|
551
607
|
}
|
|
552
608
|
function useLayoutEffect(effect, deps, label) {
|
|
553
609
|
const effectiveLabel = label || "anonymous_layout_effect";
|
|
554
610
|
(0, import_react.useLayoutEffect)(() => {
|
|
555
611
|
beginEffectTracking(effectiveLabel);
|
|
556
|
-
const
|
|
612
|
+
const destructor = effect();
|
|
557
613
|
endEffectTracking();
|
|
558
|
-
return
|
|
614
|
+
return typeof destructor === "function" ? destructor : void 0;
|
|
559
615
|
}, deps);
|
|
560
616
|
}
|
|
561
|
-
function
|
|
562
|
-
const
|
|
563
|
-
const effectiveLabel = _label || "anonymous_transition";
|
|
564
|
-
const basisStartTransition = (callback) => {
|
|
565
|
-
if (config.debug) console.log(`%c [Basis] Transition Started: "${effectiveLabel}" `, "color: #e67e22; font-weight: bold;");
|
|
566
|
-
startTransition(callback);
|
|
567
|
-
};
|
|
568
|
-
return [isPending, basisStartTransition];
|
|
569
|
-
}
|
|
570
|
-
function useDeferredValue(value, initialValueOrLabel, label) {
|
|
571
|
-
const isLabelAsSecondArg = typeof initialValueOrLabel === "string" && label === void 0;
|
|
572
|
-
const actualInitialValue = isLabelAsSecondArg ? void 0 : initialValueOrLabel;
|
|
573
|
-
const effectiveLabel = isLabelAsSecondArg ? initialValueOrLabel : label || "anonymous_deferred";
|
|
574
|
-
const deferredValue = (0, import_react.useDeferredValue)(value, actualInitialValue);
|
|
575
|
-
(0, import_react.useEffect)(() => {
|
|
576
|
-
if (config.debug && value !== deferredValue) console.log(`%c [Basis] Value Deferred: "${effectiveLabel}" `, "color: #e67e22; font-weight: bold;");
|
|
577
|
-
}, [value, deferredValue, effectiveLabel]);
|
|
578
|
-
return deferredValue;
|
|
579
|
-
}
|
|
580
|
-
var useId2 = (label) => React.useId();
|
|
581
|
-
var useDebugValue2 = React.useDebugValue;
|
|
582
|
-
var useImperativeHandle2 = React.useImperativeHandle;
|
|
583
|
-
var useInsertionEffect2 = React.useInsertionEffect;
|
|
584
|
-
var useSyncExternalStore = import_react.useSyncExternalStore;
|
|
585
|
-
function use(usable) {
|
|
586
|
-
return (0, import_react.use)(usable);
|
|
587
|
-
}
|
|
588
|
-
function useOptimistic2(passthrough, reducer, label) {
|
|
589
|
-
const effectiveLabel = label || "anonymous_optimistic";
|
|
617
|
+
function useOptimistic(passthrough, reducer, label) {
|
|
618
|
+
const effectiveLabel = (0, import_react.useRef)(label || getFallbackLabel("optimistic")).current;
|
|
590
619
|
(0, import_react.useEffect)(() => {
|
|
591
|
-
registerVariable(effectiveLabel);
|
|
620
|
+
registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
|
|
592
621
|
return () => {
|
|
593
622
|
unregisterVariable(effectiveLabel);
|
|
594
623
|
};
|
|
595
624
|
}, [effectiveLabel]);
|
|
596
|
-
const [state, reactAddOptimistic] =
|
|
625
|
+
const [state, reactAddOptimistic] = React19.useOptimistic(passthrough, reducer);
|
|
597
626
|
const addOptimistic = (0, import_react.useCallback)((payload) => {
|
|
598
627
|
if (recordUpdate(effectiveLabel)) {
|
|
599
628
|
reactAddOptimistic(payload);
|
|
@@ -601,17 +630,13 @@ function useOptimistic2(passthrough, reducer, label) {
|
|
|
601
630
|
}, [effectiveLabel, reactAddOptimistic]);
|
|
602
631
|
return [state, addOptimistic];
|
|
603
632
|
}
|
|
604
|
-
function
|
|
605
|
-
const
|
|
606
|
-
const
|
|
607
|
-
const
|
|
608
|
-
const [state, reactDispatch, isPending] =
|
|
609
|
-
action,
|
|
610
|
-
initialState,
|
|
611
|
-
actualPermalink
|
|
612
|
-
);
|
|
633
|
+
function useActionState(action, initialState, permalink, label) {
|
|
634
|
+
const isLabelArg = typeof permalink === "string" && label === void 0;
|
|
635
|
+
const effectiveLabel = (0, import_react.useRef)(isLabelArg ? permalink : label || getFallbackLabel("action_state")).current;
|
|
636
|
+
const actualPermalink = isLabelArg ? void 0 : permalink;
|
|
637
|
+
const [state, reactDispatch, isPending] = React19.useActionState(action, initialState, actualPermalink);
|
|
613
638
|
(0, import_react.useEffect)(() => {
|
|
614
|
-
registerVariable(effectiveLabel);
|
|
639
|
+
registerVariable(effectiveLabel, { role: "local" /* LOCAL */ });
|
|
615
640
|
return () => {
|
|
616
641
|
unregisterVariable(effectiveLabel);
|
|
617
642
|
};
|
|
@@ -623,6 +648,15 @@ function useActionState2(action, initialState, permalink, label) {
|
|
|
623
648
|
}, [effectiveLabel, reactDispatch]);
|
|
624
649
|
return [state, basisDispatch, isPending];
|
|
625
650
|
}
|
|
651
|
+
var useRef = import_react.useRef;
|
|
652
|
+
var useId2 = React.useId;
|
|
653
|
+
var useDebugValue2 = React.useDebugValue;
|
|
654
|
+
var useImperativeHandle2 = React.useImperativeHandle;
|
|
655
|
+
var useInsertionEffect2 = React.useInsertionEffect;
|
|
656
|
+
var useSyncExternalStore = import_react.useSyncExternalStore;
|
|
657
|
+
var useTransition = import_react.useTransition;
|
|
658
|
+
var useDeferredValue = import_react.useDeferredValue;
|
|
659
|
+
var use = React19.use;
|
|
626
660
|
|
|
627
661
|
// src/context.tsx
|
|
628
662
|
var import_react3 = require("react");
|
|
@@ -674,10 +708,15 @@ var BasisHUD = () => {
|
|
|
674
708
|
const canvasRef = (0, import_react2.useRef)(null);
|
|
675
709
|
(0, import_react2.useEffect)(() => {
|
|
676
710
|
if (!isExpanded) return;
|
|
677
|
-
let animationFrame;
|
|
678
711
|
let isMounted = true;
|
|
712
|
+
let animationFrame = null;
|
|
679
713
|
const draw = () => {
|
|
680
|
-
if (!isMounted)
|
|
714
|
+
if (!isMounted) {
|
|
715
|
+
if (animationFrame !== null) {
|
|
716
|
+
cancelAnimationFrame(animationFrame);
|
|
717
|
+
}
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
681
720
|
const canvas = canvasRef.current;
|
|
682
721
|
if (!canvas) return;
|
|
683
722
|
const ctx = canvas.getContext("2d");
|
|
@@ -685,31 +724,27 @@ var BasisHUD = () => {
|
|
|
685
724
|
const entries = Array.from(history.entries());
|
|
686
725
|
const dpr = window.devicePixelRatio || 1;
|
|
687
726
|
const rawWidth = HUD_DIMENSIONS.WINDOW_SIZE * HUD_DIMENSIONS.COL_WIDTH + HUD_DIMENSIONS.LABEL_WIDTH + HUD_DIMENSIONS.PADDING * 2;
|
|
688
|
-
const rawHeight = Math.max(entries.length * HUD_DIMENSIONS.ROW_HEIGHT + HUD_DIMENSIONS.PADDING * 2,
|
|
727
|
+
const rawHeight = Math.max(entries.length * HUD_DIMENSIONS.ROW_HEIGHT + HUD_DIMENSIONS.PADDING * 2, 80);
|
|
689
728
|
updateCanvasSize(canvas, rawWidth, rawHeight, dpr);
|
|
690
729
|
ctx.save();
|
|
691
730
|
ctx.scale(dpr, dpr);
|
|
692
731
|
ctx.clearRect(0, 0, rawWidth, rawHeight);
|
|
693
|
-
if (entries.length === 0)
|
|
694
|
-
|
|
695
|
-
} else {
|
|
696
|
-
renderMatrix(ctx, entries);
|
|
697
|
-
}
|
|
732
|
+
if (entries.length === 0) renderEmptyState(ctx);
|
|
733
|
+
else renderMatrix(ctx, entries);
|
|
698
734
|
ctx.restore();
|
|
699
735
|
animationFrame = requestAnimationFrame(draw);
|
|
700
736
|
};
|
|
701
|
-
draw
|
|
737
|
+
animationFrame = requestAnimationFrame(draw);
|
|
702
738
|
return () => {
|
|
703
739
|
isMounted = false;
|
|
704
|
-
|
|
740
|
+
if (animationFrame !== null) {
|
|
741
|
+
cancelAnimationFrame(animationFrame);
|
|
742
|
+
}
|
|
705
743
|
};
|
|
706
744
|
}, [isExpanded]);
|
|
707
745
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: getHUDContainerStyle(isExpanded), onClick: () => setIsExpanded(!isExpanded), children: [
|
|
708
746
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(HUDHeader, { isExpanded }),
|
|
709
|
-
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.
|
|
710
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("canvas", { ref: canvasRef, style: { display: "block" } }),
|
|
711
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(HUDFooter, {})
|
|
712
|
-
] })
|
|
747
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "10px 14px 15px 14px" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("canvas", { ref: canvasRef, style: { display: "block" } }) })
|
|
713
748
|
] });
|
|
714
749
|
};
|
|
715
750
|
function updateCanvasSize(canvas, w, h, dpr) {
|
|
@@ -736,18 +771,22 @@ function renderMatrix(ctx, entries) {
|
|
|
736
771
|
const cellH = rowH - 4;
|
|
737
772
|
const gridPath = new Path2D();
|
|
738
773
|
const successPath = new Path2D();
|
|
774
|
+
const contextPath = new Path2D();
|
|
739
775
|
const errorPath = new Path2D();
|
|
740
776
|
ctx.font = "11px Inter, Menlo, monospace";
|
|
741
777
|
let rowIndex = 0;
|
|
742
778
|
for (const [label, meta] of entries) {
|
|
743
779
|
const y = rowIndex * rowH + pad;
|
|
744
|
-
const
|
|
780
|
+
const isContext = meta.role === "context";
|
|
781
|
+
const isRedundant = !isContext && redundantLabels.has(label);
|
|
745
782
|
const { buffer, head } = meta;
|
|
746
783
|
let uiPos = 0;
|
|
747
784
|
const addToPath = (val, xIdx) => {
|
|
748
785
|
const x = xIdx * colW + pad;
|
|
749
786
|
if (val === 1) {
|
|
750
|
-
(
|
|
787
|
+
if (isContext) contextPath.rect(x, y, cellW, cellH);
|
|
788
|
+
else if (isRedundant) errorPath.rect(x, y, cellW, cellH);
|
|
789
|
+
else successPath.rect(x, y, cellW, cellH);
|
|
751
790
|
} else {
|
|
752
791
|
gridPath.rect(x, y, cellW, cellH);
|
|
753
792
|
}
|
|
@@ -756,17 +795,16 @@ function renderMatrix(ctx, entries) {
|
|
|
756
795
|
for (let i = 0; i < head; i++) addToPath(buffer[i], uiPos++);
|
|
757
796
|
const stateName = label.split(" -> ")[1] || label;
|
|
758
797
|
const textX = L * colW + pad + 10;
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
const isVolatile = density > 25;
|
|
762
|
-
ctx.fillStyle = isRedundant ? HUD_THEME.error : isVolatile ? HUD_THEME.success : HUD_THEME.text;
|
|
763
|
-
ctx.fillText((isRedundant ? "! " : isVolatile ? "~ " : "") + stateName, textX, y + 9);
|
|
798
|
+
ctx.fillStyle = isContext ? HUD_THEME.header : isRedundant ? HUD_THEME.error : HUD_THEME.text;
|
|
799
|
+
ctx.fillText((isContext ? "\u03A9 " : isRedundant ? "! " : "") + stateName, textX, y + 9);
|
|
764
800
|
rowIndex++;
|
|
765
801
|
}
|
|
766
802
|
ctx.fillStyle = HUD_THEME.grid;
|
|
767
803
|
ctx.fill(gridPath);
|
|
768
804
|
ctx.fillStyle = HUD_THEME.success;
|
|
769
805
|
ctx.fill(successPath);
|
|
806
|
+
ctx.fillStyle = HUD_THEME.header;
|
|
807
|
+
ctx.fill(contextPath);
|
|
770
808
|
ctx.fillStyle = HUD_THEME.error;
|
|
771
809
|
ctx.fill(errorPath);
|
|
772
810
|
}
|
|
@@ -787,25 +825,7 @@ var HUDHeader = ({ isExpanded }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)
|
|
|
787
825
|
},
|
|
788
826
|
children: [
|
|
789
827
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: isExpanded ? "STATE BASIS MATRIX" : "\u{1F4D0} BASIS ACTIVE" }),
|
|
790
|
-
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.
|
|
791
|
-
]
|
|
792
|
-
}
|
|
793
|
-
);
|
|
794
|
-
var HUDFooter = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
795
|
-
"div",
|
|
796
|
-
{
|
|
797
|
-
style: {
|
|
798
|
-
marginTop: "12px",
|
|
799
|
-
paddingTop: "8px",
|
|
800
|
-
borderTop: `1px solid ${HUD_THEME.grid}`,
|
|
801
|
-
color: HUD_THEME.textDim,
|
|
802
|
-
fontSize: "9px",
|
|
803
|
-
display: "flex",
|
|
804
|
-
justifyContent: "space-between"
|
|
805
|
-
},
|
|
806
|
-
children: [
|
|
807
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "RING BUFFER ENGINE" }),
|
|
808
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "ZERO ALLOC" })
|
|
828
|
+
isExpanded && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { opacity: 0.8, fontSize: "9px" }, children: "v0.5.x" })
|
|
809
829
|
]
|
|
810
830
|
}
|
|
811
831
|
);
|
|
@@ -814,7 +834,11 @@ var HUDFooter = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
|
814
834
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
815
835
|
var BasisContext = (0, import_react3.createContext)({ debug: false });
|
|
816
836
|
var isWeb2 = typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
817
|
-
var BasisProvider = ({
|
|
837
|
+
var BasisProvider = ({
|
|
838
|
+
children,
|
|
839
|
+
debug = true,
|
|
840
|
+
showHUD = true
|
|
841
|
+
}) => {
|
|
818
842
|
(0, import_react3.useLayoutEffect)(() => {
|
|
819
843
|
configureBasis({ debug });
|
|
820
844
|
if (isWeb2) {
|
|
@@ -823,7 +847,7 @@ var BasisProvider = ({ children, debug = true }) => {
|
|
|
823
847
|
}, [debug]);
|
|
824
848
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(BasisContext.Provider, { value: { debug }, children: [
|
|
825
849
|
children,
|
|
826
|
-
debug && isWeb2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BasisHUD, {})
|
|
850
|
+
debug && showHUD && isWeb2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(BasisHUD, {})
|
|
827
851
|
] });
|
|
828
852
|
};
|
|
829
853
|
var useBasisConfig = () => (0, import_react3.useContext)(BasisContext);
|
|
@@ -846,12 +870,14 @@ function basis() {
|
|
|
846
870
|
BasisProvider,
|
|
847
871
|
basis,
|
|
848
872
|
configureBasis,
|
|
873
|
+
createContext,
|
|
849
874
|
getBasisMetrics,
|
|
850
875
|
printBasisHealthReport,
|
|
851
876
|
use,
|
|
852
877
|
useActionState,
|
|
853
878
|
useBasisConfig,
|
|
854
879
|
useCallback,
|
|
880
|
+
useContext,
|
|
855
881
|
useDebugValue,
|
|
856
882
|
useDeferredValue,
|
|
857
883
|
useEffect,
|