tina4-nodejs 3.11.18 → 3.11.19
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/CLAUDE.md +1 -1
- package/package.json +1 -1
- package/packages/core/public/js/tina4-dev-admin.js +121 -121
- package/packages/core/public/js/tina4-dev-admin.min.js +121 -121
- package/packages/core/src/devAdmin.ts +119 -1
- package/packages/core/src/docs.ts +1231 -0
- package/packages/core/src/docsAutoDiscovery.ts +73 -0
- package/packages/core/src/index.ts +3 -0
- package/packages/core/src/mcp.ts +67 -0
- package/packages/core/src/server.ts +7 -0
|
@@ -565,6 +565,12 @@ export class DevAdmin {
|
|
|
565
565
|
{ method: "GET", pattern: "/__dev/api/index/search", handler: handleIndexSearch },
|
|
566
566
|
{ method: "GET", pattern: "/__dev/api/index/file", handler: handleIndexFile },
|
|
567
567
|
{ method: "GET", pattern: "/__dev/api/index/overview", handler: handleIndexOverview },
|
|
568
|
+
// Live API RAG (Docs) — see plan/v3/22-LIVE-API-RAG.md
|
|
569
|
+
{ method: "GET", pattern: "/__dev/api/docs/search", handler: handleDocsSearch },
|
|
570
|
+
{ method: "GET", pattern: "/__dev/api/docs/class", handler: handleDocsClass },
|
|
571
|
+
{ method: "GET", pattern: "/__dev/api/docs/method", handler: handleDocsMethod },
|
|
572
|
+
{ method: "GET", pattern: "/__dev/api/docs/index", handler: handleDocsIndex },
|
|
573
|
+
{ method: "GET", pattern: "/__dev/api/docs/.well-known.json", handler: handleDocsWellKnown },
|
|
568
574
|
// JS asset
|
|
569
575
|
{ method: "GET", pattern: "/__dev/js/tina4-dev-admin.min.js", handler: handleDevAdminJs },
|
|
570
576
|
];
|
|
@@ -1869,6 +1875,73 @@ const handleIndexOverview: RouteHandler = async (_req, res) => {
|
|
|
1869
1875
|
res.json(ProjectIndex.overview());
|
|
1870
1876
|
};
|
|
1871
1877
|
|
|
1878
|
+
// ---------------------------------------------------------------------------
|
|
1879
|
+
// Live API RAG (Docs) — plan/v3/22-LIVE-API-RAG.md
|
|
1880
|
+
// ---------------------------------------------------------------------------
|
|
1881
|
+
|
|
1882
|
+
const handleDocsSearch: RouteHandler = async (req, res) => {
|
|
1883
|
+
const { Docs } = await import("./docs.js");
|
|
1884
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
1885
|
+
const q = url.searchParams.get("q") ?? "";
|
|
1886
|
+
const k = parseInt(url.searchParams.get("k") ?? "5", 10);
|
|
1887
|
+
const source = url.searchParams.get("source") ?? "all";
|
|
1888
|
+
const includePrivate = isTruthy(url.searchParams.get("include_private") ?? "false");
|
|
1889
|
+
const start = Date.now();
|
|
1890
|
+
const results = Docs.mcpSearch(q, k, undefined, source, includePrivate);
|
|
1891
|
+
res.json({ ok: true, query: q, results, took_ms: Date.now() - start });
|
|
1892
|
+
};
|
|
1893
|
+
|
|
1894
|
+
const handleDocsClass: RouteHandler = async (req, res) => {
|
|
1895
|
+
const { Docs } = await import("./docs.js");
|
|
1896
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
1897
|
+
const name = url.searchParams.get("name") ?? "";
|
|
1898
|
+
const spec = Docs.mcpClass(name);
|
|
1899
|
+
if (!spec) {
|
|
1900
|
+
res.json({ ok: false, error: `class not found: ${name}` }, 404);
|
|
1901
|
+
return;
|
|
1902
|
+
}
|
|
1903
|
+
res.json({ ok: true, class: spec });
|
|
1904
|
+
};
|
|
1905
|
+
|
|
1906
|
+
const handleDocsMethod: RouteHandler = async (req, res) => {
|
|
1907
|
+
const { Docs } = await import("./docs.js");
|
|
1908
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
1909
|
+
const cls = url.searchParams.get("class") ?? "";
|
|
1910
|
+
const name = url.searchParams.get("name") ?? "";
|
|
1911
|
+
const spec = Docs.mcpMethod(cls, name);
|
|
1912
|
+
if (!spec) {
|
|
1913
|
+
res.json({ ok: false, error: `method not found: ${cls}.${name}` }, 404);
|
|
1914
|
+
return;
|
|
1915
|
+
}
|
|
1916
|
+
res.json({ ok: true, method: spec });
|
|
1917
|
+
};
|
|
1918
|
+
|
|
1919
|
+
const handleDocsIndex: RouteHandler = async (req, res) => {
|
|
1920
|
+
const { Docs } = await import("./docs.js");
|
|
1921
|
+
const url = new URL(req.url ?? "/", "http://localhost");
|
|
1922
|
+
const source = url.searchParams.get("source") ?? "all";
|
|
1923
|
+
const docs = new (Docs as any)(process.cwd());
|
|
1924
|
+
let entries: any[] = docs.index();
|
|
1925
|
+
if (source !== "all") entries = entries.filter((e) => e.source === source);
|
|
1926
|
+
res.json({ ok: true, count: entries.length, entries });
|
|
1927
|
+
};
|
|
1928
|
+
|
|
1929
|
+
const handleDocsWellKnown: RouteHandler = async (_req, res) => {
|
|
1930
|
+
res.json({
|
|
1931
|
+
ok: true,
|
|
1932
|
+
name: "tina4-live-docs",
|
|
1933
|
+
description: "Live API docs for this Tina4 project (framework + user code)",
|
|
1934
|
+
spec: "plan/v3/22-LIVE-API-RAG.md",
|
|
1935
|
+
endpoints: {
|
|
1936
|
+
search: "/__dev/api/docs/search?q=<query>&k=<int>&source=<framework|user|all>&include_private=<bool>",
|
|
1937
|
+
class: "/__dev/api/docs/class?name=<fqn>",
|
|
1938
|
+
method: "/__dev/api/docs/method?class=<fqn>&name=<method>",
|
|
1939
|
+
index: "/__dev/api/docs/index?source=<framework|user|all>",
|
|
1940
|
+
},
|
|
1941
|
+
mcp_tools: ["api_search", "api_class", "api_method"],
|
|
1942
|
+
});
|
|
1943
|
+
};
|
|
1944
|
+
|
|
1872
1945
|
// ---------------------------------------------------------------------------
|
|
1873
1946
|
// Dev Admin JS handler — serves the shared JS file
|
|
1874
1947
|
// ---------------------------------------------------------------------------
|
|
@@ -1934,10 +2007,55 @@ function renderToolbarHtml(ctx: {
|
|
|
1934
2007
|
<span style="color:#ffeb3b;">req:${ctx.requestId}</span>
|
|
1935
2008
|
<span style="color:#90caf9;">${ctx.routeCount} routes</span>
|
|
1936
2009
|
<span style="color:#888;">Node.js ${nodeVersion}</span>
|
|
1937
|
-
<a href="#" onclick="
|
|
2010
|
+
<a href="#" onclick="window.__tina4ToggleOverlay(event)" style="color:#ef9a9a;margin-left:auto;text-decoration:none;cursor:pointer;">Dashboard ↗</a>
|
|
1938
2011
|
<span onclick="this.parentElement.style.display='none'" style="cursor:pointer;color:#888;margin-left:8px;">✕</span>
|
|
1939
2012
|
</div>
|
|
1940
2013
|
<script>
|
|
2014
|
+
// Overlay open/toggle helper + auto-restore. Persist the dev-admin
|
|
2015
|
+
// iframe's open/closed state across parent reloads so saving a file
|
|
2016
|
+
// doesn't lose the user's dev-admin context. Cross-framework parity
|
|
2017
|
+
// with PHP / Python / Ruby — same localStorage key.
|
|
2018
|
+
(function(){
|
|
2019
|
+
var STATE_KEY = 'tina4_dev_overlay_open';
|
|
2020
|
+
function buildOverlay() {
|
|
2021
|
+
var c = document.createElement('div');
|
|
2022
|
+
c.id = 'tina4-dev-panel';
|
|
2023
|
+
c.style.cssText = 'position:fixed;top:3rem;left:0;right:0;bottom:2rem;z-index:99998;transition:all 0.2s';
|
|
2024
|
+
var f = document.createElement('iframe');
|
|
2025
|
+
f.src = '/__dev';
|
|
2026
|
+
f.style.cssText = 'width:100%;height:100%;border:1px solid #2e7d32;border-radius:0.5rem;box-shadow:0 8px 32px rgba(0,0,0,0.5);background:#0f172a';
|
|
2027
|
+
c.appendChild(f);
|
|
2028
|
+
document.body.appendChild(c);
|
|
2029
|
+
return c;
|
|
2030
|
+
}
|
|
2031
|
+
window.__tina4ToggleOverlay = function(e) {
|
|
2032
|
+
if (e) e.preventDefault();
|
|
2033
|
+
var p = document.getElementById('tina4-dev-panel');
|
|
2034
|
+
if (p) {
|
|
2035
|
+
var hide = p.style.display !== 'none';
|
|
2036
|
+
p.style.display = hide ? 'none' : 'block';
|
|
2037
|
+
try { localStorage.setItem(STATE_KEY, hide ? '0' : '1'); } catch (_) {}
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
buildOverlay();
|
|
2041
|
+
try { localStorage.setItem(STATE_KEY, '1'); } catch (_) {}
|
|
2042
|
+
};
|
|
2043
|
+
function restoreIfOpen() {
|
|
2044
|
+
try {
|
|
2045
|
+
if (location.pathname.indexOf('/__dev') === 0) return;
|
|
2046
|
+
if (localStorage.getItem(STATE_KEY) === '1' && !document.getElementById('tina4-dev-panel')) {
|
|
2047
|
+
buildOverlay();
|
|
2048
|
+
}
|
|
2049
|
+
} catch (_) {}
|
|
2050
|
+
}
|
|
2051
|
+
if (document.readyState === 'loading') {
|
|
2052
|
+
document.addEventListener('DOMContentLoaded', restoreIfOpen);
|
|
2053
|
+
} else {
|
|
2054
|
+
restoreIfOpen();
|
|
2055
|
+
}
|
|
2056
|
+
})();
|
|
2057
|
+
</script>
|
|
2058
|
+
<script>
|
|
1941
2059
|
function tina4VersionModal(){
|
|
1942
2060
|
var m=document.getElementById('tina4-ver-modal');
|
|
1943
2061
|
if(m.style.display==='block'){m.style.display='none';return;}
|