@remcostoeten/dev-widget 0.0.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/LICENSE +21 -0
- package/README.md +132 -0
- package/dist/chunk-6OCSDLNS.mjs +16 -0
- package/dist/chunk-6OCSDLNS.mjs.map +1 -0
- package/dist/chunk-VI7WXBU2.mjs +2 -0
- package/dist/chunk-VI7WXBU2.mjs.map +1 -0
- package/dist/chunk-X3LYXERT.mjs +2 -0
- package/dist/chunk-X3LYXERT.mjs.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/dist/internal-Bhwt8k21.d.mts +51 -0
- package/dist/internal-C3TqZPIi.d.ts +51 -0
- package/dist/internal.d.mts +2 -0
- package/dist/internal.d.ts +2 -0
- package/dist/internal.js +2 -0
- package/dist/internal.js.map +1 -0
- package/dist/internal.mjs +1 -0
- package/dist/internal.mjs.map +1 -0
- package/dist/next.d.mts +13 -0
- package/dist/next.d.ts +13 -0
- package/dist/next.js +2 -0
- package/dist/next.js.map +1 -0
- package/dist/next.mjs +2 -0
- package/dist/next.mjs.map +1 -0
- package/dist/public-CgTT_99y.d.mts +365 -0
- package/dist/public-CgTT_99y.d.ts +365 -0
- package/dist/react.d.mts +5 -0
- package/dist/react.d.ts +5 -0
- package/dist/react.js +16 -0
- package/dist/react.js.map +1 -0
- package/dist/react.mjs +2 -0
- package/dist/react.mjs.map +1 -0
- package/dist/routeHandler-CwUVepQp.d.mts +7 -0
- package/dist/routeHandler-DMHcrvQO.d.ts +7 -0
- package/dist/tauri.d.mts +5 -0
- package/dist/tauri.d.ts +5 -0
- package/dist/tauri.js +2 -0
- package/dist/tauri.js.map +1 -0
- package/dist/tauri.mjs +2 -0
- package/dist/tauri.mjs.map +1 -0
- package/package.json +100 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as e,b as t,c as o,d as r,e as i,f as n,g as p,h as f,i as s,j as a}from"./chunk-6OCSDLNS.mjs";import{b as m}from"./chunk-VI7WXBU2.mjs";import{a as u}from"./chunk-X3LYXERT.mjs";export{n as DEFAULTS,a as DevWidget,e as FEATURE_IDS,s as bootstrap,r as createBus,m as createLogHandler,i as createRegistry,f as createRuntime,u as createTauriStorage,p as resolveConfig,t as safeRun,o as safeRunAsync};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { y as EventName, z as EventMap, B as EventListener, C as WidgetDomain, k as FeatureId, G as StateMap, H as TabCategory, I as TabPresenter, R as ResolvedConfig, J as WidgetPlugin, W as WidgetProps } from './public-CgTT_99y.mjs';
|
|
2
|
+
|
|
3
|
+
declare function createBus(): EventBus;
|
|
4
|
+
type EventBus = {
|
|
5
|
+
publish<K extends EventName>(event: K, payload: EventMap[K]): void;
|
|
6
|
+
subscribe<K extends EventName>(event: K, listener: EventListener<K>): () => void;
|
|
7
|
+
clear(): void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
declare function createRegistry(): DomainRegistry;
|
|
11
|
+
type DomainRegistry = {
|
|
12
|
+
registerDomain(domain: WidgetDomain<unknown, unknown>): void;
|
|
13
|
+
unregisterDomain(id: FeatureId): void;
|
|
14
|
+
getDomain<K extends FeatureId>(id: K): WidgetDomain<StateMap[K], unknown> | null;
|
|
15
|
+
listDomains(): FeatureId[];
|
|
16
|
+
markStarted(id: FeatureId): void;
|
|
17
|
+
isStarted(id: FeatureId): boolean;
|
|
18
|
+
registerCategory(category: TabCategory, presenter: TabPresenter): void;
|
|
19
|
+
unregisterCategory(id: string): void;
|
|
20
|
+
getCategories(): {
|
|
21
|
+
category: TabCategory;
|
|
22
|
+
presenter: TabPresenter;
|
|
23
|
+
}[];
|
|
24
|
+
getPresenter(id: string): TabPresenter | null;
|
|
25
|
+
clear(): void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type WidgetRuntime = {
|
|
29
|
+
config: ResolvedConfig;
|
|
30
|
+
bus: EventBus;
|
|
31
|
+
registry: DomainRegistry;
|
|
32
|
+
start(): Promise<void>;
|
|
33
|
+
stop(): Promise<void>;
|
|
34
|
+
registerPlugin(plugin: WidgetPlugin): Promise<void>;
|
|
35
|
+
};
|
|
36
|
+
declare function createRuntime(props: WidgetProps): WidgetRuntime;
|
|
37
|
+
|
|
38
|
+
type ThemeTokens = {
|
|
39
|
+
bg: string;
|
|
40
|
+
bgSecondary: string;
|
|
41
|
+
border: string;
|
|
42
|
+
text: string;
|
|
43
|
+
textMuted: string;
|
|
44
|
+
accent: string;
|
|
45
|
+
accentSoft: string;
|
|
46
|
+
danger: string;
|
|
47
|
+
warning: string;
|
|
48
|
+
success: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { type DomainRegistry as D, type EventBus as E, type ThemeTokens as T, type WidgetRuntime as W, createRegistry as a, createRuntime as b, createBus as c };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { y as EventName, z as EventMap, B as EventListener, C as WidgetDomain, k as FeatureId, G as StateMap, H as TabCategory, I as TabPresenter, R as ResolvedConfig, J as WidgetPlugin, W as WidgetProps } from './public-CgTT_99y.js';
|
|
2
|
+
|
|
3
|
+
declare function createBus(): EventBus;
|
|
4
|
+
type EventBus = {
|
|
5
|
+
publish<K extends EventName>(event: K, payload: EventMap[K]): void;
|
|
6
|
+
subscribe<K extends EventName>(event: K, listener: EventListener<K>): () => void;
|
|
7
|
+
clear(): void;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
declare function createRegistry(): DomainRegistry;
|
|
11
|
+
type DomainRegistry = {
|
|
12
|
+
registerDomain(domain: WidgetDomain<unknown, unknown>): void;
|
|
13
|
+
unregisterDomain(id: FeatureId): void;
|
|
14
|
+
getDomain<K extends FeatureId>(id: K): WidgetDomain<StateMap[K], unknown> | null;
|
|
15
|
+
listDomains(): FeatureId[];
|
|
16
|
+
markStarted(id: FeatureId): void;
|
|
17
|
+
isStarted(id: FeatureId): boolean;
|
|
18
|
+
registerCategory(category: TabCategory, presenter: TabPresenter): void;
|
|
19
|
+
unregisterCategory(id: string): void;
|
|
20
|
+
getCategories(): {
|
|
21
|
+
category: TabCategory;
|
|
22
|
+
presenter: TabPresenter;
|
|
23
|
+
}[];
|
|
24
|
+
getPresenter(id: string): TabPresenter | null;
|
|
25
|
+
clear(): void;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type WidgetRuntime = {
|
|
29
|
+
config: ResolvedConfig;
|
|
30
|
+
bus: EventBus;
|
|
31
|
+
registry: DomainRegistry;
|
|
32
|
+
start(): Promise<void>;
|
|
33
|
+
stop(): Promise<void>;
|
|
34
|
+
registerPlugin(plugin: WidgetPlugin): Promise<void>;
|
|
35
|
+
};
|
|
36
|
+
declare function createRuntime(props: WidgetProps): WidgetRuntime;
|
|
37
|
+
|
|
38
|
+
type ThemeTokens = {
|
|
39
|
+
bg: string;
|
|
40
|
+
bgSecondary: string;
|
|
41
|
+
border: string;
|
|
42
|
+
text: string;
|
|
43
|
+
textMuted: string;
|
|
44
|
+
accent: string;
|
|
45
|
+
accentSoft: string;
|
|
46
|
+
danger: string;
|
|
47
|
+
warning: string;
|
|
48
|
+
success: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export { type DomainRegistry as D, type EventBus as E, type ThemeTokens as T, type WidgetRuntime as W, createRegistry as a, createRuntime as b, createBus as c };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { M as AuthState, B as EventListener, z as EventMap, y as EventName, l as FeatureMap, N as LinkEntry, O as LinksState, Q as PerfState, U as PluginContext, R as ResolvedConfig, V as RouteEntry, X as RoutesState, G as StateMap, Y as SystemState, H as TabCategory, I as TabPresenter, C as WidgetDomain, J as WidgetPlugin } from './public-CgTT_99y.mjs';
|
|
2
|
+
export { D as DomainRegistry, E as EventBus, T as ThemeTokens, W as WidgetRuntime } from './internal-Bhwt8k21.mjs';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { M as AuthState, B as EventListener, z as EventMap, y as EventName, l as FeatureMap, N as LinkEntry, O as LinksState, Q as PerfState, U as PluginContext, R as ResolvedConfig, V as RouteEntry, X as RoutesState, G as StateMap, Y as SystemState, H as TabCategory, I as TabPresenter, C as WidgetDomain, J as WidgetPlugin } from './public-CgTT_99y.js';
|
|
2
|
+
export { D as DomainRegistry, E as EventBus, T as ThemeTokens, W as WidgetRuntime } from './internal-C3TqZPIi.js';
|
package/dist/internal.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var n=Object.defineProperty;var p=Object.getOwnPropertyDescriptor;var i=Object.getOwnPropertyNames;var s=Object.prototype.hasOwnProperty;var m=(t,e,a,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of i(e))!s.call(t,r)&&r!==a&&n(t,r,{get:()=>e[r],enumerable:!(o=p(e,r))||o.enumerable});return t};var y=t=>m(n({},"__esModule",{value:!0}),t);var u={};module.exports=y(u);
|
|
2
|
+
//# sourceMappingURL=internal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal.ts"],"sourcesContent":["export type {\n\tWidgetDomain,\n\tWidgetPlugin,\n\tPluginContext,\n\tTabCategory,\n\tTabPresenter,\n\tResolvedConfig,\n\tEventMap,\n\tEventName,\n\tEventListener,\n\tAuthState,\n\tRoutesState,\n\tLinksState,\n\tPerfState,\n\tSystemState,\n\tStateMap,\n\tRouteEntry,\n\tLinkEntry\n} from './types/internal'\nexport type { EventBus } from './core/eventBus'\nexport type { DomainRegistry } from './core/registry'\nexport type { WidgetRuntime } from './core/widgetRuntime'\nexport type { ThemeTokens } from './shell/themeTokens'\nexport type { FeatureMap } from './types/featureMap'\n"],"mappings":"+WAAA,IAAAA,EAAA,kBAAAC,EAAAD","names":["internal_exports","__toCommonJS"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=internal.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/next.d.mts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { c as createLogHandler } from './routeHandler-CwUVepQp.mjs';
|
|
2
|
+
import { S as StorageProvider } from './public-CgTT_99y.mjs';
|
|
3
|
+
|
|
4
|
+
type RouteDiscoveryHandlerOptions = {
|
|
5
|
+
appRoot?: string;
|
|
6
|
+
};
|
|
7
|
+
declare function createRouteDiscoveryHandler(options?: RouteDiscoveryHandlerOptions): {
|
|
8
|
+
GET: (req: Request) => Response;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
declare function createInMemoryStorage(): StorageProvider;
|
|
12
|
+
|
|
13
|
+
export { type RouteDiscoveryHandlerOptions, createInMemoryStorage, createRouteDiscoveryHandler };
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { c as createLogHandler } from './routeHandler-DMHcrvQO.js';
|
|
2
|
+
import { S as StorageProvider } from './public-CgTT_99y.js';
|
|
3
|
+
|
|
4
|
+
type RouteDiscoveryHandlerOptions = {
|
|
5
|
+
appRoot?: string;
|
|
6
|
+
};
|
|
7
|
+
declare function createRouteDiscoveryHandler(options?: RouteDiscoveryHandlerOptions): {
|
|
8
|
+
GET: (req: Request) => Response;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
declare function createInMemoryStorage(): StorageProvider;
|
|
12
|
+
|
|
13
|
+
export { type RouteDiscoveryHandlerOptions, createInMemoryStorage, createRouteDiscoveryHandler };
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var f=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var D=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var E=(t,o)=>{for(var e in o)f(t,e,{get:o[e],enumerable:!0})},L=(t,o,e,s)=>{if(o&&typeof o=="object"||typeof o=="function")for(let n of D(o))!b.call(t,n)&&n!==e&&f(t,n,{get:()=>o[n],enumerable:!(s=j(o,n))||s.enumerable});return t};var O=t=>L(f({},"__esModule",{value:!0}),t);var I={};E(I,{createInMemoryStorage:()=>p,createLogHandler:()=>y,createRouteDiscoveryHandler:()=>m});module.exports=O(I);function p(){let t=[];async function o(s){t.push(s)}async function e(s){return t.filter(function(r){return!r||typeof r!="object"?!1:Reflect.get(r,"sessionId")===s})}return{appendLog:o,readWindow:e}}function y(t){let o=t??p();async function e(s){try{let r=(await s.json()).events??[];for(let a of r)await o.appendLog(a);let i={success:!0,count:r.length};return new Response(JSON.stringify(i),{status:200,headers:{"Content-Type":"application/json"}})}catch{return new Response(JSON.stringify({success:!1,count:0}),{status:400,headers:{"Content-Type":"application/json"}})}}return{POST:e}}var u=require("fs"),c=require("path");function q(t,o){let e=t.replace(o,"").replace(/\/page\.(tsx?|jsx?)$/,"").replace(/\\/g,"/");return e=e.replace(/\/\([^)]+\)/g,""),e.startsWith("/")||(e="/"+e),e===""&&(e="/"),e}function T(t){return/\[.*\]/.test(t)}function H(t){return t.match(/\/\(([^)]+)\)\//)?.[1]}function d(t,o){let e=new Set,s=[];for(let n of t){let r=q(n,o);if(e.has(r))continue;e.add(r);let i={path:r,sourceFile:n,isDynamic:T(r)},a=H(n);a&&(i.group=a),s.push(i)}return s.sort(function(r,i){return r.path.localeCompare(i.path)})}function l(t,o,e=[]){let s;try{s=(0,u.readdirSync)(t,{encoding:"utf-8"})}catch{return e}for(let n of s){let r=(0,c.join)(t,n),i=!1;try{i=(0,u.statSync)(r).isDirectory()}catch{continue}i?l(r,o,e):o.test(n)&&e.push(r)}return e}function m(t={}){let o=t.appRoot??"src/app";function e(s){try{let r=new URL(s.url).searchParams.get("includeApiRoutes")==="true",i=(0,c.join)(process.cwd(),o),R=l(i,/^page\.(tsx?|jsx?)$/),g=[];r&&(g=l(i,/^route\.(tsx?|jsx?)$/));let h=process.cwd(),x=[...R,...g].map(function(w){return(0,c.relative)(h,w).split(c.sep).join("/")}),v=o.split(c.sep).join("/"),P=d(x,v);return new Response(JSON.stringify({routes:P}),{status:200,headers:{"Content-Type":"application/json"}})}catch(n){let r=n instanceof Error?n.message:"Route discovery failed";return new Response(JSON.stringify({routes:[],error:r}),{status:500,headers:{"Content-Type":"application/json"}})}}return{GET:e}}0&&(module.exports={createInMemoryStorage,createLogHandler,createRouteDiscoveryHandler});
|
|
2
|
+
//# sourceMappingURL=next.js.map
|
package/dist/next.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/next.ts","../src/core/storageAdapter.ts","../src/adapters/next/routeHandler.ts","../src/adapters/next/routeDiscovery.ts","../src/domains/routes/routesDiscovery.ts"],"sourcesContent":["export { createLogHandler } from './adapters/next/routeHandler'\nexport { createRouteDiscoveryHandler } from './adapters/next/routeDiscovery'\nexport { createInMemoryStorage } from './core/storageAdapter'\nexport type { RouteDiscoveryHandlerOptions } from './adapters/next/routeDiscovery'\n","import type { StorageProvider } from '../types/public'\n\n/** Create an in-memory storage provider */\nexport function createInMemoryStorage(): StorageProvider {\n\tconst store: unknown[] = []\n\n\tasync function appendLog(entry: unknown): Promise<void> {\n\t\tstore.push(entry)\n\t}\n\n\tasync function readWindow(windowId: string): Promise<unknown[]> {\n\t\treturn store.filter(function bySession(entry) {\n\t\t\tif (!entry || typeof entry !== 'object') return false\n\t\t\tconst sessionId = Reflect.get(entry, 'sessionId')\n\t\t\treturn sessionId === windowId\n\t\t})\n\t}\n\n\treturn { appendLog, readWindow }\n}\n","import type { PerfEvent } from '../../types/public'\nimport type { StorageProvider } from '../../types/public'\nimport { createInMemoryStorage } from '../../core/storageAdapter'\n\n/** Request body for the perf log endpoint */\nexport type LogRequest = {\n\tevents: PerfEvent[]\n}\n\n/** Response body from the perf log endpoint */\nexport type LogResponse = {\n\tsuccess: boolean\n\tcount: number\n}\n\n/** Create a Next.js route handler for persisting perf events */\nexport function createLogHandler(storage?: StorageProvider): {\n\tPOST: (req: Request) => Promise<Response>\n} {\n\tconst store = storage ?? createInMemoryStorage()\n\n\tasync function POST(req: Request): Promise<Response> {\n\t\ttry {\n\t\t\tconst body = (await req.json()) as LogRequest\n\t\t\tconst events = body.events ?? []\n\t\t\tfor (const event of events) {\n\t\t\t\tawait store.appendLog(event)\n\t\t\t}\n\n\t\t\tconst response: LogResponse = {\n\t\t\t\tsuccess: true,\n\t\t\t\tcount: events.length\n\t\t\t}\n\t\t\treturn new Response(JSON.stringify(response), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t\t})\n\t\t} catch {\n\t\t\treturn new Response(JSON.stringify({ success: false, count: 0 }), {\n\t\t\t\tstatus: 400,\n\t\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t\t})\n\t\t}\n\t}\n\n\treturn { POST }\n}\n","/// <reference types=\"node\" />\nimport { readdirSync, statSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\nimport { parseRoutes } from '../../domains/routes/routesDiscovery'\n\n/** Options for the route discovery handler */\nexport type RouteDiscoveryHandlerOptions = {\n\t/** Root of the Next.js app directory. Default: 'src/app' */\n\tappRoot?: string\n}\n\n/** Recursively collect files matching a pattern */\nfunction walkDir(dir: string, pattern: RegExp, results: string[] = []): string[] {\n\tlet entries: string[]\n\ttry {\n\t\tentries = readdirSync(dir, { encoding: 'utf-8' })\n\t} catch {\n\t\treturn results\n\t}\n\n\tfor (const entry of entries) {\n\t\tconst full = join(dir, entry)\n\t\tlet isDir = false\n\t\ttry {\n\t\t\tisDir = statSync(full).isDirectory()\n\t\t} catch {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (isDir) {\n\t\t\twalkDir(full, pattern, results)\n\t\t} else if (pattern.test(entry)) {\n\t\t\tresults.push(full)\n\t\t}\n\t}\n\n\treturn results\n}\n\n/** Create a Next.js route handler that discovers page routes from the filesystem */\nexport function createRouteDiscoveryHandler(options: RouteDiscoveryHandlerOptions = {}): {\n\tGET: (req: Request) => Response\n} {\n\tconst appRoot = options.appRoot ?? 'src/app'\n\n\tfunction GET(req: Request): Response {\n\t\ttry {\n\t\t\tconst url = new URL(req.url)\n\t\t\tconst includeApi = url.searchParams.get('includeApiRoutes') === 'true'\n\n\t\t\tconst resolvedRoot = join(process.cwd(), appRoot)\n\n\t\t\t// Find page files\n\t\t\tconst pagePattern = /^page\\.(tsx?|jsx?)$/\n\t\t\tconst pageFiles = walkDir(resolvedRoot, pagePattern)\n\n\t\t\t// Optionally find API route files\n\t\t\tlet apiFiles: string[] = []\n\t\t\tif (includeApi) {\n\t\t\t\tconst routePattern = /^route\\.(tsx?|jsx?)$/\n\t\t\t\tapiFiles = walkDir(resolvedRoot, routePattern)\n\t\t\t}\n\n\t\t\t// Normalize paths to use forward slashes and be relative to cwd\n\t\t\tconst cwd = process.cwd()\n\t\t\tconst allFiles = [...pageFiles, ...apiFiles].map(function normalizePath(fp) {\n\t\t\t\treturn relative(cwd, fp).split(sep).join('/')\n\t\t\t})\n\n\t\t\tconst normalizedAppRoot = appRoot.split(sep).join('/')\n\t\t\tconst routes = parseRoutes(allFiles, normalizedAppRoot)\n\n\t\t\treturn new Response(JSON.stringify({ routes }), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t\t})\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Route discovery failed'\n\t\t\treturn new Response(JSON.stringify({ routes: [], error: message }), {\n\t\t\t\tstatus: 500,\n\t\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t\t})\n\t\t}\n\t}\n\n\treturn { GET }\n}\n","import type { RouteEntry } from '../../types/internal'\n\n/** Convert filesystem path to route path */\nexport function toRoutePath(filePath: string, appRoot: string): string {\n\tlet route = filePath\n\t\t.replace(appRoot, '')\n\t\t.replace(/\\/page\\.(tsx?|jsx?)$/, '')\n\t\t.replace(/\\\\/g, '/')\n\n\troute = route.replace(/\\/\\([^)]+\\)/g, '')\n\n\tif (!route.startsWith('/')) {\n\t\troute = '/' + route\n\t}\n\n\tif (route === '') route = '/'\n\n\treturn route\n}\n\n/** Check if a route segment is dynamic */\nexport function isDynamicRoute(route: string): boolean {\n\treturn /\\[.*\\]/.test(route)\n}\n\n/** Extract route group name from path */\nexport function extractGroup(filePath: string): string | undefined {\n\tconst match = filePath.match(/\\/\\(([^)]+)\\)\\//)\n\treturn match?.[1]\n}\n\n/** Parse discovered file paths into route entries */\nexport function parseRoutes(filePaths: string[], appRoot: string): RouteEntry[] {\n\tconst seen = new Set<string>()\n\tconst entries: RouteEntry[] = []\n\n\tfor (const fp of filePaths) {\n\t\tconst path = toRoutePath(fp, appRoot)\n\t\tif (seen.has(path)) continue\n\t\tseen.add(path)\n\n\t\tconst entry: RouteEntry = {\n\t\t\tpath,\n\t\t\tsourceFile: fp,\n\t\t\tisDynamic: isDynamicRoute(path)\n\t\t}\n\t\tconst group = extractGroup(fp)\n\t\tif (group) entry.group = group\n\t\tentries.push(entry)\n\t}\n\n\treturn entries.sort(function sortRoutes(a, b) {\n\t\treturn a.path.localeCompare(b.path)\n\t})\n}\n"],"mappings":"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","names":["next_exports","__export","createInMemoryStorage","createLogHandler","createRouteDiscoveryHandler","__toCommonJS","createInMemoryStorage","store","appendLog","entry","readWindow","windowId","createLogHandler","storage","store","createInMemoryStorage","POST","req","events","event","response","import_node_fs","import_node_path","toRoutePath","filePath","appRoot","route","isDynamicRoute","extractGroup","parseRoutes","filePaths","seen","entries","fp","path","entry","group","a","b","walkDir","dir","pattern","results","entries","entry","full","isDir","createRouteDiscoveryHandler","options","appRoot","GET","req","includeApi","resolvedRoot","pageFiles","apiFiles","cwd","allFiles","fp","normalizedAppRoot","routes","parseRoutes","err","message"]}
|
package/dist/next.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a as D,b as v}from"./chunk-VI7WXBU2.mjs";import{readdirSync as P,statSync as H}from"fs";import{join as f,relative as S,sep as l}from"path";function j(r,n){let t=r.replace(n,"").replace(/\/page\.(tsx?|jsx?)$/,"").replace(/\\/g,"/");return t=t.replace(/\/\([^)]+\)/g,""),t.startsWith("/")||(t="/"+t),t===""&&(t="/"),t}function w(r){return/\[.*\]/.test(r)}function E(r){return r.match(/\/\(([^)]+)\)\//)?.[1]}function u(r,n){let t=new Set,i=[];for(let o of r){let e=j(o,n);if(t.has(e))continue;t.add(e);let s={path:e,sourceFile:o,isDynamic:w(e)},a=E(o);a&&(s.group=a),i.push(s)}return i.sort(function(e,s){return e.path.localeCompare(s.path)})}function c(r,n,t=[]){let i;try{i=P(r,{encoding:"utf-8"})}catch{return t}for(let o of i){let e=f(r,o),s=!1;try{s=H(e).isDirectory()}catch{continue}s?c(e,n,t):n.test(o)&&t.push(e)}return t}function O(r={}){let n=r.appRoot??"src/app";function t(i){try{let e=new URL(i.url).searchParams.get("includeApiRoutes")==="true",s=f(process.cwd(),n),g=c(s,/^page\.(tsx?|jsx?)$/),p=[];e&&(p=c(s,/^route\.(tsx?|jsx?)$/));let y=process.cwd(),R=[...g,...p].map(function(h){return S(y,h).split(l).join("/")}),m=n.split(l).join("/"),d=u(R,m);return new Response(JSON.stringify({routes:d}),{status:200,headers:{"Content-Type":"application/json"}})}catch(o){let e=o instanceof Error?o.message:"Route discovery failed";return new Response(JSON.stringify({routes:[],error:e}),{status:500,headers:{"Content-Type":"application/json"}})}}return{GET:t}}export{D as createInMemoryStorage,v as createLogHandler,O as createRouteDiscoveryHandler};
|
|
2
|
+
//# sourceMappingURL=next.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/adapters/next/routeDiscovery.ts","../src/domains/routes/routesDiscovery.ts"],"sourcesContent":["/// <reference types=\"node\" />\nimport { readdirSync, statSync } from 'node:fs'\nimport { join, relative, sep } from 'node:path'\nimport { parseRoutes } from '../../domains/routes/routesDiscovery'\n\n/** Options for the route discovery handler */\nexport type RouteDiscoveryHandlerOptions = {\n\t/** Root of the Next.js app directory. Default: 'src/app' */\n\tappRoot?: string\n}\n\n/** Recursively collect files matching a pattern */\nfunction walkDir(dir: string, pattern: RegExp, results: string[] = []): string[] {\n\tlet entries: string[]\n\ttry {\n\t\tentries = readdirSync(dir, { encoding: 'utf-8' })\n\t} catch {\n\t\treturn results\n\t}\n\n\tfor (const entry of entries) {\n\t\tconst full = join(dir, entry)\n\t\tlet isDir = false\n\t\ttry {\n\t\t\tisDir = statSync(full).isDirectory()\n\t\t} catch {\n\t\t\tcontinue\n\t\t}\n\n\t\tif (isDir) {\n\t\t\twalkDir(full, pattern, results)\n\t\t} else if (pattern.test(entry)) {\n\t\t\tresults.push(full)\n\t\t}\n\t}\n\n\treturn results\n}\n\n/** Create a Next.js route handler that discovers page routes from the filesystem */\nexport function createRouteDiscoveryHandler(options: RouteDiscoveryHandlerOptions = {}): {\n\tGET: (req: Request) => Response\n} {\n\tconst appRoot = options.appRoot ?? 'src/app'\n\n\tfunction GET(req: Request): Response {\n\t\ttry {\n\t\t\tconst url = new URL(req.url)\n\t\t\tconst includeApi = url.searchParams.get('includeApiRoutes') === 'true'\n\n\t\t\tconst resolvedRoot = join(process.cwd(), appRoot)\n\n\t\t\t// Find page files\n\t\t\tconst pagePattern = /^page\\.(tsx?|jsx?)$/\n\t\t\tconst pageFiles = walkDir(resolvedRoot, pagePattern)\n\n\t\t\t// Optionally find API route files\n\t\t\tlet apiFiles: string[] = []\n\t\t\tif (includeApi) {\n\t\t\t\tconst routePattern = /^route\\.(tsx?|jsx?)$/\n\t\t\t\tapiFiles = walkDir(resolvedRoot, routePattern)\n\t\t\t}\n\n\t\t\t// Normalize paths to use forward slashes and be relative to cwd\n\t\t\tconst cwd = process.cwd()\n\t\t\tconst allFiles = [...pageFiles, ...apiFiles].map(function normalizePath(fp) {\n\t\t\t\treturn relative(cwd, fp).split(sep).join('/')\n\t\t\t})\n\n\t\t\tconst normalizedAppRoot = appRoot.split(sep).join('/')\n\t\t\tconst routes = parseRoutes(allFiles, normalizedAppRoot)\n\n\t\t\treturn new Response(JSON.stringify({ routes }), {\n\t\t\t\tstatus: 200,\n\t\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t\t})\n\t\t} catch (err) {\n\t\t\tconst message = err instanceof Error ? err.message : 'Route discovery failed'\n\t\t\treturn new Response(JSON.stringify({ routes: [], error: message }), {\n\t\t\t\tstatus: 500,\n\t\t\t\theaders: { 'Content-Type': 'application/json' }\n\t\t\t})\n\t\t}\n\t}\n\n\treturn { GET }\n}\n","import type { RouteEntry } from '../../types/internal'\n\n/** Convert filesystem path to route path */\nexport function toRoutePath(filePath: string, appRoot: string): string {\n\tlet route = filePath\n\t\t.replace(appRoot, '')\n\t\t.replace(/\\/page\\.(tsx?|jsx?)$/, '')\n\t\t.replace(/\\\\/g, '/')\n\n\troute = route.replace(/\\/\\([^)]+\\)/g, '')\n\n\tif (!route.startsWith('/')) {\n\t\troute = '/' + route\n\t}\n\n\tif (route === '') route = '/'\n\n\treturn route\n}\n\n/** Check if a route segment is dynamic */\nexport function isDynamicRoute(route: string): boolean {\n\treturn /\\[.*\\]/.test(route)\n}\n\n/** Extract route group name from path */\nexport function extractGroup(filePath: string): string | undefined {\n\tconst match = filePath.match(/\\/\\(([^)]+)\\)\\//)\n\treturn match?.[1]\n}\n\n/** Parse discovered file paths into route entries */\nexport function parseRoutes(filePaths: string[], appRoot: string): RouteEntry[] {\n\tconst seen = new Set<string>()\n\tconst entries: RouteEntry[] = []\n\n\tfor (const fp of filePaths) {\n\t\tconst path = toRoutePath(fp, appRoot)\n\t\tif (seen.has(path)) continue\n\t\tseen.add(path)\n\n\t\tconst entry: RouteEntry = {\n\t\t\tpath,\n\t\t\tsourceFile: fp,\n\t\t\tisDynamic: isDynamicRoute(path)\n\t\t}\n\t\tconst group = extractGroup(fp)\n\t\tif (group) entry.group = group\n\t\tentries.push(entry)\n\t}\n\n\treturn entries.sort(function sortRoutes(a, b) {\n\t\treturn a.path.localeCompare(b.path)\n\t})\n}\n"],"mappings":"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","names":["readdirSync","statSync","join","relative","sep","toRoutePath","filePath","appRoot","route","isDynamicRoute","extractGroup","parseRoutes","filePaths","seen","entries","fp","path","entry","group","a","b","walkDir","dir","pattern","results","entries","readdirSync","entry","full","join","isDir","statSync","createRouteDiscoveryHandler","options","appRoot","GET","req","includeApi","resolvedRoot","pageFiles","apiFiles","cwd","allFiles","fp","relative","sep","normalizedAppRoot","routes","parseRoutes","err","message"]}
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
type MonitorRule = {
|
|
2
|
+
id: string;
|
|
3
|
+
type: 'console' | 'network';
|
|
4
|
+
match: string;
|
|
5
|
+
enabled: boolean;
|
|
6
|
+
};
|
|
7
|
+
type HeaderPair = {
|
|
8
|
+
name: string;
|
|
9
|
+
value: string;
|
|
10
|
+
};
|
|
11
|
+
type BodyInfo = {
|
|
12
|
+
text: string | null;
|
|
13
|
+
size: number;
|
|
14
|
+
truncated: boolean;
|
|
15
|
+
contentType: string | null;
|
|
16
|
+
};
|
|
17
|
+
type ConsoleDetails = {
|
|
18
|
+
type: 'console';
|
|
19
|
+
level: 'log' | 'warn' | 'error';
|
|
20
|
+
args: ReadonlyArray<unknown>;
|
|
21
|
+
};
|
|
22
|
+
type NetworkDetails = {
|
|
23
|
+
type: 'network';
|
|
24
|
+
request: {
|
|
25
|
+
method: string;
|
|
26
|
+
url: string;
|
|
27
|
+
headers: ReadonlyArray<HeaderPair>;
|
|
28
|
+
body?: BodyInfo;
|
|
29
|
+
};
|
|
30
|
+
response?: {
|
|
31
|
+
status: number;
|
|
32
|
+
statusText: string;
|
|
33
|
+
ok: boolean;
|
|
34
|
+
headers: ReadonlyArray<HeaderPair>;
|
|
35
|
+
body?: BodyInfo;
|
|
36
|
+
};
|
|
37
|
+
durationMs: number;
|
|
38
|
+
error?: string;
|
|
39
|
+
};
|
|
40
|
+
type MonitorDetails = ConsoleDetails | NetworkDetails;
|
|
41
|
+
type MonitorMatch = {
|
|
42
|
+
id: string;
|
|
43
|
+
ruleId: string;
|
|
44
|
+
timestamp: number;
|
|
45
|
+
content: string;
|
|
46
|
+
details?: MonitorDetails;
|
|
47
|
+
};
|
|
48
|
+
type MonitorState = {
|
|
49
|
+
rules: ReadonlyArray<MonitorRule>;
|
|
50
|
+
matches: ReadonlyArray<MonitorMatch>;
|
|
51
|
+
isListening: boolean;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
type AuthState = {
|
|
55
|
+
provider: string;
|
|
56
|
+
authenticated: boolean;
|
|
57
|
+
confidence: AuthConfidence;
|
|
58
|
+
session: AuthSession | null;
|
|
59
|
+
error: string | null;
|
|
60
|
+
};
|
|
61
|
+
type RouteEntry = {
|
|
62
|
+
path: string;
|
|
63
|
+
sourceFile: string;
|
|
64
|
+
isDynamic: boolean;
|
|
65
|
+
group?: string;
|
|
66
|
+
};
|
|
67
|
+
type LinkEntry = {
|
|
68
|
+
target: string;
|
|
69
|
+
sourceFile: string;
|
|
70
|
+
sourceType: 'next-link' | 'router-push' | 'anchor' | 'markdown';
|
|
71
|
+
};
|
|
72
|
+
type LinkDiagnostic = 'missing-route-target' | 'dynamic-route-unresolved' | 'relative-link-ambiguity' | 'external-link-without-rel';
|
|
73
|
+
type RoutesState = {
|
|
74
|
+
routes: ReadonlyArray<RouteEntry>;
|
|
75
|
+
loading: boolean;
|
|
76
|
+
error: string | null;
|
|
77
|
+
};
|
|
78
|
+
type LinksState = {
|
|
79
|
+
links: ReadonlyArray<LinkEntry>;
|
|
80
|
+
diagnostics: ReadonlyArray<{
|
|
81
|
+
link: LinkEntry;
|
|
82
|
+
issue: LinkDiagnostic;
|
|
83
|
+
}>;
|
|
84
|
+
loading: boolean;
|
|
85
|
+
};
|
|
86
|
+
type PerfState = {
|
|
87
|
+
fps: number;
|
|
88
|
+
isScrolling: boolean;
|
|
89
|
+
scrollFps: number;
|
|
90
|
+
events: ReadonlyArray<PerfEvent>;
|
|
91
|
+
hourlyCount: number;
|
|
92
|
+
analysisRunning: boolean;
|
|
93
|
+
lastReport: string | null;
|
|
94
|
+
};
|
|
95
|
+
type SystemState = {
|
|
96
|
+
userAgent: string;
|
|
97
|
+
env: string;
|
|
98
|
+
viewport: {
|
|
99
|
+
w: number;
|
|
100
|
+
h: number;
|
|
101
|
+
};
|
|
102
|
+
hydrationErrors: ReadonlyArray<{
|
|
103
|
+
id: string;
|
|
104
|
+
message: string;
|
|
105
|
+
serverContent: string | null;
|
|
106
|
+
clientContent: string | null;
|
|
107
|
+
componentStack: string | null;
|
|
108
|
+
timestamp: number;
|
|
109
|
+
}>;
|
|
110
|
+
};
|
|
111
|
+
type StateMap = {
|
|
112
|
+
auth: AuthState;
|
|
113
|
+
routes: RoutesState;
|
|
114
|
+
performance: PerfState;
|
|
115
|
+
system: SystemState;
|
|
116
|
+
links: LinksState;
|
|
117
|
+
monitor: MonitorState;
|
|
118
|
+
};
|
|
119
|
+
type EventMap = {
|
|
120
|
+
'auth/state-changed': {
|
|
121
|
+
provider: string;
|
|
122
|
+
authenticated: boolean;
|
|
123
|
+
};
|
|
124
|
+
'auth/sign-out': Record<string, never>;
|
|
125
|
+
'routes/discovered': {
|
|
126
|
+
count: number;
|
|
127
|
+
routes: ReadonlyArray<RouteEntry>;
|
|
128
|
+
};
|
|
129
|
+
'links/validated': {
|
|
130
|
+
total: number;
|
|
131
|
+
broken: number;
|
|
132
|
+
};
|
|
133
|
+
'performance/drop-detected': {
|
|
134
|
+
fps: number;
|
|
135
|
+
reasons: string[];
|
|
136
|
+
};
|
|
137
|
+
'performance/analysis-complete': {
|
|
138
|
+
reportId: string;
|
|
139
|
+
};
|
|
140
|
+
'system/updated': {
|
|
141
|
+
key: string;
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
type EventName = keyof EventMap;
|
|
145
|
+
type EventListener<K extends EventName> = (payload: EventMap[K]) => void;
|
|
146
|
+
type WidgetDomain<TState, TConfig> = {
|
|
147
|
+
id: FeatureId;
|
|
148
|
+
setup(config: TConfig): void | Promise<void>;
|
|
149
|
+
start(): void | Promise<void>;
|
|
150
|
+
stop(): void | Promise<void>;
|
|
151
|
+
getState(): TState;
|
|
152
|
+
subscribe(listener: (state: TState) => void): () => void;
|
|
153
|
+
serializeDiagnostics?(): Record<string, unknown>;
|
|
154
|
+
runHealthCheck?(): boolean;
|
|
155
|
+
reset?(): void;
|
|
156
|
+
};
|
|
157
|
+
type TabCategory = {
|
|
158
|
+
id: string;
|
|
159
|
+
label: string;
|
|
160
|
+
icon?: string;
|
|
161
|
+
order?: number;
|
|
162
|
+
group?: string;
|
|
163
|
+
enabled?: boolean;
|
|
164
|
+
badgeCount?: number;
|
|
165
|
+
};
|
|
166
|
+
type TabPresenter<TState = unknown> = {
|
|
167
|
+
render: (state: TState) => React.ReactNode;
|
|
168
|
+
getAriaLabel?: (state: TState) => string;
|
|
169
|
+
};
|
|
170
|
+
type PluginContext = {
|
|
171
|
+
registerDomain(domain: WidgetDomain<unknown, unknown>): void;
|
|
172
|
+
registerCategory(category: TabCategory, presenter: TabPresenter): void;
|
|
173
|
+
onEvent<K extends EventName>(event: K, listener: EventListener<K>): () => void;
|
|
174
|
+
};
|
|
175
|
+
type WidgetPlugin = {
|
|
176
|
+
id: string;
|
|
177
|
+
version: string;
|
|
178
|
+
register(ctx: PluginContext): void | Promise<void>;
|
|
179
|
+
};
|
|
180
|
+
type ResolvedConfig = {
|
|
181
|
+
enabled: boolean;
|
|
182
|
+
mode: 'development-only' | 'always';
|
|
183
|
+
theme: Required<ThemeConfig>;
|
|
184
|
+
features: Record<FeatureId, {
|
|
185
|
+
enabled: boolean;
|
|
186
|
+
} & Record<string, unknown>>;
|
|
187
|
+
keyboard: Required<KeyboardConfig>;
|
|
188
|
+
accessibility: Required<A11yConfig>;
|
|
189
|
+
rightRail: Required<Omit<RailConfig, 'panels'>> & {
|
|
190
|
+
panels: PanelConfig[];
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
declare const FEATURE_IDS: readonly ["auth", "routes", "performance", "system", "links", "monitor"];
|
|
195
|
+
type FeatureId = (typeof FEATURE_IDS)[number];
|
|
196
|
+
type FeatureBase = {
|
|
197
|
+
enabled?: boolean;
|
|
198
|
+
};
|
|
199
|
+
type AuthOptions = FeatureBase & {
|
|
200
|
+
provider?: 'better-auth' | 'cookie' | 'jwt' | 'custom';
|
|
201
|
+
};
|
|
202
|
+
type RoutesOptions = FeatureBase & {
|
|
203
|
+
appRoot?: string;
|
|
204
|
+
endpoint?: string;
|
|
205
|
+
includeApiRoutes?: boolean;
|
|
206
|
+
includeDynamic?: boolean;
|
|
207
|
+
};
|
|
208
|
+
type PerfOptions = FeatureBase & {
|
|
209
|
+
fpsThreshold?: number;
|
|
210
|
+
hourlyIssueThreshold?: number;
|
|
211
|
+
captureReactCommits?: boolean;
|
|
212
|
+
captureLongTasks?: boolean;
|
|
213
|
+
};
|
|
214
|
+
type SystemOptions = FeatureBase & {
|
|
215
|
+
includeUserAgent?: boolean;
|
|
216
|
+
includeEnv?: boolean;
|
|
217
|
+
};
|
|
218
|
+
type LinksOptions = FeatureBase & {
|
|
219
|
+
includeExternal?: boolean;
|
|
220
|
+
validateInternal?: boolean;
|
|
221
|
+
extractLinks?: () => Promise<LinkEntry[]>;
|
|
222
|
+
};
|
|
223
|
+
type MonitorOptions = FeatureBase & {};
|
|
224
|
+
type FeatureMap = {
|
|
225
|
+
auth: AuthOptions;
|
|
226
|
+
routes: RoutesOptions;
|
|
227
|
+
performance: PerfOptions;
|
|
228
|
+
system: SystemOptions;
|
|
229
|
+
links: LinksOptions;
|
|
230
|
+
monitor: MonitorOptions;
|
|
231
|
+
};
|
|
232
|
+
type FeatureConfig = {
|
|
233
|
+
[K in keyof FeatureMap]?: boolean | FeatureMap[K];
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
type ThemeMode = 'system' | 'light' | 'dark';
|
|
237
|
+
type Density = 'compact' | 'comfortable';
|
|
238
|
+
type RadiusScale = 'none' | 'sm' | 'md' | 'lg';
|
|
239
|
+
type AuthConfidence = 'confirmed' | 'inferred' | 'unknown';
|
|
240
|
+
type Severity = 'low' | 'medium' | 'high';
|
|
241
|
+
type ThemeConfig = {
|
|
242
|
+
mode?: ThemeMode;
|
|
243
|
+
accent?: string;
|
|
244
|
+
density?: Density;
|
|
245
|
+
radius?: RadiusScale;
|
|
246
|
+
};
|
|
247
|
+
type AuthConfig = {
|
|
248
|
+
provider: 'better-auth' | 'cookie' | 'jwt' | 'custom';
|
|
249
|
+
options?: Record<string, unknown>;
|
|
250
|
+
customProvider?: AuthProvider;
|
|
251
|
+
};
|
|
252
|
+
type AuthSession = {
|
|
253
|
+
userId: string;
|
|
254
|
+
email?: string;
|
|
255
|
+
role?: string;
|
|
256
|
+
image?: string;
|
|
257
|
+
expiresAt?: string;
|
|
258
|
+
};
|
|
259
|
+
type AuthProvider = {
|
|
260
|
+
id: string;
|
|
261
|
+
getSession(): Promise<AuthSession | null>;
|
|
262
|
+
signOut?(): Promise<void>;
|
|
263
|
+
purge?(): Promise<void>;
|
|
264
|
+
};
|
|
265
|
+
type StorageProvider = {
|
|
266
|
+
appendLog(entry: unknown): Promise<void>;
|
|
267
|
+
readWindow(windowId: string): Promise<unknown[]>;
|
|
268
|
+
};
|
|
269
|
+
type AnalysisInput = {
|
|
270
|
+
events: ReadonlyArray<PerfEvent>;
|
|
271
|
+
route?: string;
|
|
272
|
+
suspects?: ReadonlyArray<string>;
|
|
273
|
+
};
|
|
274
|
+
type AnalysisOutput = {
|
|
275
|
+
summary: string;
|
|
276
|
+
hotspots: ReadonlyArray<string>;
|
|
277
|
+
suggestions: ReadonlyArray<string>;
|
|
278
|
+
confidence: number;
|
|
279
|
+
};
|
|
280
|
+
type AiProvider = {
|
|
281
|
+
analyze(input: AnalysisInput): Promise<AnalysisOutput>;
|
|
282
|
+
};
|
|
283
|
+
type StorageConfig = {
|
|
284
|
+
type: 'jsonl' | 'sqlite' | 'external';
|
|
285
|
+
options?: Record<string, unknown>;
|
|
286
|
+
};
|
|
287
|
+
type AiConfig = {
|
|
288
|
+
provider: 'rules' | 'openai' | 'local' | 'custom';
|
|
289
|
+
model?: string;
|
|
290
|
+
maxTokens?: number;
|
|
291
|
+
enableRedaction?: boolean;
|
|
292
|
+
customProvider?: AiProvider;
|
|
293
|
+
};
|
|
294
|
+
type KeyboardConfig = {
|
|
295
|
+
toggleKey?: string;
|
|
296
|
+
enableShortcuts?: boolean;
|
|
297
|
+
};
|
|
298
|
+
type A11yConfig = {
|
|
299
|
+
reducedMotion?: 'system' | 'always' | 'never';
|
|
300
|
+
announceUpdates?: boolean;
|
|
301
|
+
};
|
|
302
|
+
type PanelConfig = {
|
|
303
|
+
id: string;
|
|
304
|
+
label: string;
|
|
305
|
+
icon: string;
|
|
306
|
+
enabled?: boolean;
|
|
307
|
+
order?: number;
|
|
308
|
+
badgeCount?: number;
|
|
309
|
+
};
|
|
310
|
+
type RailConfig = {
|
|
311
|
+
enabled?: boolean;
|
|
312
|
+
defaultPanel?: string | null;
|
|
313
|
+
panels?: PanelConfig[];
|
|
314
|
+
collapsible?: boolean;
|
|
315
|
+
};
|
|
316
|
+
type EventType = 'fps_drop' | 'long_task' | 'react_commit_burst' | 'dom_mutation_burst' | 'scroll_pressure' | 'route_transition_slow' | 'hydration_warning';
|
|
317
|
+
type PerfMetrics = {
|
|
318
|
+
fps?: number;
|
|
319
|
+
frameWindowMs?: number;
|
|
320
|
+
longTaskDurationMs?: number;
|
|
321
|
+
commitCount?: number;
|
|
322
|
+
mutationCount?: number;
|
|
323
|
+
scrollEventCount?: number;
|
|
324
|
+
};
|
|
325
|
+
type PerfSuspects = {
|
|
326
|
+
components?: string[];
|
|
327
|
+
files?: string[];
|
|
328
|
+
};
|
|
329
|
+
type PerfContext = {
|
|
330
|
+
userAgent?: string;
|
|
331
|
+
viewport?: {
|
|
332
|
+
w: number;
|
|
333
|
+
h: number;
|
|
334
|
+
};
|
|
335
|
+
branch?: string;
|
|
336
|
+
commitSha?: string;
|
|
337
|
+
};
|
|
338
|
+
type PerfEvent = {
|
|
339
|
+
id: string;
|
|
340
|
+
timestamp: string;
|
|
341
|
+
sessionId: string;
|
|
342
|
+
route: string;
|
|
343
|
+
eventType: EventType;
|
|
344
|
+
severity: Severity;
|
|
345
|
+
metrics: PerfMetrics;
|
|
346
|
+
suspects?: PerfSuspects;
|
|
347
|
+
context: PerfContext;
|
|
348
|
+
};
|
|
349
|
+
type WidgetProps = {
|
|
350
|
+
enabled?: boolean;
|
|
351
|
+
mode?: 'development-only' | 'always';
|
|
352
|
+
theme?: ThemeConfig;
|
|
353
|
+
features?: FeatureConfig;
|
|
354
|
+
disable?: FeatureId[];
|
|
355
|
+
providers?: {
|
|
356
|
+
auth?: AuthConfig;
|
|
357
|
+
ai?: AiConfig;
|
|
358
|
+
storage?: StorageConfig;
|
|
359
|
+
};
|
|
360
|
+
keyboard?: KeyboardConfig;
|
|
361
|
+
accessibility?: A11yConfig;
|
|
362
|
+
rightRail?: RailConfig;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
export { type A11yConfig as A, type EventListener as B, type WidgetDomain as C, type Density as D, type EventType as E, FEATURE_IDS as F, type StateMap as G, type TabCategory as H, type TabPresenter as I, type WidgetPlugin as J, type KeyboardConfig as K, type LinksOptions as L, type AuthState as M, type LinkEntry as N, type LinksState as O, type PanelConfig as P, type PerfState as Q, type ResolvedConfig as R, type StorageProvider as S, type ThemeConfig as T, type PluginContext as U, type RouteEntry as V, type WidgetProps as W, type RoutesState as X, type SystemState as Y, type AiConfig as a, type AiProvider as b, type AnalysisInput as c, type AnalysisOutput as d, type AuthConfidence as e, type AuthConfig as f, type AuthOptions as g, type AuthProvider as h, type AuthSession as i, type FeatureConfig as j, type FeatureId as k, type FeatureMap as l, type PerfContext as m, type PerfEvent as n, type PerfMetrics as o, type PerfOptions as p, type PerfSuspects as q, type RadiusScale as r, type RailConfig as s, type RoutesOptions as t, type Severity as u, type StorageConfig as v, type SystemOptions as w, type ThemeMode as x, type EventName as y, type EventMap as z };
|