tina4-nodejs 3.13.110 → 3.13.112
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 +2 -2
- package/package.json +1 -1
- package/packages/cli/dist/bin.js +951 -153
- package/packages/core/dist/index.js +951 -153
- package/packages/core/src/devAdmin.ts +181 -145
- package/packages/core/src/server.ts +6 -0
- package/packages/orm/dist/index.js +958 -150
- package/packages/orm/src/graph/adapters/arango.ts +256 -0
- package/packages/orm/src/graph/adapters/bolt.ts +259 -0
- package/packages/orm/src/graph/adapters/ultipa.ts +271 -0
- package/packages/orm/src/graph/connectTimeout.ts +39 -0
- package/packages/orm/src/graph/errors.ts +29 -0
- package/packages/orm/src/graph/graphAdapter.ts +53 -0
- package/packages/orm/src/graph/graphDatabase.ts +114 -0
- package/packages/orm/src/graph/graphUrl.ts +98 -0
- package/packages/orm/src/graph/shapes.ts +95 -0
- package/packages/orm/src/index.ts +137 -115
- package/types/core/src/devAdmin.d.ts +1 -0
- package/types/orm/src/graph/adapters/arango.d.ts +42 -0
- package/types/orm/src/graph/adapters/bolt.d.ts +43 -0
- package/types/orm/src/graph/adapters/ultipa.d.ts +39 -0
- package/types/orm/src/graph/connectTimeout.d.ts +12 -0
- package/types/orm/src/graph/errors.d.ts +21 -0
- package/types/orm/src/graph/graphAdapter.d.ts +38 -0
- package/types/orm/src/graph/graphDatabase.d.ts +44 -0
- package/types/orm/src/graph/graphUrl.d.ts +28 -0
- package/types/orm/src/graph/shapes.d.ts +37 -0
- package/types/orm/src/index.d.ts +8 -0
|
@@ -21192,47 +21192,120 @@ function renderToolbarHtml(ctx) {
|
|
|
21192
21192
|
const method = escapeHtml(ctx.method);
|
|
21193
21193
|
const path8 = escapeHtml(ctx.path);
|
|
21194
21194
|
const matchedPattern = escapeHtml(ctx.matchedPattern);
|
|
21195
|
-
|
|
21196
|
-
|
|
21197
|
-
|
|
21198
|
-
|
|
21199
|
-
|
|
21200
|
-
|
|
21195
|
+
const reload = ctx.reload === false ? "0" : "1";
|
|
21196
|
+
return `<link rel="stylesheet" href="/__dev/toolbar.css">
|
|
21197
|
+
<div id="tina4-dev-toolbar" data-reload="${reload}">
|
|
21198
|
+
<span id="tina4-ver-btn" title="Click to check for updates">Tina4 v${ctx.version}</span>
|
|
21199
|
+
<div id="tina4-ver-modal">
|
|
21200
|
+
<div class="t4-modal-head">
|
|
21201
|
+
<strong class="t4-modal-title">Version Info</strong>
|
|
21202
|
+
<span id="tina4-ver-close" class="t4-x">×</span>
|
|
21201
21203
|
</div>
|
|
21202
|
-
<div id="tina4-ver-body"
|
|
21203
|
-
<div>Current: <strong
|
|
21204
|
-
<div id="tina4-ver-latest"
|
|
21204
|
+
<div id="tina4-ver-body">
|
|
21205
|
+
<div>Current: <strong class="t4-ok">v${ctx.version}</strong></div>
|
|
21206
|
+
<div id="tina4-ver-latest" class="t4-dim">Checking for updates...</div>
|
|
21205
21207
|
</div>
|
|
21206
21208
|
</div>
|
|
21207
|
-
<span
|
|
21209
|
+
<span class="t4-green">${method}</span>
|
|
21208
21210
|
<span>${path8}</span>
|
|
21209
|
-
<span
|
|
21210
|
-
<span
|
|
21211
|
-
<span
|
|
21212
|
-
<span
|
|
21213
|
-
<a href="#"
|
|
21214
|
-
<span
|
|
21211
|
+
<span class="t4-arrow">→ ${matchedPattern}</span>
|
|
21212
|
+
<span class="t4-yellow">req:${ctx.requestId}</span>
|
|
21213
|
+
<span class="t4-blue">${ctx.routeCount} routes</span>
|
|
21214
|
+
<span class="t4-dim">Node.js ${nodeVersion}</span>
|
|
21215
|
+
<a href="#" id="tina4-dash-link" class="t4-dash">Dashboard ↗</a>
|
|
21216
|
+
<span id="tina4-bar-close" class="t4-x t4-bar-close">✕</span>
|
|
21215
21217
|
</div>
|
|
21216
|
-
<script
|
|
21217
|
-
|
|
21218
|
-
|
|
21219
|
-
|
|
21220
|
-
|
|
21221
|
-
|
|
21218
|
+
<script src="/__dev/toolbar.js"></script>`;
|
|
21219
|
+
}
|
|
21220
|
+
function toolbarCss() {
|
|
21221
|
+
return `#tina4-dev-toolbar{position:fixed;bottom:0;left:0;right:0;background:#333;color:#fff;font-family:monospace;font-size:12px;padding:6px 16px;z-index:99999;display:flex;align-items:center;gap:16px}
|
|
21222
|
+
#tina4-dev-toolbar a{text-decoration:none}
|
|
21223
|
+
#tina4-ver-btn{color:#2e7d32;font-weight:bold;cursor:pointer;text-decoration:underline dotted}
|
|
21224
|
+
#tina4-ver-modal{display:none;position:fixed;bottom:3rem;left:1rem;background:#1e1e2e;border:1px solid #2e7d32;border-radius:8px;padding:16px 20px;z-index:100000;min-width:320px;box-shadow:0 8px 32px rgba(0,0,0,.5);font-family:monospace;font-size:13px;color:#cdd6f4}
|
|
21225
|
+
.t4-modal-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:12px}
|
|
21226
|
+
.t4-modal-title{color:#89b4fa}
|
|
21227
|
+
#tina4-ver-body{line-height:1.8}
|
|
21228
|
+
.t4-x{cursor:pointer;color:#888}
|
|
21229
|
+
.t4-bar-close{margin-left:8px}
|
|
21230
|
+
.t4-green{color:#4caf50}
|
|
21231
|
+
.t4-dim{color:#888}
|
|
21232
|
+
.t4-arrow{color:#666}
|
|
21233
|
+
.t4-yellow{color:#ffeb3b}
|
|
21234
|
+
.t4-blue{color:#90caf9}
|
|
21235
|
+
.t4-ok{color:#a6e3a1}
|
|
21236
|
+
.t4-warn{color:#f9e2af}
|
|
21237
|
+
.t4-err{color:#f38ba8}
|
|
21238
|
+
.t4-purple{color:#cba6f7}
|
|
21239
|
+
.t4-link{color:#89b4fa}
|
|
21240
|
+
.t4-code{background:#313244;padding:2px 6px;border-radius:3px}
|
|
21241
|
+
.t4-note{margin-top:6px}
|
|
21242
|
+
.t4-dash{color:#ef9a9a;margin-left:auto;cursor:pointer}
|
|
21243
|
+
#tina4-dev-panel{position:fixed;top:3rem;left:0;right:0;bottom:2rem;z-index:99998;transition:all .2s}
|
|
21244
|
+
#tina4-dev-panel iframe{width:100%;height:100%;border:1px solid #2e7d32;border-radius:.5rem;box-shadow:0 8px 32px rgba(0,0,0,.5);background:#0f172a}`;
|
|
21245
|
+
}
|
|
21246
|
+
function toolbarJs() {
|
|
21247
|
+
return `(function () {
|
|
21248
|
+
var bar = document.getElementById('tina4-dev-toolbar');
|
|
21249
|
+
if (!bar) { return; }
|
|
21250
|
+
|
|
21251
|
+
var modal = document.getElementById('tina4-ver-modal');
|
|
21252
|
+
function upToDate(el, latest) {
|
|
21253
|
+
el.className = 't4-ok';
|
|
21254
|
+
el.innerHTML = 'Latest: <strong class="t4-ok">v' + latest + '</strong> — You are up to date!';
|
|
21255
|
+
}
|
|
21256
|
+
function checkVersion() {
|
|
21257
|
+
if (modal.style.display === 'block') { modal.style.display = 'none'; return; }
|
|
21258
|
+
modal.style.display = 'block';
|
|
21259
|
+
var el = document.getElementById('tina4-ver-latest');
|
|
21260
|
+
el.className = 't4-dim';
|
|
21261
|
+
el.textContent = 'Checking for updates...';
|
|
21262
|
+
fetch('/__dev/api/version-check').then(function (r) { return r.json(); }).then(function (d) {
|
|
21263
|
+
var latest = d.latest, current = d.current;
|
|
21264
|
+
if (latest === current) { upToDate(el, latest); return; }
|
|
21265
|
+
var cP = current.split('.').map(Number), lP = latest.split('.').map(Number);
|
|
21266
|
+
var isNewer = false, i, c, l;
|
|
21267
|
+
for (i = 0; i < Math.max(cP.length, lP.length); i++) { c = cP[i] || 0; l = lP[i] || 0; if (l > c) { isNewer = true; break; } if (l < c) { break; } }
|
|
21268
|
+
var isAhead = false;
|
|
21269
|
+
if (!isNewer) { for (i = 0; i < Math.max(cP.length, lP.length); i++) { var c2 = cP[i] || 0, l2 = lP[i] || 0; if (c2 > l2) { isAhead = true; break; } if (c2 < l2) { break; } } }
|
|
21270
|
+
if (isNewer) {
|
|
21271
|
+
var breaking = (lP[0] !== cP[0] || lP[1] !== cP[1]);
|
|
21272
|
+
el.className = '';
|
|
21273
|
+
el.innerHTML = 'Latest: <strong class="t4-warn">v' + latest + '</strong>';
|
|
21274
|
+
if (breaking) {
|
|
21275
|
+
el.innerHTML += '<div class="t4-err t4-note">⚠ Major/minor version change — check the <a href="https://github.com/tina4stack/tina4-nodejs/releases" target="_blank" class="t4-link">changelog</a> for breaking changes before upgrading.</div>';
|
|
21276
|
+
} else {
|
|
21277
|
+
el.innerHTML += '<div class="t4-warn t4-note">Patch update available. Run: <code class="t4-code">npm install tina4-nodejs@latest</code></div>';
|
|
21278
|
+
}
|
|
21279
|
+
} else if (isAhead) {
|
|
21280
|
+
el.className = 't4-purple';
|
|
21281
|
+
el.innerHTML = 'You are running <strong class="t4-purple">v' + current + '</strong> (ahead of npm <strong>v' + latest + '</strong> — not yet published).';
|
|
21282
|
+
} else {
|
|
21283
|
+
upToDate(el, latest);
|
|
21284
|
+
}
|
|
21285
|
+
}).catch(function () {
|
|
21286
|
+
el.className = 't4-err';
|
|
21287
|
+
el.textContent = 'Could not check for updates (offline?)';
|
|
21288
|
+
});
|
|
21289
|
+
}
|
|
21290
|
+
var verBtn = document.getElementById('tina4-ver-btn');
|
|
21291
|
+
if (verBtn) { verBtn.addEventListener('click', checkVersion); }
|
|
21292
|
+
var verClose = document.getElementById('tina4-ver-close');
|
|
21293
|
+
if (verClose) { verClose.addEventListener('click', function () { modal.style.display = 'none'; }); }
|
|
21294
|
+
var barClose = document.getElementById('tina4-bar-close');
|
|
21295
|
+
if (barClose) { barClose.addEventListener('click', function () { bar.style.display = 'none'; }); }
|
|
21296
|
+
|
|
21222
21297
|
var STATE_KEY = 'tina4_dev_overlay_open';
|
|
21223
21298
|
function buildOverlay() {
|
|
21224
21299
|
var c = document.createElement('div');
|
|
21225
21300
|
c.id = 'tina4-dev-panel';
|
|
21226
|
-
c.style.cssText = 'position:fixed;top:3rem;left:0;right:0;bottom:2rem;z-index:99998;transition:all 0.2s';
|
|
21227
21301
|
var f = document.createElement('iframe');
|
|
21228
21302
|
f.src = '/__dev';
|
|
21229
|
-
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';
|
|
21230
21303
|
c.appendChild(f);
|
|
21231
21304
|
document.body.appendChild(c);
|
|
21232
21305
|
return c;
|
|
21233
21306
|
}
|
|
21234
|
-
|
|
21235
|
-
if (e) e.preventDefault();
|
|
21307
|
+
function toggleOverlay(e) {
|
|
21308
|
+
if (e) { e.preventDefault(); }
|
|
21236
21309
|
var p = document.getElementById('tina4-dev-panel');
|
|
21237
21310
|
if (p) {
|
|
21238
21311
|
var hide = p.style.display !== 'none';
|
|
@@ -21242,137 +21315,61 @@ function renderToolbarHtml(ctx) {
|
|
|
21242
21315
|
}
|
|
21243
21316
|
buildOverlay();
|
|
21244
21317
|
try { localStorage.setItem(STATE_KEY, '1'); } catch (_) {}
|
|
21245
|
-
};
|
|
21246
|
-
function restoreIfOpen() {
|
|
21247
|
-
try {
|
|
21248
|
-
if (location.pathname.indexOf('/__dev') === 0) return;
|
|
21249
|
-
if (localStorage.getItem(STATE_KEY) === '1' && !document.getElementById('tina4-dev-panel')) {
|
|
21250
|
-
buildOverlay();
|
|
21251
|
-
}
|
|
21252
|
-
} catch (_) {}
|
|
21253
21318
|
}
|
|
21254
|
-
|
|
21255
|
-
|
|
21256
|
-
|
|
21257
|
-
|
|
21258
|
-
|
|
21259
|
-
|
|
21260
|
-
|
|
21261
|
-
|
|
21262
|
-
|
|
21263
|
-
|
|
21264
|
-
if(
|
|
21265
|
-
|
|
21266
|
-
var
|
|
21267
|
-
|
|
21268
|
-
|
|
21269
|
-
|
|
21270
|
-
|
|
21271
|
-
|
|
21272
|
-
|
|
21273
|
-
|
|
21274
|
-
|
|
21275
|
-
el.innerHTML='Latest: <strong style="color:#a6e3a1;">v'+latest+'</strong> — You are up to date!';
|
|
21276
|
-
el.style.color='#a6e3a1';
|
|
21277
|
-
}else{
|
|
21278
|
-
var cParts=current.split('.').map(Number);
|
|
21279
|
-
var lParts=latest.split('.').map(Number);
|
|
21280
|
-
var isNewer=false;
|
|
21281
|
-
for(var i=0;i<Math.max(cParts.length,lParts.length);i++){
|
|
21282
|
-
var c=cParts[i]||0,l=lParts[i]||0;
|
|
21283
|
-
if(l>c){isNewer=true;break;}
|
|
21284
|
-
if(l<c)break;
|
|
21285
|
-
}
|
|
21286
|
-
var isAhead=false;
|
|
21287
|
-
if(!isNewer){for(var i=0;i<Math.max(cParts.length,lParts.length);i++){var c2=cParts[i]||0,l2=lParts[i]||0;if(c2>l2){isAhead=true;break;}if(c2<l2)break;}}
|
|
21288
|
-
if(isNewer){
|
|
21289
|
-
var breaking=(lParts[0]!==cParts[0]||lParts[1]!==cParts[1]);
|
|
21290
|
-
el.innerHTML='Latest: <strong style="color:#f9e2af;">v'+latest+'</strong>';
|
|
21291
|
-
if(breaking){
|
|
21292
|
-
el.innerHTML+='<div style="color:#f38ba8;margin-top:6px;">⚠ Major/minor version change — check the <a href="https://github.com/tina4stack/tina4-nodejs/releases" target="_blank" style="color:#89b4fa;">changelog</a> for breaking changes before upgrading.</div>';
|
|
21293
|
-
}else{
|
|
21294
|
-
el.innerHTML+='<div style="color:#f9e2af;margin-top:6px;">Patch update available. Run: <code style="background:#313244;padding:2px 6px;border-radius:3px;">npm install tina4-nodejs@latest</code></div>';
|
|
21295
|
-
}
|
|
21296
|
-
}else if(isAhead){
|
|
21297
|
-
el.innerHTML='You are running <strong style="color:#cba6f7;">v'+current+'</strong> (ahead of npm <strong>v'+latest+'</strong> — not yet published).';
|
|
21298
|
-
el.style.color='#cba6f7';
|
|
21299
|
-
}else{
|
|
21300
|
-
el.innerHTML='Latest: <strong style="color:#a6e3a1;">v'+latest+'</strong> — You are up to date!';
|
|
21301
|
-
el.style.color='#a6e3a1';
|
|
21302
|
-
}
|
|
21303
|
-
}
|
|
21304
|
-
})
|
|
21305
|
-
.catch(function(){
|
|
21306
|
-
el.innerHTML='Could not check for updates (offline?)';
|
|
21307
|
-
el.style.color='#f38ba8';
|
|
21308
|
-
});
|
|
21309
|
-
}
|
|
21310
|
-
</script>
|
|
21311
|
-
<script>
|
|
21312
|
-
(function(){
|
|
21313
|
-
// WebSocket-primary dev reloader. The running server re-imports changed
|
|
21314
|
-
// src/ routes in-process and pushes a {type,file,mtime} message over
|
|
21315
|
-
// /__dev_reload \u2014 no respawn, instant refresh. The mtime poll below is a
|
|
21316
|
-
// FALLBACK only, started when the socket is down and stopped on connect.
|
|
21317
|
-
var _t4_css_exts=['.css','.scss'],_t4_debounce=null;
|
|
21318
|
-
var _t4_interval=3000;
|
|
21319
|
-
var _t4_ws=null,_t4_poll_timer=null,_t4_mtime=null;
|
|
21320
|
-
function _t4_apply(d){
|
|
21321
|
-
d=d||{};
|
|
21322
|
-
var f=d.file||'',t=d.type||'';
|
|
21323
|
-
var isCss=t==='css'||_t4_css_exts.some(function(e){return f.endsWith(e)});
|
|
21324
|
-
if(isCss){
|
|
21325
|
-
var links=document.querySelectorAll('link[rel="stylesheet"]');
|
|
21326
|
-
links.forEach(function(l){
|
|
21327
|
-
var href=l.getAttribute('href');
|
|
21328
|
-
if(href){l.setAttribute('href',href.split('?')[0]+'?_t4='+(d.mtime||Date.now()))}
|
|
21319
|
+
var dash = document.getElementById('tina4-dash-link');
|
|
21320
|
+
if (dash) { dash.addEventListener('click', toggleOverlay); }
|
|
21321
|
+
try {
|
|
21322
|
+
if (location.pathname.indexOf('/__dev') !== 0
|
|
21323
|
+
&& localStorage.getItem(STATE_KEY) === '1'
|
|
21324
|
+
&& !document.getElementById('tina4-dev-panel')) {
|
|
21325
|
+
buildOverlay();
|
|
21326
|
+
}
|
|
21327
|
+
} catch (_) {}
|
|
21328
|
+
|
|
21329
|
+
if (bar.getAttribute('data-reload') !== '1') { return; }
|
|
21330
|
+
var cssExts = ['.css', '.scss'], debounce = null, interval = 3000;
|
|
21331
|
+
var ws = null, pollTimer = null, mtime = null;
|
|
21332
|
+
function apply(d) {
|
|
21333
|
+
d = d || {};
|
|
21334
|
+
var f = d.file || '', t = d.type || '';
|
|
21335
|
+
var isCss = t === 'css' || cssExts.some(function (e) { return f.endsWith(e); });
|
|
21336
|
+
if (isCss) {
|
|
21337
|
+
document.querySelectorAll('link[rel="stylesheet"]').forEach(function (l) {
|
|
21338
|
+
var href = l.getAttribute('href');
|
|
21339
|
+
if (href) { l.setAttribute('href', href.split('?')[0] + '?_t4=' + (d.mtime || Date.now())); }
|
|
21329
21340
|
});
|
|
21330
|
-
}else{
|
|
21341
|
+
} else {
|
|
21331
21342
|
location.reload();
|
|
21332
21343
|
}
|
|
21333
21344
|
}
|
|
21334
|
-
function
|
|
21335
|
-
fetch('/__dev/api/mtime').then(function(r){return r.json()}).then(function(d){
|
|
21336
|
-
|
|
21337
|
-
|
|
21338
|
-
|
|
21339
|
-
|
|
21340
|
-
|
|
21341
|
-
|
|
21342
|
-
|
|
21343
|
-
|
|
21344
|
-
|
|
21345
|
-
|
|
21346
|
-
|
|
21347
|
-
|
|
21348
|
-
|
|
21349
|
-
|
|
21350
|
-
|
|
21351
|
-
|
|
21352
|
-
|
|
21353
|
-
if(_t4_poll_timer){clearInterval(_t4_poll_timer);_t4_poll_timer=null;}
|
|
21354
|
-
}
|
|
21355
|
-
function _t4_connect(){
|
|
21356
|
-
var url=(location.protocol==='https:'?'wss':'ws')+'://'+location.host+'/__dev_reload';
|
|
21357
|
-
try{_t4_ws=new WebSocket(url);}catch(_){_t4_startPoll();return;}
|
|
21358
|
-
_t4_ws.addEventListener('open',function(){_t4_stopPoll();});
|
|
21359
|
-
_t4_ws.addEventListener('message',function(ev){
|
|
21360
|
-
var d=null;
|
|
21361
|
-
try{d=typeof ev.data==='string'?JSON.parse(ev.data):null;}catch(_){}
|
|
21362
|
-
if(!d)return;
|
|
21363
|
-
if(d.type==='reload'||d.type==='change'||d.type==='css'){
|
|
21364
|
-
if(_t4_debounce)clearTimeout(_t4_debounce);
|
|
21365
|
-
_t4_debounce=setTimeout(function(){_t4_apply(d);},150);
|
|
21345
|
+
function poll() {
|
|
21346
|
+
fetch('/__dev/api/mtime').then(function (r) { return r.json(); }).then(function (d) {
|
|
21347
|
+
if (mtime === null) { mtime = d.mtime; return; }
|
|
21348
|
+
if (d.mtime !== mtime) { mtime = d.mtime; if (debounce) { clearTimeout(debounce); } debounce = setTimeout(function () { apply(d); }, 500); }
|
|
21349
|
+
}).catch(function () {});
|
|
21350
|
+
}
|
|
21351
|
+
function startPoll() { if (pollTimer) { return; } mtime = null; pollTimer = setInterval(poll, interval); }
|
|
21352
|
+
function stopPoll() { if (pollTimer) { clearInterval(pollTimer); pollTimer = null; } }
|
|
21353
|
+
function connect() {
|
|
21354
|
+
var url = (location.protocol === 'https:' ? 'wss' : 'ws') + '://' + location.host + '/__dev_reload';
|
|
21355
|
+
try { ws = new WebSocket(url); } catch (_) { startPoll(); return; }
|
|
21356
|
+
ws.addEventListener('open', function () { stopPoll(); });
|
|
21357
|
+
ws.addEventListener('message', function (ev) {
|
|
21358
|
+
var d = null;
|
|
21359
|
+
try { d = typeof ev.data === 'string' ? JSON.parse(ev.data) : null; } catch (_) {}
|
|
21360
|
+
if (!d) { return; }
|
|
21361
|
+
if (d.type === 'reload' || d.type === 'change' || d.type === 'css') {
|
|
21362
|
+
if (debounce) { clearTimeout(debounce); }
|
|
21363
|
+
debounce = setTimeout(function () { apply(d); }, 150);
|
|
21366
21364
|
}
|
|
21367
21365
|
});
|
|
21368
|
-
|
|
21369
|
-
|
|
21366
|
+
ws.addEventListener('close', function () { ws = null; startPoll(); setTimeout(connect, 2000); });
|
|
21367
|
+
ws.addEventListener('error', function () { try { ws && ws.close(); } catch (_) {} });
|
|
21370
21368
|
}
|
|
21371
|
-
|
|
21372
|
-
})()
|
|
21373
|
-
</script>`;
|
|
21369
|
+
connect();
|
|
21370
|
+
})();`;
|
|
21374
21371
|
}
|
|
21375
|
-
var cpuCount, DEV_SAFE_METHODS, DEV_MCP_PREFIXES, DEV_SECRET_BASENAMES, DEV_SECRET_SUFFIXES, MessageLog, RequestInspector, ErrorTracker, DevMailboxStore, DevQueue, WsTracker, DevAdmin, handleDashboard, _reloadMtime, _reloadFile, handleMtime, handleReload, handleMessages, handleMessagesClear, handleRequests, handleRequestsClear, handleSystem, handleMessagesSearch, handleQueue, handleQueueTopics, handleQueueDeadLetters, handleQueueRetry, handleQueuePurge, handleQueueReplay, handleMailbox, handleMailboxRead, handleMailboxSeed, handleMailboxClear, handleTable, handleTables, handleSeed, handleQuery, handleBroken, handleBrokenResolve, handleBrokenClear, handleWebsockets, handleWebsocketsDisconnect, handleTool, handleChat, DEFAULT_MCP_URL, handleGroundingStatus, handleGroundingToken, handleMigrate, handleSeedRun, handleTest, handleThreads, handleThreadsSub, handleConnections, handleConnectionsTest, handleConnectionsSave, __devAdminFilename, __devAdminDirname, handleGalleryList, handleVersionCheck, handleThoughts, handleSuperviseStub, handleExecute, DEV_FILES_IGNORED, handleFiles, DEV_ADMIN_LANG_MAP, handleFileRead, handleFileSave, handleFileRaw, handleFileRename, handleFileDelete, handleDepsSearch, handleDepsInstall, handleGitStatus, handleMcpTools, handleMcpCall, handleMcpStreamable, handleMcpDelete, handleMcpGet405, handleMcpLegacyMessage, handleMcpSse, handleScaffoldList, handleScaffoldRun, handlePlanCurrent, handlePlanList, handlePlanCreate, handlePlanSwitch, handlePlanCompleteStep, handlePlanAddStep, handlePlanNote, handlePlanArchive, handlePlanRead, handlePlanFlesh, handleIndexRebuild, handleIndexSearch, handleIndexFile, handleIndexOverview, handleDocsSearch, handleDocsClass, handleDocsMethod, handleDocsIndex, handleDocsWellKnown, handleDevAdminJs;
|
|
21372
|
+
var cpuCount, DEV_SAFE_METHODS, DEV_MCP_PREFIXES, DEV_SECRET_BASENAMES, DEV_SECRET_SUFFIXES, MessageLog, RequestInspector, ErrorTracker, DevMailboxStore, DevQueue, WsTracker, DevAdmin, handleDashboard, _reloadMtime, _reloadFile, handleMtime, handleReload, handleMessages, handleMessagesClear, handleRequests, handleRequestsClear, handleSystem, handleMessagesSearch, handleQueue, handleQueueTopics, handleQueueDeadLetters, handleQueueRetry, handleQueuePurge, handleQueueReplay, handleMailbox, handleMailboxRead, handleMailboxSeed, handleMailboxClear, handleTable, handleTables, handleSeed, handleQuery, handleBroken, handleBrokenResolve, handleBrokenClear, handleWebsockets, handleWebsocketsDisconnect, handleTool, handleChat, DEFAULT_MCP_URL, handleGroundingStatus, handleGroundingToken, handleMigrate, handleSeedRun, handleTest, handleThreads, handleThreadsSub, handleConnections, handleConnectionsTest, handleConnectionsSave, __devAdminFilename, __devAdminDirname, handleGalleryList, handleVersionCheck, handleThoughts, handleSuperviseStub, handleExecute, DEV_FILES_IGNORED, handleFiles, DEV_ADMIN_LANG_MAP, handleFileRead, handleFileSave, handleFileRaw, handleFileRename, handleFileDelete, handleDepsSearch, handleDepsInstall, handleGitStatus, handleMcpTools, handleMcpCall, handleMcpStreamable, handleMcpDelete, handleMcpGet405, handleMcpLegacyMessage, handleMcpSse, handleScaffoldList, handleScaffoldRun, handlePlanCurrent, handlePlanList, handlePlanCreate, handlePlanSwitch, handlePlanCompleteStep, handlePlanAddStep, handlePlanNote, handlePlanArchive, handlePlanRead, handlePlanFlesh, handleIndexRebuild, handleIndexSearch, handleIndexFile, handleIndexOverview, handleDocsSearch, handleDocsClass, handleDocsMethod, handleDocsIndex, handleDocsWellKnown, handleDevAdminJs, handleToolbarCss, handleToolbarJs;
|
|
21376
21373
|
var init_devAdmin = __esm({
|
|
21377
21374
|
"../core/src/devAdmin.ts"() {
|
|
21378
21375
|
"use strict";
|
|
@@ -21838,7 +21835,12 @@ var init_devAdmin = __esm({
|
|
|
21838
21835
|
{ method: "GET", pattern: "/__dev/api/docs/index", handler: handleDocsIndex },
|
|
21839
21836
|
{ method: "GET", pattern: "/__dev/api/docs/.well-known.json", handler: handleDocsWellKnown },
|
|
21840
21837
|
// JS asset
|
|
21841
|
-
{ method: "GET", pattern: "/__dev/js/tina4-dev-admin.min.js", handler: handleDevAdminJs }
|
|
21838
|
+
{ method: "GET", pattern: "/__dev/js/tina4-dev-admin.min.js", handler: handleDevAdminJs },
|
|
21839
|
+
// Dev-toolbar assets — served as external CSS/JS so the injected toolbar is
|
|
21840
|
+
// CSP-clean (no inline style=, onclick=, or <script>) under a strict
|
|
21841
|
+
// `default-src 'self'`. Parity with PHP's /__dev/toolbar.css + toolbar.js.
|
|
21842
|
+
{ method: "GET", pattern: "/__dev/toolbar.css", handler: handleToolbarCss },
|
|
21843
|
+
{ method: "GET", pattern: "/__dev/toolbar.js", handler: handleToolbarJs }
|
|
21842
21844
|
];
|
|
21843
21845
|
for (const route of routes) {
|
|
21844
21846
|
router.addRoute({
|
|
@@ -23274,6 +23276,14 @@ var init_devAdmin = __esm({
|
|
|
23274
23276
|
res.raw.writeHead(404, { "Content-Type": "text/plain" });
|
|
23275
23277
|
res.raw.end("tina4-dev-admin.min.js not found");
|
|
23276
23278
|
};
|
|
23279
|
+
handleToolbarCss = (_req, res) => {
|
|
23280
|
+
res.raw.writeHead(200, { "Content-Type": "text/css; charset=utf-8", "Cache-Control": "no-cache" });
|
|
23281
|
+
res.raw.end(toolbarCss());
|
|
23282
|
+
};
|
|
23283
|
+
handleToolbarJs = (_req, res) => {
|
|
23284
|
+
res.raw.writeHead(200, { "Content-Type": "application/javascript; charset=utf-8", "Cache-Control": "no-cache" });
|
|
23285
|
+
res.raw.end(toolbarJs());
|
|
23286
|
+
};
|
|
23277
23287
|
}
|
|
23278
23288
|
});
|
|
23279
23289
|
|
|
@@ -25135,7 +25145,11 @@ function injectIntoHtml(ctx, devToolbar, html) {
|
|
|
25135
25145
|
path: ctx.pathname,
|
|
25136
25146
|
matchedPattern: ctx.matchedPattern.value || ctx.pathname,
|
|
25137
25147
|
requestId: ctx.requestId,
|
|
25138
|
-
routeCount: ctx.router.getRoutes().length
|
|
25148
|
+
routeCount: ctx.router.getRoutes().length,
|
|
25149
|
+
// Suppress the live reloader on the AI/stable port (data-reload="0"); the
|
|
25150
|
+
// toolbar JS early-returns when data-reload !== "1". Mirrors PHP's
|
|
25151
|
+
// suppressReload flag.
|
|
25152
|
+
reload: !ctx.isAiPortRequest
|
|
25139
25153
|
};
|
|
25140
25154
|
return injectFeedbackWidget(ctx.req, injectDevToolbar(html, toolbarCtx));
|
|
25141
25155
|
}
|
|
@@ -42620,6 +42634,775 @@ var init_docstore = __esm({
|
|
|
42620
42634
|
}
|
|
42621
42635
|
});
|
|
42622
42636
|
|
|
42637
|
+
// src/graph/graphUrl.ts
|
|
42638
|
+
var SCHEME_ENGINE, ENGINE_DEFAULT_PORT, GraphUrl;
|
|
42639
|
+
var init_graphUrl = __esm({
|
|
42640
|
+
"src/graph/graphUrl.ts"() {
|
|
42641
|
+
"use strict";
|
|
42642
|
+
SCHEME_ENGINE = {
|
|
42643
|
+
ultipa: "ultipa",
|
|
42644
|
+
ultipas: "ultipa",
|
|
42645
|
+
// TLS variant
|
|
42646
|
+
neo4j: "bolt",
|
|
42647
|
+
"neo4j+s": "bolt",
|
|
42648
|
+
bolt: "bolt",
|
|
42649
|
+
"bolt+s": "bolt",
|
|
42650
|
+
memgraph: "bolt",
|
|
42651
|
+
arango: "arango",
|
|
42652
|
+
arangodb: "arango"
|
|
42653
|
+
};
|
|
42654
|
+
ENGINE_DEFAULT_PORT = {
|
|
42655
|
+
ultipa: 60061,
|
|
42656
|
+
bolt: 7687,
|
|
42657
|
+
arango: 8529
|
|
42658
|
+
};
|
|
42659
|
+
GraphUrl = class _GraphUrl {
|
|
42660
|
+
raw;
|
|
42661
|
+
scheme;
|
|
42662
|
+
engine;
|
|
42663
|
+
host;
|
|
42664
|
+
port;
|
|
42665
|
+
/** The graph/database name (leading slash stripped), or null when absent. */
|
|
42666
|
+
graph;
|
|
42667
|
+
username;
|
|
42668
|
+
password;
|
|
42669
|
+
params;
|
|
42670
|
+
useTls;
|
|
42671
|
+
constructor(url) {
|
|
42672
|
+
this.raw = url;
|
|
42673
|
+
let parsed;
|
|
42674
|
+
try {
|
|
42675
|
+
parsed = new URL(url);
|
|
42676
|
+
} catch {
|
|
42677
|
+
throw new Error(
|
|
42678
|
+
`Unsupported graph URL '${url}' \u2014 expected scheme://[user[:password]@]host[:port]/graph (e.g. ultipa://host:60061/mygraph).`
|
|
42679
|
+
);
|
|
42680
|
+
}
|
|
42681
|
+
const scheme = parsed.protocol.replace(/:$/, "").toLowerCase();
|
|
42682
|
+
const engine = SCHEME_ENGINE[scheme];
|
|
42683
|
+
if (engine === void 0) {
|
|
42684
|
+
throw new Error(
|
|
42685
|
+
`Unsupported graph URL scheme '${scheme}'. Supported: ${Object.keys(SCHEME_ENGINE).sort().join(", ")} (e.g. ultipa://host:60061/mygraph).`
|
|
42686
|
+
);
|
|
42687
|
+
}
|
|
42688
|
+
this.scheme = scheme;
|
|
42689
|
+
this.engine = engine;
|
|
42690
|
+
this.host = parsed.hostname || "localhost";
|
|
42691
|
+
this.port = parsed.port ? parseInt(parsed.port, 10) : ENGINE_DEFAULT_PORT[engine];
|
|
42692
|
+
const path8 = (parsed.pathname || "").replace(/^\//, "");
|
|
42693
|
+
this.graph = path8 === "" ? null : path8;
|
|
42694
|
+
this.username = parsed.username ? decodeURIComponent(parsed.username) : null;
|
|
42695
|
+
this.password = parsed.password ? decodeURIComponent(parsed.password) : null;
|
|
42696
|
+
this.params = {};
|
|
42697
|
+
for (const [key, value] of parsed.searchParams) {
|
|
42698
|
+
if (!(key in this.params)) this.params[key] = value;
|
|
42699
|
+
}
|
|
42700
|
+
this.useTls = scheme.endsWith("s") || this.params.tls === "1" || this.params.tls === "true";
|
|
42701
|
+
}
|
|
42702
|
+
/** host:port/graph — for messages, never carrying credentials. */
|
|
42703
|
+
getDsn() {
|
|
42704
|
+
const target = this.port ? `${this.host}:${this.port}` : this.host;
|
|
42705
|
+
return this.graph ? `${target}/${this.graph}` : target;
|
|
42706
|
+
}
|
|
42707
|
+
static fromEnv(envKey = "TINA4_GRAPH_URL") {
|
|
42708
|
+
const url = (process.env[envKey] ?? "").trim();
|
|
42709
|
+
return url === "" ? null : new _GraphUrl(url);
|
|
42710
|
+
}
|
|
42711
|
+
};
|
|
42712
|
+
}
|
|
42713
|
+
});
|
|
42714
|
+
|
|
42715
|
+
// src/graph/errors.ts
|
|
42716
|
+
var GraphError, GraphConnectTimeout;
|
|
42717
|
+
var init_errors = __esm({
|
|
42718
|
+
"src/graph/errors.ts"() {
|
|
42719
|
+
"use strict";
|
|
42720
|
+
GraphError = class extends Error {
|
|
42721
|
+
constructor(message, cause) {
|
|
42722
|
+
super(message, cause === void 0 ? void 0 : { cause });
|
|
42723
|
+
this.name = "GraphError";
|
|
42724
|
+
}
|
|
42725
|
+
};
|
|
42726
|
+
GraphConnectTimeout = class extends GraphError {
|
|
42727
|
+
constructor(message, cause) {
|
|
42728
|
+
super(message, cause);
|
|
42729
|
+
this.name = "GraphConnectTimeout";
|
|
42730
|
+
}
|
|
42731
|
+
};
|
|
42732
|
+
}
|
|
42733
|
+
});
|
|
42734
|
+
|
|
42735
|
+
// src/graph/shapes.ts
|
|
42736
|
+
var GraphNode, GraphEdge, GraphResult;
|
|
42737
|
+
var init_shapes = __esm({
|
|
42738
|
+
"src/graph/shapes.ts"() {
|
|
42739
|
+
"use strict";
|
|
42740
|
+
GraphNode = class {
|
|
42741
|
+
id;
|
|
42742
|
+
labels;
|
|
42743
|
+
properties;
|
|
42744
|
+
constructor(id, labels = null, properties = null) {
|
|
42745
|
+
this.id = id;
|
|
42746
|
+
this.labels = [...labels ?? []];
|
|
42747
|
+
this.properties = { ...properties ?? {} };
|
|
42748
|
+
}
|
|
42749
|
+
toDict() {
|
|
42750
|
+
return { id: this.id, labels: this.labels, properties: this.properties };
|
|
42751
|
+
}
|
|
42752
|
+
};
|
|
42753
|
+
GraphEdge = class {
|
|
42754
|
+
id;
|
|
42755
|
+
type;
|
|
42756
|
+
from;
|
|
42757
|
+
to;
|
|
42758
|
+
properties;
|
|
42759
|
+
constructor(id, type2, from, to, properties = null) {
|
|
42760
|
+
this.id = id;
|
|
42761
|
+
this.type = type2;
|
|
42762
|
+
this.from = from;
|
|
42763
|
+
this.to = to;
|
|
42764
|
+
this.properties = { ...properties ?? {} };
|
|
42765
|
+
}
|
|
42766
|
+
toDict() {
|
|
42767
|
+
return {
|
|
42768
|
+
id: this.id,
|
|
42769
|
+
type: this.type,
|
|
42770
|
+
from: this.from,
|
|
42771
|
+
to: this.to,
|
|
42772
|
+
properties: this.properties
|
|
42773
|
+
};
|
|
42774
|
+
}
|
|
42775
|
+
};
|
|
42776
|
+
GraphResult = class {
|
|
42777
|
+
records;
|
|
42778
|
+
columns;
|
|
42779
|
+
constructor(records = null, columns = null) {
|
|
42780
|
+
this.records = [...records ?? []];
|
|
42781
|
+
this.columns = [...columns ?? []];
|
|
42782
|
+
}
|
|
42783
|
+
toArray() {
|
|
42784
|
+
return this.records;
|
|
42785
|
+
}
|
|
42786
|
+
/** The first value of the first record, or null. */
|
|
42787
|
+
scalar() {
|
|
42788
|
+
if (this.records.length === 0) return null;
|
|
42789
|
+
const values = Object.values(this.records[0]);
|
|
42790
|
+
return values.length ? values[0] : null;
|
|
42791
|
+
}
|
|
42792
|
+
[Symbol.iterator]() {
|
|
42793
|
+
return this.records[Symbol.iterator]();
|
|
42794
|
+
}
|
|
42795
|
+
get length() {
|
|
42796
|
+
return this.records.length;
|
|
42797
|
+
}
|
|
42798
|
+
};
|
|
42799
|
+
}
|
|
42800
|
+
});
|
|
42801
|
+
|
|
42802
|
+
// src/graph/connectTimeout.ts
|
|
42803
|
+
function resolveGraphConnectTimeout() {
|
|
42804
|
+
const raw = (process.env[GRAPH_CONNECT_TIMEOUT_VARIABLE] ?? "").trim();
|
|
42805
|
+
if (raw === "") {
|
|
42806
|
+
return DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS;
|
|
42807
|
+
}
|
|
42808
|
+
const seconds = Number(raw);
|
|
42809
|
+
if (!Number.isFinite(seconds)) {
|
|
42810
|
+
Log.warning(
|
|
42811
|
+
`${GRAPH_CONNECT_TIMEOUT_VARIABLE}="${raw}" is not a number of seconds \u2014 bounding graph connects at the ${DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS}s default instead`
|
|
42812
|
+
);
|
|
42813
|
+
return DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS;
|
|
42814
|
+
}
|
|
42815
|
+
return seconds <= 0 ? null : seconds;
|
|
42816
|
+
}
|
|
42817
|
+
var GRAPH_CONNECT_TIMEOUT_VARIABLE, DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS;
|
|
42818
|
+
var init_connectTimeout2 = __esm({
|
|
42819
|
+
"src/graph/connectTimeout.ts"() {
|
|
42820
|
+
"use strict";
|
|
42821
|
+
init_src2();
|
|
42822
|
+
GRAPH_CONNECT_TIMEOUT_VARIABLE = "TINA4_GRAPH_CONNECT_TIMEOUT";
|
|
42823
|
+
DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS = 10;
|
|
42824
|
+
}
|
|
42825
|
+
});
|
|
42826
|
+
|
|
42827
|
+
// src/graph/adapters/ultipa.ts
|
|
42828
|
+
var ultipa_exports = {};
|
|
42829
|
+
__export(ultipa_exports, {
|
|
42830
|
+
UltipaGraphAdapter: () => UltipaGraphAdapter
|
|
42831
|
+
});
|
|
42832
|
+
function propClause(properties) {
|
|
42833
|
+
const props = properties ?? {};
|
|
42834
|
+
const keys = Object.keys(props);
|
|
42835
|
+
if (keys.length === 0) return { clause: "{}", params: {} };
|
|
42836
|
+
const pairs = keys.map((key) => `${key}: $p_${key}`).join(", ");
|
|
42837
|
+
const params = {};
|
|
42838
|
+
for (const key of keys) params[`p_${key}`] = props[key];
|
|
42839
|
+
return { clause: `{${pairs}}`, params };
|
|
42840
|
+
}
|
|
42841
|
+
function errorMessage(exc) {
|
|
42842
|
+
if (exc instanceof Error) return exc.message;
|
|
42843
|
+
return String(exc);
|
|
42844
|
+
}
|
|
42845
|
+
var DRIVER_PACKAGE2, driver, UltipaClient, UltipaConnectError, UNBOUNDED_CONNECT_SECONDS, UltipaGraphAdapter;
|
|
42846
|
+
var init_ultipa = __esm({
|
|
42847
|
+
async "src/graph/adapters/ultipa.ts"() {
|
|
42848
|
+
"use strict";
|
|
42849
|
+
init_shapes();
|
|
42850
|
+
init_errors();
|
|
42851
|
+
init_connectTimeout2();
|
|
42852
|
+
DRIVER_PACKAGE2 = "tina4-ultipa";
|
|
42853
|
+
driver = await import(DRIVER_PACKAGE2);
|
|
42854
|
+
UltipaClient = driver.UltipaClient;
|
|
42855
|
+
UltipaConnectError = driver.UltipaConnectError;
|
|
42856
|
+
UNBOUNDED_CONNECT_SECONDS = 31536e4;
|
|
42857
|
+
UltipaGraphAdapter = class {
|
|
42858
|
+
url;
|
|
42859
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
42860
|
+
client;
|
|
42861
|
+
lastError = null;
|
|
42862
|
+
constructor(graphUrl, credentials = {}) {
|
|
42863
|
+
this.url = graphUrl;
|
|
42864
|
+
const timeout = resolveGraphConnectTimeout();
|
|
42865
|
+
this.client = new UltipaClient({
|
|
42866
|
+
host: graphUrl.host,
|
|
42867
|
+
port: graphUrl.port,
|
|
42868
|
+
username: graphUrl.username || credentials.username || null,
|
|
42869
|
+
password: graphUrl.password || credentials.password || null,
|
|
42870
|
+
graph: graphUrl.graph,
|
|
42871
|
+
connectTimeout: timeout ?? UNBOUNDED_CONNECT_SECONDS,
|
|
42872
|
+
useTls: graphUrl.useTls
|
|
42873
|
+
});
|
|
42874
|
+
}
|
|
42875
|
+
// -- connection + raw pass-through -------------------------------------
|
|
42876
|
+
async run(gql, params = null, readOnly = true) {
|
|
42877
|
+
try {
|
|
42878
|
+
await this.client.connect();
|
|
42879
|
+
} catch (exc) {
|
|
42880
|
+
this.lastError = errorMessage(exc);
|
|
42881
|
+
if (exc instanceof UltipaConnectError || exc?.name === "UltipaConnectError") {
|
|
42882
|
+
const elapsed = typeof exc?.elapsed === "number" ? exc.elapsed : 0;
|
|
42883
|
+
throw new GraphConnectTimeout(
|
|
42884
|
+
`Graph connect to ${this.url.host}:${this.url.port} timed out after ${elapsed.toFixed(1)}s (${GRAPH_CONNECT_TIMEOUT_VARIABLE}). Raise ${GRAPH_CONNECT_TIMEOUT_VARIABLE} if the server is simply slow, or set it to 0 to wait indefinitely.`,
|
|
42885
|
+
exc
|
|
42886
|
+
);
|
|
42887
|
+
}
|
|
42888
|
+
throw new GraphError(this.lastError, exc);
|
|
42889
|
+
}
|
|
42890
|
+
try {
|
|
42891
|
+
return await this.client.query(gql, { params: params ?? null, readOnly });
|
|
42892
|
+
} catch (exc) {
|
|
42893
|
+
this.lastError = errorMessage(exc);
|
|
42894
|
+
throw new GraphError(this.lastError, exc);
|
|
42895
|
+
}
|
|
42896
|
+
}
|
|
42897
|
+
async query(text, params = null) {
|
|
42898
|
+
const result = await this.run(text, params, true);
|
|
42899
|
+
return new GraphResult(result.dicts(), result.columns);
|
|
42900
|
+
}
|
|
42901
|
+
async execute(text, params = null) {
|
|
42902
|
+
const result = await this.run(text, params, false);
|
|
42903
|
+
return new GraphResult(result.dicts(), result.columns);
|
|
42904
|
+
}
|
|
42905
|
+
// -- portable node/edge/traverse core (GQL) ----------------------------
|
|
42906
|
+
nodeFromRow(row) {
|
|
42907
|
+
if (row === null || row === void 0) return null;
|
|
42908
|
+
return new GraphNode(
|
|
42909
|
+
String(row.id),
|
|
42910
|
+
row.labels ?? [],
|
|
42911
|
+
row.props ?? {}
|
|
42912
|
+
);
|
|
42913
|
+
}
|
|
42914
|
+
async addNode(label, properties = null) {
|
|
42915
|
+
const { clause, params } = propClause(properties);
|
|
42916
|
+
const gql = `INSERT (n:\`${label}\` ${clause}) RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
|
|
42917
|
+
const rows = (await this.run(gql, params, false)).dicts();
|
|
42918
|
+
return rows.length ? this.nodeFromRow(rows[0]) : null;
|
|
42919
|
+
}
|
|
42920
|
+
async addEdge(fromId, toId, type2, properties = null) {
|
|
42921
|
+
const { clause, params } = propClause(properties);
|
|
42922
|
+
params.from_id = fromId;
|
|
42923
|
+
params.to_id = toId;
|
|
42924
|
+
const gql = `MATCH (a), (b) WHERE id(a) = $from_id AND id(b) = $to_id INSERT (a)-[e:\`${type2}\` ${clause}]->(b) RETURN id(e) AS id, type(e) AS type, id(a) AS f, id(b) AS t, properties(e) AS props`;
|
|
42925
|
+
const rows = (await this.run(gql, params, false)).dicts();
|
|
42926
|
+
if (rows.length === 0) return null;
|
|
42927
|
+
const row = rows[0];
|
|
42928
|
+
return new GraphEdge(
|
|
42929
|
+
String(row.id),
|
|
42930
|
+
String(row.type),
|
|
42931
|
+
String(row.f),
|
|
42932
|
+
String(row.t),
|
|
42933
|
+
row.props ?? {}
|
|
42934
|
+
);
|
|
42935
|
+
}
|
|
42936
|
+
async getNode(nodeId) {
|
|
42937
|
+
const gql = `MATCH (n) WHERE id(n) = $id RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
|
|
42938
|
+
const rows = (await this.run(gql, { id: nodeId }, true)).dicts();
|
|
42939
|
+
return rows.length ? this.nodeFromRow(rows[0]) : null;
|
|
42940
|
+
}
|
|
42941
|
+
async updateNode(nodeId, properties) {
|
|
42942
|
+
const props = properties ?? {};
|
|
42943
|
+
const keys = Object.keys(props);
|
|
42944
|
+
const sets = keys.map((key) => `n.${key} = $p_${key}`).join(", ");
|
|
42945
|
+
const params = { id: nodeId };
|
|
42946
|
+
for (const key of keys) params[`p_${key}`] = props[key];
|
|
42947
|
+
const gql = `MATCH (n) WHERE id(n) = $id SET ${sets} RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
|
|
42948
|
+
const rows = (await this.run(gql, params, false)).dicts();
|
|
42949
|
+
return rows.length ? this.nodeFromRow(rows[0]) : null;
|
|
42950
|
+
}
|
|
42951
|
+
async deleteNode(nodeId) {
|
|
42952
|
+
const gql = "MATCH (n) WHERE id(n) = $id DETACH DELETE n";
|
|
42953
|
+
await this.run(gql, { id: nodeId }, false);
|
|
42954
|
+
return true;
|
|
42955
|
+
}
|
|
42956
|
+
async neighbors(nodeId, options = {}) {
|
|
42957
|
+
const direction = options.direction ?? "both";
|
|
42958
|
+
const limit = options.limit ?? 100;
|
|
42959
|
+
const edge = options.edgeType ? `:\`${options.edgeType}\`` : "";
|
|
42960
|
+
const pattern = {
|
|
42961
|
+
out: `(n)-[${edge}]->(m)`,
|
|
42962
|
+
in: `(n)<-[${edge}]-(m)`,
|
|
42963
|
+
both: `(n)-[${edge}]-(m)`
|
|
42964
|
+
}[direction];
|
|
42965
|
+
const gql = `MATCH ${pattern} WHERE id(n) = $id RETURN DISTINCT id(m) AS id, labels(m) AS labels, properties(m) AS props LIMIT ${Math.trunc(limit)}`;
|
|
42966
|
+
const rows = (await this.run(gql, { id: nodeId }, true)).dicts();
|
|
42967
|
+
return rows.map((row) => this.nodeFromRow(row)).filter((node) => node !== null);
|
|
42968
|
+
}
|
|
42969
|
+
async traverse(startId, options = {}) {
|
|
42970
|
+
const depth = options.depth ?? 1;
|
|
42971
|
+
const direction = options.direction ?? "both";
|
|
42972
|
+
const limit = options.limit ?? 1e3;
|
|
42973
|
+
const edge = options.edgeType ? `:\`${options.edgeType}\`` : "";
|
|
42974
|
+
const quant = `{1,${Math.trunc(depth)}}`;
|
|
42975
|
+
const pattern = {
|
|
42976
|
+
out: `(n)-[${edge}]->${quant}(m)`,
|
|
42977
|
+
in: `(n)<-[${edge}]-${quant}(m)`,
|
|
42978
|
+
both: `(n)-[${edge}]-${quant}(m)`
|
|
42979
|
+
}[direction];
|
|
42980
|
+
const gql = `MATCH ${pattern} WHERE id(n) = $start RETURN DISTINCT id(m) AS id, labels(m) AS labels, properties(m) AS props LIMIT ${Math.trunc(limit)}`;
|
|
42981
|
+
const rows = (await this.run(gql, { start: startId }, true)).dicts();
|
|
42982
|
+
return rows.map((row) => this.nodeFromRow(row)).filter((node) => node !== null);
|
|
42983
|
+
}
|
|
42984
|
+
close() {
|
|
42985
|
+
this.client.close();
|
|
42986
|
+
}
|
|
42987
|
+
getError() {
|
|
42988
|
+
return this.lastError;
|
|
42989
|
+
}
|
|
42990
|
+
};
|
|
42991
|
+
}
|
|
42992
|
+
});
|
|
42993
|
+
|
|
42994
|
+
// src/graph/adapters/bolt.ts
|
|
42995
|
+
var bolt_exports = {};
|
|
42996
|
+
__export(bolt_exports, {
|
|
42997
|
+
BoltGraphAdapter: () => BoltGraphAdapter
|
|
42998
|
+
});
|
|
42999
|
+
function errorMessage2(exc) {
|
|
43000
|
+
if (exc instanceof Error) return exc.message;
|
|
43001
|
+
return String(exc);
|
|
43002
|
+
}
|
|
43003
|
+
function boltId(id) {
|
|
43004
|
+
const value = Number(id);
|
|
43005
|
+
return Number.isNaN(value) ? -1 : value;
|
|
43006
|
+
}
|
|
43007
|
+
var DRIVER_PACKAGE3, driverModule, neo4j, BoltGraphAdapter;
|
|
43008
|
+
var init_bolt = __esm({
|
|
43009
|
+
async "src/graph/adapters/bolt.ts"() {
|
|
43010
|
+
"use strict";
|
|
43011
|
+
init_shapes();
|
|
43012
|
+
init_errors();
|
|
43013
|
+
init_connectTimeout2();
|
|
43014
|
+
DRIVER_PACKAGE3 = "neo4j-driver";
|
|
43015
|
+
driverModule = await import(DRIVER_PACKAGE3);
|
|
43016
|
+
neo4j = driverModule.default ?? driverModule;
|
|
43017
|
+
BoltGraphAdapter = class {
|
|
43018
|
+
url;
|
|
43019
|
+
database;
|
|
43020
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43021
|
+
driver;
|
|
43022
|
+
lastError = null;
|
|
43023
|
+
constructor(graphUrl, credentials = {}) {
|
|
43024
|
+
this.url = graphUrl;
|
|
43025
|
+
this.database = graphUrl.graph || null;
|
|
43026
|
+
const user = graphUrl.username || credentials.username || "neo4j";
|
|
43027
|
+
const pwd = graphUrl.password || credentials.password || "";
|
|
43028
|
+
const scheme = graphUrl.useTls ? "bolt+s" : "bolt";
|
|
43029
|
+
const uri = `${scheme}://${graphUrl.host}:${graphUrl.port}`;
|
|
43030
|
+
const timeout = resolveGraphConnectTimeout();
|
|
43031
|
+
const config = { disableLosslessIntegers: true };
|
|
43032
|
+
if (timeout !== null) {
|
|
43033
|
+
const ms = Math.max(1, Math.ceil(timeout * 1e3));
|
|
43034
|
+
config.connectionTimeout = ms;
|
|
43035
|
+
config.connectionAcquisitionTimeout = ms;
|
|
43036
|
+
config.maxTransactionRetryTime = ms;
|
|
43037
|
+
}
|
|
43038
|
+
this.driver = neo4j.driver(uri, neo4j.auth.basic(user, pwd), config);
|
|
43039
|
+
}
|
|
43040
|
+
// -- connection + raw pass-through -------------------------------------
|
|
43041
|
+
async run(cypher, params = null) {
|
|
43042
|
+
const session = this.database ? this.driver.session({ database: this.database }) : this.driver.session();
|
|
43043
|
+
try {
|
|
43044
|
+
const result = await session.run(cypher, params ?? {});
|
|
43045
|
+
return result.records.map((record) => record.toObject());
|
|
43046
|
+
} catch (exc) {
|
|
43047
|
+
this.lastError = errorMessage2(exc);
|
|
43048
|
+
const code = exc?.code ?? "";
|
|
43049
|
+
const message = this.lastError.toLowerCase();
|
|
43050
|
+
if (code === "ServiceUnavailable" || code === neo4j.error?.SERVICE_UNAVAILABLE || message.includes("timed out") || message.includes("timeout")) {
|
|
43051
|
+
throw new GraphConnectTimeout(
|
|
43052
|
+
`Graph connect to ${this.url.host}:${this.url.port} timed out (${GRAPH_CONNECT_TIMEOUT_VARIABLE}). Raise ${GRAPH_CONNECT_TIMEOUT_VARIABLE} if the server is simply slow, or set it to 0 to wait indefinitely.`,
|
|
43053
|
+
exc
|
|
43054
|
+
);
|
|
43055
|
+
}
|
|
43056
|
+
throw new GraphError(this.lastError, exc);
|
|
43057
|
+
} finally {
|
|
43058
|
+
await session.close();
|
|
43059
|
+
}
|
|
43060
|
+
}
|
|
43061
|
+
async query(text, params = null) {
|
|
43062
|
+
const rows = await this.run(text, params);
|
|
43063
|
+
const columns = rows.length ? Object.keys(rows[0]) : [];
|
|
43064
|
+
return new GraphResult(rows, columns);
|
|
43065
|
+
}
|
|
43066
|
+
async execute(text, params = null) {
|
|
43067
|
+
return this.query(text, params);
|
|
43068
|
+
}
|
|
43069
|
+
// -- portable node/edge/traverse core (Cypher) -------------------------
|
|
43070
|
+
nodeFromRow(row) {
|
|
43071
|
+
if (row === null || row === void 0) return null;
|
|
43072
|
+
return new GraphNode(
|
|
43073
|
+
String(row.id),
|
|
43074
|
+
row.labels ?? [],
|
|
43075
|
+
row.props ?? {}
|
|
43076
|
+
);
|
|
43077
|
+
}
|
|
43078
|
+
async addNode(label, properties = null) {
|
|
43079
|
+
const cypher = `CREATE (n:\`${label}\` $props) RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
|
|
43080
|
+
const rows = await this.run(cypher, { props: properties ?? {} });
|
|
43081
|
+
return rows.length ? this.nodeFromRow(rows[0]) : null;
|
|
43082
|
+
}
|
|
43083
|
+
async addEdge(fromId, toId, type2, properties = null) {
|
|
43084
|
+
const cypher = `MATCH (a), (b) WHERE id(a) = $from_id AND id(b) = $to_id CREATE (a)-[e:\`${type2}\` $props]->(b) RETURN id(e) AS id, type(e) AS type, id(a) AS f, id(b) AS t, properties(e) AS props`;
|
|
43085
|
+
const rows = await this.run(cypher, {
|
|
43086
|
+
from_id: boltId(fromId),
|
|
43087
|
+
to_id: boltId(toId),
|
|
43088
|
+
props: properties ?? {}
|
|
43089
|
+
});
|
|
43090
|
+
if (rows.length === 0) return null;
|
|
43091
|
+
const row = rows[0];
|
|
43092
|
+
return new GraphEdge(
|
|
43093
|
+
String(row.id),
|
|
43094
|
+
String(row.type),
|
|
43095
|
+
String(row.f),
|
|
43096
|
+
String(row.t),
|
|
43097
|
+
row.props ?? {}
|
|
43098
|
+
);
|
|
43099
|
+
}
|
|
43100
|
+
async getNode(nodeId) {
|
|
43101
|
+
const cypher = `MATCH (n) WHERE id(n) = $id RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
|
|
43102
|
+
const rows = await this.run(cypher, { id: boltId(nodeId) });
|
|
43103
|
+
return rows.length ? this.nodeFromRow(rows[0]) : null;
|
|
43104
|
+
}
|
|
43105
|
+
async updateNode(nodeId, properties) {
|
|
43106
|
+
const cypher = `MATCH (n) WHERE id(n) = $id SET n += $props RETURN id(n) AS id, labels(n) AS labels, properties(n) AS props`;
|
|
43107
|
+
const rows = await this.run(cypher, { id: boltId(nodeId), props: properties ?? {} });
|
|
43108
|
+
return rows.length ? this.nodeFromRow(rows[0]) : null;
|
|
43109
|
+
}
|
|
43110
|
+
async deleteNode(nodeId) {
|
|
43111
|
+
await this.run("MATCH (n) WHERE id(n) = $id DETACH DELETE n", { id: boltId(nodeId) });
|
|
43112
|
+
return true;
|
|
43113
|
+
}
|
|
43114
|
+
async neighbors(nodeId, options = {}) {
|
|
43115
|
+
const direction = options.direction ?? "both";
|
|
43116
|
+
const limit = options.limit ?? 100;
|
|
43117
|
+
const edge = options.edgeType ? `:\`${options.edgeType}\`` : "";
|
|
43118
|
+
const pattern = {
|
|
43119
|
+
out: `(n)-[${edge}]->(m)`,
|
|
43120
|
+
in: `(n)<-[${edge}]-(m)`,
|
|
43121
|
+
both: `(n)-[${edge}]-(m)`
|
|
43122
|
+
}[direction];
|
|
43123
|
+
const cypher = `MATCH ${pattern} WHERE id(n) = $id RETURN DISTINCT id(m) AS id, labels(m) AS labels, properties(m) AS props LIMIT ${Math.trunc(limit)}`;
|
|
43124
|
+
const rows = await this.run(cypher, { id: boltId(nodeId) });
|
|
43125
|
+
return rows.map((row) => this.nodeFromRow(row)).filter((node) => node !== null);
|
|
43126
|
+
}
|
|
43127
|
+
async traverse(startId, options = {}) {
|
|
43128
|
+
const depth = options.depth ?? 1;
|
|
43129
|
+
const direction = options.direction ?? "both";
|
|
43130
|
+
const limit = options.limit ?? 1e3;
|
|
43131
|
+
const edge = options.edgeType ? `:\`${options.edgeType}\`` : "";
|
|
43132
|
+
const range = `*1..${Math.trunc(depth)}`;
|
|
43133
|
+
const arrow = {
|
|
43134
|
+
out: `-[${edge}${range}]->`,
|
|
43135
|
+
in: `<-[${edge}${range}]-`,
|
|
43136
|
+
both: `-[${edge}${range}]-`
|
|
43137
|
+
}[direction];
|
|
43138
|
+
const cypher = `MATCH (n)${arrow}(m) WHERE id(n) = $start RETURN DISTINCT id(m) AS id, labels(m) AS labels, properties(m) AS props LIMIT ${Math.trunc(limit)}`;
|
|
43139
|
+
const rows = await this.run(cypher, { start: boltId(startId) });
|
|
43140
|
+
return rows.map((row) => this.nodeFromRow(row)).filter((node) => node !== null);
|
|
43141
|
+
}
|
|
43142
|
+
async close() {
|
|
43143
|
+
await this.driver.close();
|
|
43144
|
+
}
|
|
43145
|
+
getError() {
|
|
43146
|
+
return this.lastError;
|
|
43147
|
+
}
|
|
43148
|
+
};
|
|
43149
|
+
}
|
|
43150
|
+
});
|
|
43151
|
+
|
|
43152
|
+
// src/graph/adapters/arango.ts
|
|
43153
|
+
var arango_exports = {};
|
|
43154
|
+
__export(arango_exports, {
|
|
43155
|
+
ArangoGraphAdapter: () => ArangoGraphAdapter
|
|
43156
|
+
});
|
|
43157
|
+
function cleanProps(doc) {
|
|
43158
|
+
const props = {};
|
|
43159
|
+
for (const [key, value] of Object.entries(doc)) {
|
|
43160
|
+
if (!RESERVED.has(key)) props[key] = value;
|
|
43161
|
+
}
|
|
43162
|
+
return props;
|
|
43163
|
+
}
|
|
43164
|
+
function errorMessage3(exc) {
|
|
43165
|
+
if (exc instanceof Error) return exc.message;
|
|
43166
|
+
return String(exc);
|
|
43167
|
+
}
|
|
43168
|
+
var DRIVER_PACKAGE4, driverModule2, ArangoDatabase, VERTEX_COLLECTION, EDGE_COLLECTION, RESERVED, ArangoGraphAdapter;
|
|
43169
|
+
var init_arango = __esm({
|
|
43170
|
+
async "src/graph/adapters/arango.ts"() {
|
|
43171
|
+
"use strict";
|
|
43172
|
+
init_shapes();
|
|
43173
|
+
init_errors();
|
|
43174
|
+
init_connectTimeout2();
|
|
43175
|
+
DRIVER_PACKAGE4 = "arangojs";
|
|
43176
|
+
driverModule2 = await import(DRIVER_PACKAGE4);
|
|
43177
|
+
ArangoDatabase = driverModule2.Database ?? driverModule2.default?.Database;
|
|
43178
|
+
VERTEX_COLLECTION = "tina4_nodes";
|
|
43179
|
+
EDGE_COLLECTION = "tina4_edges";
|
|
43180
|
+
RESERVED = /* @__PURE__ */ new Set(["_id", "_key", "_rev", "_from", "_to", "_labels", "_type"]);
|
|
43181
|
+
ArangoGraphAdapter = class {
|
|
43182
|
+
url;
|
|
43183
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43184
|
+
db;
|
|
43185
|
+
ensured = false;
|
|
43186
|
+
lastError = null;
|
|
43187
|
+
constructor(graphUrl, credentials = {}) {
|
|
43188
|
+
this.url = graphUrl;
|
|
43189
|
+
const scheme = graphUrl.useTls ? "https" : "http";
|
|
43190
|
+
const user = graphUrl.username || credentials.username || "root";
|
|
43191
|
+
const pwd = graphUrl.password || credentials.password || "";
|
|
43192
|
+
const database = graphUrl.graph || "_system";
|
|
43193
|
+
const timeout = resolveGraphConnectTimeout();
|
|
43194
|
+
const config = {
|
|
43195
|
+
url: `${scheme}://${graphUrl.host}:${graphUrl.port}`,
|
|
43196
|
+
databaseName: database,
|
|
43197
|
+
auth: { username: user, password: pwd }
|
|
43198
|
+
};
|
|
43199
|
+
if (timeout !== null) config.timeout = Math.max(1, Math.ceil(timeout * 1e3));
|
|
43200
|
+
this.db = new ArangoDatabase(config);
|
|
43201
|
+
}
|
|
43202
|
+
connectOrError(exc) {
|
|
43203
|
+
const text = errorMessage3(exc).toLowerCase();
|
|
43204
|
+
if (text.includes("timed out") || text.includes("timeout") || text.includes("connection") || text.includes("econnrefused") || text.includes("etimedout") || text.includes("max retries")) {
|
|
43205
|
+
return new GraphConnectTimeout(
|
|
43206
|
+
`Graph connect to ${this.url.host}:${this.url.port} timed out (${GRAPH_CONNECT_TIMEOUT_VARIABLE}). Raise ${GRAPH_CONNECT_TIMEOUT_VARIABLE} if the server is simply slow, or set it to 0 to wait indefinitely.`,
|
|
43207
|
+
exc
|
|
43208
|
+
);
|
|
43209
|
+
}
|
|
43210
|
+
return new GraphError(errorMessage3(exc), exc);
|
|
43211
|
+
}
|
|
43212
|
+
async ensureCollections() {
|
|
43213
|
+
if (this.ensured) return;
|
|
43214
|
+
try {
|
|
43215
|
+
const nodes = this.db.collection(VERTEX_COLLECTION);
|
|
43216
|
+
if (!await nodes.exists()) await this.db.createCollection(VERTEX_COLLECTION);
|
|
43217
|
+
const edges = this.db.collection(EDGE_COLLECTION);
|
|
43218
|
+
if (!await edges.exists()) await this.db.createEdgeCollection(EDGE_COLLECTION);
|
|
43219
|
+
this.ensured = true;
|
|
43220
|
+
} catch (exc) {
|
|
43221
|
+
this.lastError = errorMessage3(exc);
|
|
43222
|
+
throw this.connectOrError(exc);
|
|
43223
|
+
}
|
|
43224
|
+
}
|
|
43225
|
+
async aql(query, bind2 = null) {
|
|
43226
|
+
await this.ensureCollections();
|
|
43227
|
+
try {
|
|
43228
|
+
const cursor = await this.db.query({ query, bindVars: bind2 ?? {} });
|
|
43229
|
+
return await cursor.all();
|
|
43230
|
+
} catch (exc) {
|
|
43231
|
+
this.lastError = errorMessage3(exc);
|
|
43232
|
+
throw this.connectOrError(exc);
|
|
43233
|
+
}
|
|
43234
|
+
}
|
|
43235
|
+
async query(text, params = null) {
|
|
43236
|
+
const rows = await this.aql(text, params);
|
|
43237
|
+
const first = rows[0];
|
|
43238
|
+
const columns = rows.length && first && typeof first === "object" ? Object.keys(first) : [];
|
|
43239
|
+
return new GraphResult(rows, columns);
|
|
43240
|
+
}
|
|
43241
|
+
async execute(text, params = null) {
|
|
43242
|
+
return this.query(text, params);
|
|
43243
|
+
}
|
|
43244
|
+
// -- portable node/edge/traverse core (AQL) ----------------------------
|
|
43245
|
+
nodeFromDoc(doc) {
|
|
43246
|
+
if (doc === null || doc === void 0) return null;
|
|
43247
|
+
return new GraphNode(
|
|
43248
|
+
String(doc._id),
|
|
43249
|
+
doc._labels ?? [],
|
|
43250
|
+
cleanProps(doc)
|
|
43251
|
+
);
|
|
43252
|
+
}
|
|
43253
|
+
async addNode(label, properties = null) {
|
|
43254
|
+
const doc = { ...properties ?? {}, _labels: [label] };
|
|
43255
|
+
const rows = await this.aql(`INSERT @doc INTO ${VERTEX_COLLECTION} RETURN NEW`, { doc });
|
|
43256
|
+
return rows.length ? this.nodeFromDoc(rows[0]) : null;
|
|
43257
|
+
}
|
|
43258
|
+
async addEdge(fromId, toId, type2, properties = null) {
|
|
43259
|
+
const doc = { ...properties ?? {}, _from: fromId, _to: toId, _type: type2 };
|
|
43260
|
+
const rows = await this.aql(`INSERT @doc INTO ${EDGE_COLLECTION} RETURN NEW`, { doc });
|
|
43261
|
+
if (rows.length === 0) return null;
|
|
43262
|
+
const row = rows[0];
|
|
43263
|
+
return new GraphEdge(
|
|
43264
|
+
String(row._id),
|
|
43265
|
+
String(row._type),
|
|
43266
|
+
String(row._from),
|
|
43267
|
+
String(row._to),
|
|
43268
|
+
cleanProps(row)
|
|
43269
|
+
);
|
|
43270
|
+
}
|
|
43271
|
+
async getNode(nodeId) {
|
|
43272
|
+
const rows = await this.aql("RETURN DOCUMENT(@id)", { id: nodeId });
|
|
43273
|
+
return rows.length && rows[0] ? this.nodeFromDoc(rows[0]) : null;
|
|
43274
|
+
}
|
|
43275
|
+
async updateNode(nodeId, properties) {
|
|
43276
|
+
const rows = await this.aql(
|
|
43277
|
+
`UPDATE PARSE_IDENTIFIER(@id).key WITH @props IN ${VERTEX_COLLECTION} RETURN NEW`,
|
|
43278
|
+
{ id: nodeId, props: properties ?? {} }
|
|
43279
|
+
);
|
|
43280
|
+
return rows.length ? this.nodeFromDoc(rows[0]) : null;
|
|
43281
|
+
}
|
|
43282
|
+
async deleteNode(nodeId) {
|
|
43283
|
+
await this.aql(
|
|
43284
|
+
`FOR e IN ${EDGE_COLLECTION} FILTER e._from == @id OR e._to == @id REMOVE e IN ${EDGE_COLLECTION}`,
|
|
43285
|
+
{ id: nodeId }
|
|
43286
|
+
);
|
|
43287
|
+
await this.aql(
|
|
43288
|
+
`REMOVE PARSE_IDENTIFIER(@id).key IN ${VERTEX_COLLECTION}`,
|
|
43289
|
+
{ id: nodeId }
|
|
43290
|
+
);
|
|
43291
|
+
return true;
|
|
43292
|
+
}
|
|
43293
|
+
async neighbors(nodeId, options = {}) {
|
|
43294
|
+
const direction = options.direction ?? "both";
|
|
43295
|
+
const limit = options.limit ?? 100;
|
|
43296
|
+
const arangoDir = { out: "OUTBOUND", in: "INBOUND", both: "ANY" }[direction];
|
|
43297
|
+
const typeFilter = options.edgeType ? "FILTER e._type == @etype " : "";
|
|
43298
|
+
const bind2 = { start: nodeId, limit: Math.trunc(limit) };
|
|
43299
|
+
if (options.edgeType) bind2.etype = options.edgeType;
|
|
43300
|
+
const rows = await this.aql(
|
|
43301
|
+
`FOR v, e IN 1..1 ${arangoDir} @start ${EDGE_COLLECTION} ${typeFilter}LIMIT @limit RETURN DISTINCT v`,
|
|
43302
|
+
bind2
|
|
43303
|
+
);
|
|
43304
|
+
return rows.map((doc) => this.nodeFromDoc(doc)).filter((node) => node !== null);
|
|
43305
|
+
}
|
|
43306
|
+
async traverse(startId, options = {}) {
|
|
43307
|
+
const depth = options.depth ?? 1;
|
|
43308
|
+
const direction = options.direction ?? "both";
|
|
43309
|
+
const limit = options.limit ?? 1e3;
|
|
43310
|
+
const arangoDir = { out: "OUTBOUND", in: "INBOUND", both: "ANY" }[direction];
|
|
43311
|
+
const typeFilter = options.edgeType ? "FILTER e._type == @etype " : "";
|
|
43312
|
+
const bind2 = { start: startId, limit: Math.trunc(limit) };
|
|
43313
|
+
if (options.edgeType) bind2.etype = options.edgeType;
|
|
43314
|
+
const rows = await this.aql(
|
|
43315
|
+
`FOR v, e IN 1..${Math.trunc(depth)} ${arangoDir} @start ${EDGE_COLLECTION} ${typeFilter}LIMIT @limit RETURN DISTINCT v`,
|
|
43316
|
+
bind2
|
|
43317
|
+
);
|
|
43318
|
+
return rows.map((doc) => this.nodeFromDoc(doc)).filter((node) => node !== null);
|
|
43319
|
+
}
|
|
43320
|
+
async close() {
|
|
43321
|
+
if (typeof this.db.close === "function") this.db.close();
|
|
43322
|
+
}
|
|
43323
|
+
getError() {
|
|
43324
|
+
return this.lastError;
|
|
43325
|
+
}
|
|
43326
|
+
};
|
|
43327
|
+
}
|
|
43328
|
+
});
|
|
43329
|
+
|
|
43330
|
+
// src/graph/graphDatabase.ts
|
|
43331
|
+
var ENGINE_ADAPTERS, GraphDatabase;
|
|
43332
|
+
var init_graphDatabase = __esm({
|
|
43333
|
+
"src/graph/graphDatabase.ts"() {
|
|
43334
|
+
"use strict";
|
|
43335
|
+
init_graphUrl();
|
|
43336
|
+
init_errors();
|
|
43337
|
+
ENGINE_ADAPTERS = {
|
|
43338
|
+
ultipa: {
|
|
43339
|
+
load: () => init_ultipa().then(() => ultipa_exports),
|
|
43340
|
+
className: "UltipaGraphAdapter",
|
|
43341
|
+
package: "tina4-ultipa",
|
|
43342
|
+
installCommand: "npm install tina4-ultipa"
|
|
43343
|
+
},
|
|
43344
|
+
bolt: {
|
|
43345
|
+
// Neo4j AND Memgraph — both speak Bolt/Cypher over the neo4j-driver package.
|
|
43346
|
+
load: () => init_bolt().then(() => bolt_exports),
|
|
43347
|
+
className: "BoltGraphAdapter",
|
|
43348
|
+
package: "neo4j-driver",
|
|
43349
|
+
installCommand: "npm install neo4j-driver"
|
|
43350
|
+
},
|
|
43351
|
+
arango: {
|
|
43352
|
+
load: () => init_arango().then(() => arango_exports),
|
|
43353
|
+
className: "ArangoGraphAdapter",
|
|
43354
|
+
package: "arangojs",
|
|
43355
|
+
installCommand: "npm install arangojs"
|
|
43356
|
+
}
|
|
43357
|
+
};
|
|
43358
|
+
GraphDatabase = class _GraphDatabase {
|
|
43359
|
+
/**
|
|
43360
|
+
* Parse the URL, pick the engine adapter, connect lazily.
|
|
43361
|
+
*
|
|
43362
|
+
* The engine driver is imported only here (first use of that engine); if it is
|
|
43363
|
+
* absent the error names the package and the install command. Async because the
|
|
43364
|
+
* driver import is dynamic — the connect itself still happens lazily on first
|
|
43365
|
+
* operation (mirroring the relational adapters).
|
|
43366
|
+
*/
|
|
43367
|
+
static async create(url, credentials = {}) {
|
|
43368
|
+
const graphUrl = new GraphUrl(url);
|
|
43369
|
+
const registration = ENGINE_ADAPTERS[graphUrl.engine];
|
|
43370
|
+
if (registration === void 0) {
|
|
43371
|
+
throw new GraphError(
|
|
43372
|
+
`No graph adapter for engine '${graphUrl.engine}' yet (scheme '${graphUrl.scheme}'). Available: ${Object.keys(ENGINE_ADAPTERS).sort().join(", ")}.`
|
|
43373
|
+
);
|
|
43374
|
+
}
|
|
43375
|
+
let module;
|
|
43376
|
+
try {
|
|
43377
|
+
module = await registration.load();
|
|
43378
|
+
} catch (cause) {
|
|
43379
|
+
throw new GraphError(
|
|
43380
|
+
`The graph driver for '${graphUrl.engine}' is not installed (${registration.package}). Install it with:
|
|
43381
|
+
${registration.installCommand}`,
|
|
43382
|
+
cause
|
|
43383
|
+
);
|
|
43384
|
+
}
|
|
43385
|
+
const AdapterClass = module[registration.className];
|
|
43386
|
+
if (AdapterClass === void 0) {
|
|
43387
|
+
throw new GraphError(
|
|
43388
|
+
`The graph adapter '${registration.className}' is missing from its module for engine '${graphUrl.engine}'.`
|
|
43389
|
+
);
|
|
43390
|
+
}
|
|
43391
|
+
return new AdapterClass(graphUrl, credentials);
|
|
43392
|
+
}
|
|
43393
|
+
/** Build from TINA4_GRAPH_URL (+ TINA4_GRAPH_USERNAME/_PASSWORD). */
|
|
43394
|
+
static async fromEnv(envKey = "TINA4_GRAPH_URL") {
|
|
43395
|
+
const url = (process.env[envKey] ?? "").trim();
|
|
43396
|
+
if (url === "") return null;
|
|
43397
|
+
return _GraphDatabase.create(url, {
|
|
43398
|
+
username: process.env.TINA4_GRAPH_USERNAME,
|
|
43399
|
+
password: process.env.TINA4_GRAPH_PASSWORD
|
|
43400
|
+
});
|
|
43401
|
+
}
|
|
43402
|
+
};
|
|
43403
|
+
}
|
|
43404
|
+
});
|
|
43405
|
+
|
|
42623
43406
|
// src/realtime/models/workspace.ts
|
|
42624
43407
|
var Workspace;
|
|
42625
43408
|
var init_workspace = __esm({
|
|
@@ -43178,6 +43961,7 @@ __export(index_exports, {
|
|
|
43178
43961
|
CachedDatabaseAdapter: () => CachedDatabaseAdapter,
|
|
43179
43962
|
Cursor: () => Cursor,
|
|
43180
43963
|
DEFAULT_DATABASE_CONNECT_TIMEOUT_SECONDS: () => DEFAULT_DATABASE_CONNECT_TIMEOUT_SECONDS,
|
|
43964
|
+
DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS: () => DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS,
|
|
43181
43965
|
DEFAULT_SRID: () => DEFAULT_SRID,
|
|
43182
43966
|
Database: () => Database,
|
|
43183
43967
|
DatabaseResult: () => DatabaseResult,
|
|
@@ -43185,6 +43969,14 @@ __export(index_exports, {
|
|
|
43185
43969
|
DocStoreDriverMissing: () => DocStoreDriverMissing,
|
|
43186
43970
|
FakeData: () => FakeData2,
|
|
43187
43971
|
FirebirdAdapter: () => FirebirdAdapter,
|
|
43972
|
+
GRAPH_CONNECT_TIMEOUT_VARIABLE: () => GRAPH_CONNECT_TIMEOUT_VARIABLE,
|
|
43973
|
+
GraphConnectTimeout: () => GraphConnectTimeout,
|
|
43974
|
+
GraphDatabase: () => GraphDatabase,
|
|
43975
|
+
GraphEdge: () => GraphEdge,
|
|
43976
|
+
GraphError: () => GraphError,
|
|
43977
|
+
GraphNode: () => GraphNode,
|
|
43978
|
+
GraphResult: () => GraphResult,
|
|
43979
|
+
GraphUrl: () => GraphUrl,
|
|
43188
43980
|
InvalidId: () => InvalidId,
|
|
43189
43981
|
LocalStorage: () => LocalStorage,
|
|
43190
43982
|
Migration: () => Migration,
|
|
@@ -43266,6 +44058,7 @@ __export(index_exports, {
|
|
|
43266
44058
|
resetRequestCaches: () => resetRequestCaches2,
|
|
43267
44059
|
resolveDbPool: () => resolveDbPool,
|
|
43268
44060
|
resolveFirebirdCharset: () => resolveFirebirdCharset,
|
|
44061
|
+
resolveGraphConnectTimeout: () => resolveGraphConnectTimeout,
|
|
43269
44062
|
rollback: () => rollback,
|
|
43270
44063
|
seedModels: () => seedModels,
|
|
43271
44064
|
seedOrm: () => seedOrm,
|
|
@@ -43314,6 +44107,11 @@ var init_index = __esm({
|
|
|
43314
44107
|
init_firebird();
|
|
43315
44108
|
init_mongodb();
|
|
43316
44109
|
init_odbc();
|
|
44110
|
+
init_graphDatabase();
|
|
44111
|
+
init_graphUrl();
|
|
44112
|
+
init_shapes();
|
|
44113
|
+
init_errors();
|
|
44114
|
+
init_connectTimeout2();
|
|
43317
44115
|
init_realtime2();
|
|
43318
44116
|
}
|
|
43319
44117
|
});
|
|
@@ -43325,6 +44123,7 @@ export {
|
|
|
43325
44123
|
CachedDatabaseAdapter,
|
|
43326
44124
|
Cursor,
|
|
43327
44125
|
DEFAULT_DATABASE_CONNECT_TIMEOUT_SECONDS,
|
|
44126
|
+
DEFAULT_GRAPH_CONNECT_TIMEOUT_SECONDS,
|
|
43328
44127
|
DEFAULT_SRID,
|
|
43329
44128
|
Database,
|
|
43330
44129
|
DatabaseResult,
|
|
@@ -43332,6 +44131,14 @@ export {
|
|
|
43332
44131
|
DocStoreDriverMissing,
|
|
43333
44132
|
FakeData2 as FakeData,
|
|
43334
44133
|
FirebirdAdapter,
|
|
44134
|
+
GRAPH_CONNECT_TIMEOUT_VARIABLE,
|
|
44135
|
+
GraphConnectTimeout,
|
|
44136
|
+
GraphDatabase,
|
|
44137
|
+
GraphEdge,
|
|
44138
|
+
GraphError,
|
|
44139
|
+
GraphNode,
|
|
44140
|
+
GraphResult,
|
|
44141
|
+
GraphUrl,
|
|
43335
44142
|
InvalidId,
|
|
43336
44143
|
LocalStorage,
|
|
43337
44144
|
Migration,
|
|
@@ -43413,6 +44220,7 @@ export {
|
|
|
43413
44220
|
resetRequestCaches2 as resetRequestCaches,
|
|
43414
44221
|
resolveDbPool,
|
|
43415
44222
|
resolveFirebirdCharset,
|
|
44223
|
+
resolveGraphConnectTimeout,
|
|
43416
44224
|
rollback,
|
|
43417
44225
|
seedModels,
|
|
43418
44226
|
seedOrm,
|