@objectstack/service-datasource 10.0.0 → 10.2.0
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/.turbo/turbo-build.log +19 -15
- package/CHANGELOG.md +69 -0
- package/dist/chunk-BI2SYWLC.cjs +9 -0
- package/dist/chunk-BI2SYWLC.cjs.map +1 -0
- package/dist/chunk-XLS4RP7B.js +9 -0
- package/dist/chunk-XLS4RP7B.js.map +1 -0
- package/dist/contracts/index.cjs +7 -1
- package/dist/contracts/index.cjs.map +1 -1
- package/dist/contracts/index.d.cts +59 -1
- package/dist/contracts/index.d.ts +59 -1
- package/dist/contracts/index.js +6 -0
- package/dist/index.cjs +269 -99
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +176 -4
- package/dist/index.d.ts +176 -4
- package/dist/index.js +201 -31
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
- package/src/__tests__/datasource-connection-service.test.ts +294 -0
- package/src/contracts/connect-policy.ts +69 -0
- package/src/contracts/index.ts +11 -0
- package/src/datasource-admin-plugin.ts +37 -40
- package/src/datasource-admin-service.ts +2 -0
- package/src/datasource-connection-service.ts +364 -0
- package/src/index.ts +18 -0
- package/src/logger.ts +2 -0
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
|
+
|
|
3
|
+
var _chunkBI2SYWLCcjs = require('./chunk-BI2SYWLC.cjs');
|
|
4
|
+
|
|
5
|
+
// src/external-datasource-service.ts
|
|
2
6
|
|
|
3
7
|
|
|
4
8
|
|
|
@@ -368,6 +372,179 @@ function safeGetService(ctx, name) {
|
|
|
368
372
|
}
|
|
369
373
|
}
|
|
370
374
|
|
|
375
|
+
// src/datasource-connection-service.ts
|
|
376
|
+
function isDatasourceAddressed(ds, ctx) {
|
|
377
|
+
if (ds.schemaMode && ds.schemaMode !== "managed") return true;
|
|
378
|
+
if (ds.autoConnect === true) return true;
|
|
379
|
+
if (_optionalChain([ctx, 'access', _38 => _38.objects, 'optionalAccess', _39 => _39.some, 'call', _40 => _40((o) => _optionalChain([o, 'optionalAccess', _41 => _41.datasource]) === ds.name)])) return true;
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
var DatasourceConnectionService = class {
|
|
383
|
+
constructor(cfg) {
|
|
384
|
+
this.cfg = cfg;
|
|
385
|
+
this.policy = _nullishCoalesce(cfg.policy, () => ( _chunkBI2SYWLCcjs.allowAllConnectPolicy));
|
|
386
|
+
this.logger = cfg.logger;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Auto-connect the declared (code-defined) datasources that pass the D2 gate.
|
|
390
|
+
* Called from `AppPlugin.start()` with the app bundle's datasources + objects.
|
|
391
|
+
* Each connected external datasource also has its bound objects' read metadata
|
|
392
|
+
* synced so they are immediately queryable with zero app code.
|
|
393
|
+
*/
|
|
394
|
+
async connectDeclared(input) {
|
|
395
|
+
const objects = _nullishCoalesce(input.objects, () => ( []));
|
|
396
|
+
const results = [];
|
|
397
|
+
for (const ds of input.datasources) {
|
|
398
|
+
if (!_optionalChain([ds, 'optionalAccess', _42 => _42.name])) continue;
|
|
399
|
+
if (ds.active === false) continue;
|
|
400
|
+
if (!isDatasourceAddressed(ds, { objects })) continue;
|
|
401
|
+
const bound = objects.filter((o) => _optionalChain([o, 'optionalAccess', _43 => _43.datasource]) === ds.name && typeof _optionalChain([o, 'optionalAccess', _44 => _44.name]) === "string").map((o) => o.name);
|
|
402
|
+
results.push(
|
|
403
|
+
await this.connect(ds, { objects: bound, context: { origin: _nullishCoalesce(ds.origin, () => ( "code")), trigger: "declared-auto" } })
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
return results;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Build + connect + register a single datasource's live driver. The shared
|
|
410
|
+
* core used by both auto-connect and the runtime-admin pool registration.
|
|
411
|
+
*
|
|
412
|
+
* Failure policy (ADR-0062 D5): an `external` datasource with
|
|
413
|
+
* `validation.onMismatch: 'fail'` fails fast (re-throws, bricking boot as
|
|
414
|
+
* intended); everything else degrades with a warning so an optional replica's
|
|
415
|
+
* connectivity blip never bricks boot.
|
|
416
|
+
*/
|
|
417
|
+
async connect(record, opts = {}) {
|
|
418
|
+
const name = record.name;
|
|
419
|
+
const engine = this.cfg.engine();
|
|
420
|
+
const factory = this.cfg.factory();
|
|
421
|
+
if (_optionalChain([engine, 'optionalAccess', _45 => _45.getDriverByName, 'optionalCall', _46 => _46(name)])) {
|
|
422
|
+
return { name, status: "already-registered" };
|
|
423
|
+
}
|
|
424
|
+
let decision;
|
|
425
|
+
try {
|
|
426
|
+
decision = await this.policy.canConnect(
|
|
427
|
+
{ name, driver: record.driver, schemaMode: record.schemaMode, external: record.external },
|
|
428
|
+
opts.context
|
|
429
|
+
);
|
|
430
|
+
} catch (err) {
|
|
431
|
+
decision = { allow: false, reason: `connect policy threw: ${errMsg(err)}` };
|
|
432
|
+
}
|
|
433
|
+
if (!decision.allow) {
|
|
434
|
+
_optionalChain([this, 'access', _47 => _47.logger, 'optionalAccess', _48 => _48.info, 'optionalCall', _49 => _49(`datasource '${name}': connect denied by policy${decision.reason ? ` (${decision.reason})` : ""}`)]);
|
|
435
|
+
return { name, status: "skipped-policy", reason: decision.reason };
|
|
436
|
+
}
|
|
437
|
+
if (!factory || !_optionalChain([engine, 'optionalAccess', _50 => _50.registerDriver])) {
|
|
438
|
+
_optionalChain([this, 'access', _51 => _51.logger, 'optionalAccess', _52 => _52.debug, 'optionalCall', _53 => _53(`datasource '${name}': no driver factory / engine \u2014 left metadata-only`)]);
|
|
439
|
+
return { name, status: "skipped-no-infra" };
|
|
440
|
+
}
|
|
441
|
+
if (!factory.supports(record.driver)) {
|
|
442
|
+
return this.handleFailure(
|
|
443
|
+
record,
|
|
444
|
+
"skipped-unsupported",
|
|
445
|
+
`no driver factory supports driver '${record.driver}'`,
|
|
446
|
+
opts.context
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
let secret;
|
|
450
|
+
const credentialsRef = _optionalChain([record, 'access', _54 => _54.external, 'optionalAccess', _55 => _55.credentialsRef]);
|
|
451
|
+
if (credentialsRef) {
|
|
452
|
+
const resolver = _optionalChain([this, 'access', _56 => _56.cfg, 'access', _57 => _57.secrets, 'optionalAccess', _58 => _58.resolve]);
|
|
453
|
+
if (!resolver) {
|
|
454
|
+
return this.handleFailure(
|
|
455
|
+
record,
|
|
456
|
+
"failed-credentials",
|
|
457
|
+
`requires credential '${credentialsRef}' but no secret store (SecretBinder/ICryptoProvider) is configured`,
|
|
458
|
+
opts.context
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
try {
|
|
462
|
+
secret = await resolver(credentialsRef);
|
|
463
|
+
} catch (err) {
|
|
464
|
+
return this.handleFailure(record, "failed-credentials", `resolving credential '${credentialsRef}' threw: ${errMsg(err)}`, opts.context);
|
|
465
|
+
}
|
|
466
|
+
if (secret == null || secret === "") {
|
|
467
|
+
return this.handleFailure(
|
|
468
|
+
record,
|
|
469
|
+
"failed-credentials",
|
|
470
|
+
`credential '${credentialsRef}' could not be resolved or decrypted (missing sys_secret row, or the encryption key changed)`,
|
|
471
|
+
opts.context
|
|
472
|
+
);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
try {
|
|
476
|
+
const handle = await factory.create({ ...toSpec(record), ...secret ? { secret } : {} });
|
|
477
|
+
if (typeof _optionalChain([handle, 'optionalAccess', _59 => _59.connect]) === "function") await handle.connect();
|
|
478
|
+
const engineDriver = _nullishCoalesce(handle.driver, () => ( handle));
|
|
479
|
+
try {
|
|
480
|
+
engineDriver.name = name;
|
|
481
|
+
} catch (e2) {
|
|
482
|
+
}
|
|
483
|
+
engine.registerDriver(engineDriver);
|
|
484
|
+
_optionalChain([engine, 'access', _60 => _60.registerDatasourceDef, 'optionalCall', _61 => _61({
|
|
485
|
+
name,
|
|
486
|
+
schemaMode: record.schemaMode,
|
|
487
|
+
external: record.external
|
|
488
|
+
})]);
|
|
489
|
+
for (const objectName of _nullishCoalesce(opts.objects, () => ( []))) {
|
|
490
|
+
try {
|
|
491
|
+
await _optionalChain([engine, 'access', _62 => _62.syncObjectSchema, 'optionalCall', _63 => _63(objectName)]);
|
|
492
|
+
} catch (err) {
|
|
493
|
+
_optionalChain([this, 'access', _64 => _64.logger, 'optionalAccess', _65 => _65.warn, 'optionalCall', _66 => _66(`datasource '${name}': syncObjectSchema('${objectName}') failed: ${errMsg(err)}`)]);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
_optionalChain([this, 'access', _67 => _67.logger, 'optionalAccess', _68 => _68.info, 'optionalCall', _69 => _69(`datasource '${name}': connected (driver=${record.driver}, schemaMode=${_nullishCoalesce(record.schemaMode, () => ( "managed"))})`)]);
|
|
497
|
+
return { name, status: "connected" };
|
|
498
|
+
} catch (err) {
|
|
499
|
+
return this.handleFailure(record, "failed-degraded", errMsg(err), opts.context);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
/** Gracefully disconnect a previously-registered datasource pool. */
|
|
503
|
+
async disconnect(name) {
|
|
504
|
+
const driver = _optionalChain([this, 'access', _70 => _70.cfg, 'access', _71 => _71.engine, 'call', _72 => _72(), 'optionalAccess', _73 => _73.getDriverByName, 'optionalCall', _74 => _74(name)]);
|
|
505
|
+
if (typeof _optionalChain([driver, 'optionalAccess', _75 => _75.disconnect]) === "function") {
|
|
506
|
+
try {
|
|
507
|
+
await driver.disconnect();
|
|
508
|
+
} catch (err) {
|
|
509
|
+
_optionalChain([this, 'access', _76 => _76.logger, 'optionalAccess', _77 => _77.warn, 'optionalCall', _78 => _78(`datasource '${name}': disconnect failed: ${errMsg(err)}`)]);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Apply the D5 connect-failure policy (also covers D3 credential failures). A
|
|
515
|
+
* code-defined `external` datasource with `onMismatch:'fail'` auto-connected at
|
|
516
|
+
* boot re-throws (fail-fast, bricking boot as intended). Runtime-admin
|
|
517
|
+
* create/update + boot rehydration always degrade-with-warning — a UI action
|
|
518
|
+
* or a replica blip must never brick the running server (preserves the
|
|
519
|
+
* pre-ADR-0062 admin behavior). Either way the datasource is left unconnected
|
|
520
|
+
* with a clear message — never a silent skip.
|
|
521
|
+
*/
|
|
522
|
+
handleFailure(record, status, reason, context) {
|
|
523
|
+
const isExternal = record.schemaMode && record.schemaMode !== "managed";
|
|
524
|
+
const failFast = _optionalChain([context, 'optionalAccess', _79 => _79.trigger]) === "declared-auto" && isExternal && _optionalChain([record, 'access', _80 => _80.external, 'optionalAccess', _81 => _81.validation, 'optionalAccess', _82 => _82.onMismatch]) === "fail";
|
|
525
|
+
const msg = `datasource '${record.name}': connect failed \u2014 ${reason}`;
|
|
526
|
+
if (failFast) {
|
|
527
|
+
throw new Error(
|
|
528
|
+
`${msg}. (schemaMode=${record.schemaMode}, validation.onMismatch='fail' \u21D2 fail-fast per ADR-0062 D5)`
|
|
529
|
+
);
|
|
530
|
+
}
|
|
531
|
+
_optionalChain([this, 'access', _83 => _83.logger, 'optionalAccess', _84 => _84.warn, 'optionalCall', _85 => _85(`${msg} \u2014 degrading (datasource left unconnected)`)]);
|
|
532
|
+
return { name: record.name, status, reason };
|
|
533
|
+
}
|
|
534
|
+
};
|
|
535
|
+
function toSpec(record) {
|
|
536
|
+
return {
|
|
537
|
+
name: record.name,
|
|
538
|
+
driver: record.driver,
|
|
539
|
+
config: _nullishCoalesce(record.config, () => ( {})),
|
|
540
|
+
external: record.external,
|
|
541
|
+
pool: record.pool
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function errMsg(err) {
|
|
545
|
+
return err instanceof Error ? err.message : String(err);
|
|
546
|
+
}
|
|
547
|
+
|
|
371
548
|
// src/datasource-admin-service.ts
|
|
372
549
|
var NAME_RE = /^[a-z_][a-z0-9_]*$/;
|
|
373
550
|
var DatasourceAdminService = class {
|
|
@@ -398,7 +575,7 @@ var DatasourceAdminService = class {
|
|
|
398
575
|
origin: slot.code ? "code" : "runtime",
|
|
399
576
|
active: _nullishCoalesce(effective.active, () => ( true)),
|
|
400
577
|
status: "unvalidated",
|
|
401
|
-
..._optionalChain([slot, 'access',
|
|
578
|
+
..._optionalChain([slot, 'access', _86 => _86.code, 'optionalAccess', _87 => _87.definedIn]) ? { definedIn: slot.code.definedIn } : {},
|
|
402
579
|
...slot.code && slot.runtime ? { conflictsWithCode: true } : {}
|
|
403
580
|
});
|
|
404
581
|
}
|
|
@@ -414,7 +591,7 @@ var DatasourceAdminService = class {
|
|
|
414
591
|
async getDatasource(name) {
|
|
415
592
|
const rec = await this.config.getDatasourceRecord(name);
|
|
416
593
|
if (!rec) return void 0;
|
|
417
|
-
const hasSecret = Boolean(_optionalChain([rec, 'access',
|
|
594
|
+
const hasSecret = Boolean(_optionalChain([rec, 'access', _88 => _88.external, 'optionalAccess', _89 => _89.credentialsRef]));
|
|
418
595
|
return {
|
|
419
596
|
name: rec.name,
|
|
420
597
|
label: rec.label,
|
|
@@ -428,15 +605,15 @@ var DatasourceAdminService = class {
|
|
|
428
605
|
};
|
|
429
606
|
}
|
|
430
607
|
async testConnection(input, secret) {
|
|
431
|
-
if (!_optionalChain([input, 'optionalAccess',
|
|
608
|
+
if (!_optionalChain([input, 'optionalAccess', _90 => _90.driver])) {
|
|
432
609
|
return { ok: false, error: "A driver is required to test a connection." };
|
|
433
610
|
}
|
|
434
|
-
const queryTimeoutMs = _optionalChain([input, 'access',
|
|
611
|
+
const queryTimeoutMs = _optionalChain([input, 'access', _91 => _91.external, 'optionalAccess', _92 => _92.queryTimeoutMs]);
|
|
435
612
|
try {
|
|
436
613
|
return await this.config.probe({
|
|
437
614
|
driver: input.driver,
|
|
438
615
|
config: _nullishCoalesce(input.config, () => ( {})),
|
|
439
|
-
secret: _optionalChain([secret, 'optionalAccess',
|
|
616
|
+
secret: _optionalChain([secret, 'optionalAccess', _93 => _93.value]),
|
|
440
617
|
external: input.external,
|
|
441
618
|
...typeof queryTimeoutMs === "number" ? { timeoutMs: queryTimeoutMs } : {}
|
|
442
619
|
});
|
|
@@ -445,7 +622,7 @@ var DatasourceAdminService = class {
|
|
|
445
622
|
}
|
|
446
623
|
}
|
|
447
624
|
async createDatasource(input, secret) {
|
|
448
|
-
this.assertValidName(_optionalChain([input, 'optionalAccess',
|
|
625
|
+
this.assertValidName(_optionalChain([input, 'optionalAccess', _94 => _94.name]));
|
|
449
626
|
if (!input.driver) throw new Error("A driver is required to create a datasource.");
|
|
450
627
|
const existing = await this.config.getDatasourceRecord(input.name);
|
|
451
628
|
if (existing) {
|
|
@@ -486,10 +663,10 @@ var DatasourceAdminService = class {
|
|
|
486
663
|
origin: "runtime"
|
|
487
664
|
};
|
|
488
665
|
if (patch.external !== void 0) {
|
|
489
|
-
merged.external = { ...patch.external, credentialsRef: _optionalChain([existing, 'access',
|
|
666
|
+
merged.external = { ...patch.external, credentialsRef: _optionalChain([existing, 'access', _95 => _95.external, 'optionalAccess', _96 => _96.credentialsRef]) };
|
|
490
667
|
}
|
|
491
668
|
if (secret) {
|
|
492
|
-
const prevRef = _optionalChain([existing, 'access',
|
|
669
|
+
const prevRef = _optionalChain([existing, 'access', _97 => _97.external, 'optionalAccess', _98 => _98.credentialsRef]);
|
|
493
670
|
const credentialsRef = await this.config.writeSecret(secret, { name });
|
|
494
671
|
merged.external = { ..._nullishCoalesce(merged.external, () => ( {})), credentialsRef };
|
|
495
672
|
if (prevRef && prevRef !== credentialsRef) await this.tryRemoveSecret(prevRef);
|
|
@@ -511,7 +688,7 @@ var DatasourceAdminService = class {
|
|
|
511
688
|
);
|
|
512
689
|
}
|
|
513
690
|
await this.config.deleteDatasourceRecord(name);
|
|
514
|
-
if (_optionalChain([existing, 'access',
|
|
691
|
+
if (_optionalChain([existing, 'access', _99 => _99.external, 'optionalAccess', _100 => _100.credentialsRef])) await this.tryRemoveSecret(existing.external.credentialsRef);
|
|
515
692
|
await this.tryUnregisterPool(name);
|
|
516
693
|
}
|
|
517
694
|
// --- internals -----------------------------------------------------------
|
|
@@ -547,23 +724,23 @@ var DatasourceAdminService = class {
|
|
|
547
724
|
}
|
|
548
725
|
async tryRegisterPool(record) {
|
|
549
726
|
try {
|
|
550
|
-
await _optionalChain([this, 'access',
|
|
727
|
+
await _optionalChain([this, 'access', _101 => _101.config, 'access', _102 => _102.registerPool, 'optionalCall', _103 => _103(record)]);
|
|
551
728
|
} catch (err) {
|
|
552
|
-
_optionalChain([this, 'access',
|
|
729
|
+
_optionalChain([this, 'access', _104 => _104.logger, 'optionalAccess', _105 => _105.warn, 'call', _106 => _106(`registerPool('${record.name}') failed`, err)]);
|
|
553
730
|
}
|
|
554
731
|
}
|
|
555
732
|
async tryUnregisterPool(name) {
|
|
556
733
|
try {
|
|
557
|
-
await _optionalChain([this, 'access',
|
|
734
|
+
await _optionalChain([this, 'access', _107 => _107.config, 'access', _108 => _108.unregisterPool, 'optionalCall', _109 => _109(name)]);
|
|
558
735
|
} catch (err) {
|
|
559
|
-
_optionalChain([this, 'access',
|
|
736
|
+
_optionalChain([this, 'access', _110 => _110.logger, 'optionalAccess', _111 => _111.warn, 'call', _112 => _112(`unregisterPool('${name}') failed`, err)]);
|
|
560
737
|
}
|
|
561
738
|
}
|
|
562
739
|
async tryRemoveSecret(credentialsRef) {
|
|
563
740
|
try {
|
|
564
|
-
await _optionalChain([this, 'access',
|
|
741
|
+
await _optionalChain([this, 'access', _113 => _113.config, 'access', _114 => _114.removeSecret, 'optionalCall', _115 => _115(credentialsRef)]);
|
|
565
742
|
} catch (err) {
|
|
566
|
-
_optionalChain([this, 'access',
|
|
743
|
+
_optionalChain([this, 'access', _116 => _116.logger, 'optionalAccess', _117 => _117.warn, 'call', _118 => _118(`removeSecret('${credentialsRef}') failed`, err)]);
|
|
567
744
|
}
|
|
568
745
|
}
|
|
569
746
|
};
|
|
@@ -576,13 +753,13 @@ function newMetaId() {
|
|
|
576
753
|
return typeof crypto !== "undefined" && typeof crypto.randomUUID === "function" ? crypto.randomUUID() : `meta_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
577
754
|
}
|
|
578
755
|
async function persistDatasourceRow(engine, record) {
|
|
579
|
-
if (!_optionalChain([engine, 'optionalAccess',
|
|
756
|
+
if (!_optionalChain([engine, 'optionalAccess', _119 => _119.insert]) || !engine.findOne) return;
|
|
580
757
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
581
758
|
const existing = await engine.findOne(SYS_METADATA, {
|
|
582
759
|
where: { type: DS_META_TYPE, name: record.name, state: "active" }
|
|
583
760
|
});
|
|
584
761
|
if (existing) {
|
|
585
|
-
await _optionalChain([engine, 'access',
|
|
762
|
+
await _optionalChain([engine, 'access', _120 => _120.update, 'optionalCall', _121 => _121(
|
|
586
763
|
SYS_METADATA,
|
|
587
764
|
{ metadata: JSON.stringify(record), updated_at: now, version: (existing.version || 0) + 1, state: "active" },
|
|
588
765
|
{ where: { id: existing.id } }
|
|
@@ -602,21 +779,21 @@ async function persistDatasourceRow(engine, record) {
|
|
|
602
779
|
}
|
|
603
780
|
}
|
|
604
781
|
async function deleteDatasourceRow(engine, name) {
|
|
605
|
-
if (!_optionalChain([engine, 'optionalAccess',
|
|
782
|
+
if (!_optionalChain([engine, 'optionalAccess', _122 => _122.findOne])) return;
|
|
606
783
|
const existing = await engine.findOne(SYS_METADATA, { where: { type: DS_META_TYPE, name, state: "active" } });
|
|
607
784
|
if (!existing) return;
|
|
608
785
|
if (engine.delete) await engine.delete(SYS_METADATA, { where: { id: existing.id } });
|
|
609
|
-
else await _optionalChain([engine, 'access',
|
|
786
|
+
else await _optionalChain([engine, 'access', _123 => _123.update, 'optionalCall', _124 => _124(SYS_METADATA, { state: "inactive" }, { where: { id: existing.id } })]);
|
|
610
787
|
}
|
|
611
788
|
async function loadDatasourceRows(engine) {
|
|
612
|
-
if (!_optionalChain([engine, 'optionalAccess',
|
|
789
|
+
if (!_optionalChain([engine, 'optionalAccess', _125 => _125.find])) return [];
|
|
613
790
|
const rows = await engine.find(SYS_METADATA, { where: { type: DS_META_TYPE, state: "active" } });
|
|
614
791
|
const out = [];
|
|
615
792
|
for (const r of _nullishCoalesce(rows, () => ( []))) {
|
|
616
793
|
const raw = r.metadata;
|
|
617
794
|
try {
|
|
618
795
|
out.push(typeof raw === "string" ? JSON.parse(raw) : raw);
|
|
619
|
-
} catch (
|
|
796
|
+
} catch (e3) {
|
|
620
797
|
}
|
|
621
798
|
}
|
|
622
799
|
return out;
|
|
@@ -647,19 +824,27 @@ var DatasourceAdminServicePlugin = class {
|
|
|
647
824
|
const metadataOf = () => safeGetService2(ctx, "metadata");
|
|
648
825
|
const engineOf = () => safeGetService2(ctx, "data");
|
|
649
826
|
const factory = () => _nullishCoalesce(this.options.driverFactory, () => ( safeGetService2(ctx, "datasource-driver-factory")));
|
|
827
|
+
this.connection = new DatasourceConnectionService({
|
|
828
|
+
factory,
|
|
829
|
+
engine: () => engineOf(),
|
|
830
|
+
secrets: { resolve: (ref) => _nullishCoalesce(_optionalChain([this, 'access', _126 => _126.options, 'access', _127 => _127.secrets, 'optionalAccess', _128 => _128.resolve, 'optionalCall', _129 => _129(ref)]), () => ( Promise.resolve(void 0))) },
|
|
831
|
+
policy: this.options.connectPolicy,
|
|
832
|
+
logger: this.options.logger
|
|
833
|
+
});
|
|
834
|
+
ctx.registerService("datasource-connection", this.connection);
|
|
650
835
|
const config = {
|
|
651
836
|
probe: (input) => this.probe(factory(), input),
|
|
652
837
|
listDatasourceRecords: async () => {
|
|
653
|
-
const rows = await _asyncNullishCoalesce(await _optionalChain([metadataOf, 'call',
|
|
838
|
+
const rows = await _asyncNullishCoalesce(await _optionalChain([metadataOf, 'call', _130 => _130(), 'optionalAccess', _131 => _131.list, 'call', _132 => _132("datasource")]), async () => ( []));
|
|
654
839
|
return rows.map((r) => ({ ...r, origin: _nullishCoalesce(r.origin, () => ( "code")) }));
|
|
655
840
|
},
|
|
656
841
|
getDatasourceRecord: async (name) => {
|
|
657
|
-
const row = await _optionalChain([metadataOf, 'call',
|
|
842
|
+
const row = await _optionalChain([metadataOf, 'call', _133 => _133(), 'optionalAccess', _134 => _134.get, 'call', _135 => _135("datasource", name)]);
|
|
658
843
|
return row ? { ...row, origin: _nullishCoalesce(row.origin, () => ( "code")) } : void 0;
|
|
659
844
|
},
|
|
660
845
|
putDatasourceRecord: async (record) => {
|
|
661
846
|
const metadata = metadataOf();
|
|
662
|
-
if (!_optionalChain([metadata, 'optionalAccess',
|
|
847
|
+
if (!_optionalChain([metadata, 'optionalAccess', _136 => _136.register])) {
|
|
663
848
|
throw new Error("Metadata service is unavailable; cannot persist datasource.");
|
|
664
849
|
}
|
|
665
850
|
await metadata.register("datasource", record.name, record);
|
|
@@ -667,7 +852,7 @@ var DatasourceAdminServicePlugin = class {
|
|
|
667
852
|
},
|
|
668
853
|
deleteDatasourceRecord: async (name) => {
|
|
669
854
|
const metadata = metadataOf();
|
|
670
|
-
if (!_optionalChain([metadata, 'optionalAccess',
|
|
855
|
+
if (!_optionalChain([metadata, 'optionalAccess', _137 => _137.unregister])) {
|
|
671
856
|
throw new Error("Metadata service is unavailable; cannot remove datasource.");
|
|
672
857
|
}
|
|
673
858
|
await metadata.unregister("datasource", name);
|
|
@@ -675,7 +860,7 @@ var DatasourceAdminServicePlugin = class {
|
|
|
675
860
|
},
|
|
676
861
|
writeSecret: async (input, hint) => {
|
|
677
862
|
const binder = this.options.secrets;
|
|
678
|
-
if (!_optionalChain([binder, 'optionalAccess',
|
|
863
|
+
if (!_optionalChain([binder, 'optionalAccess', _138 => _138.bind])) {
|
|
679
864
|
throw new Error(
|
|
680
865
|
"No secret store configured: refusing to persist a datasource credential in cleartext. Wire a SecretBinder (CryptoProvider + sys_secret) into DatasourceAdminServicePlugin."
|
|
681
866
|
);
|
|
@@ -683,36 +868,27 @@ var DatasourceAdminServicePlugin = class {
|
|
|
683
868
|
return binder.bind(input, hint);
|
|
684
869
|
},
|
|
685
870
|
removeSecret: async (ref) => {
|
|
686
|
-
await _optionalChain([this, 'access',
|
|
871
|
+
await _optionalChain([this, 'access', _139 => _139.options, 'access', _140 => _140.secrets, 'optionalAccess', _141 => _141.unbind, 'optionalCall', _142 => _142(ref)]);
|
|
687
872
|
},
|
|
688
873
|
countBoundObjects: async (datasource) => {
|
|
689
874
|
const metadata = metadataOf();
|
|
690
|
-
const objects = await _asyncNullishCoalesce(await _asyncNullishCoalesce(await _optionalChain([metadata, 'optionalAccess',
|
|
691
|
-
return objects.filter((o) => _optionalChain([o, 'optionalAccess',
|
|
875
|
+
const objects = await _asyncNullishCoalesce(await _asyncNullishCoalesce(await _optionalChain([metadata, 'optionalAccess', _143 => _143.listObjects, 'optionalCall', _144 => _144()]), async () => ( await _optionalChain([metadata, 'optionalAccess', _145 => _145.list, 'call', _146 => _146("object")]))), async () => ( []));
|
|
876
|
+
return objects.filter((o) => _optionalChain([o, 'optionalAccess', _147 => _147.datasource]) === datasource).length;
|
|
692
877
|
},
|
|
878
|
+
// Hot pool (de)registration converges on the shared
|
|
879
|
+
// DatasourceConnectionService (ADR-0062 D1) — one connect path for code-
|
|
880
|
+
// and runtime-origin datasources. `connect()` builds the driver via the
|
|
881
|
+
// factory, dereferences `external.credentialsRef` through the SecretBinder,
|
|
882
|
+
// opens the connection, and registers the live driver + datasource def.
|
|
883
|
+
// Runtime-admin connects always degrade-with-warning on failure (never
|
|
884
|
+
// fail-fast), preserving the pre-ADR-0062 admin behavior.
|
|
693
885
|
registerPool: async (record) => {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
if (!f || !_optionalChain([engine, 'optionalAccess', _96 => _96.registerDriver]) || !f.supports(record.driver)) return;
|
|
697
|
-
const credentialsRef = _optionalChain([record, 'access', _97 => _97.external, 'optionalAccess', _98 => _98.credentialsRef]);
|
|
698
|
-
const secret = credentialsRef ? await _optionalChain([this, 'access', _99 => _99.options, 'access', _100 => _100.secrets, 'optionalAccess', _101 => _101.resolve, 'optionalCall', _102 => _102(credentialsRef)]) : void 0;
|
|
699
|
-
const handle = await f.create({ ...this.toSpec(record), ...secret ? { secret } : {} });
|
|
700
|
-
if (typeof _optionalChain([handle, 'optionalAccess', _103 => _103.connect]) === "function") await handle.connect();
|
|
701
|
-
const engineDriver = _nullishCoalesce(handle.driver, () => ( handle));
|
|
702
|
-
try {
|
|
703
|
-
engineDriver.name = record.name;
|
|
704
|
-
} catch (e3) {
|
|
705
|
-
}
|
|
706
|
-
engine.registerDriver(engineDriver);
|
|
707
|
-
_optionalChain([engine, 'access', _104 => _104.registerDatasourceDef, 'optionalCall', _105 => _105({
|
|
708
|
-
name: record.name,
|
|
709
|
-
schemaMode: record.schemaMode,
|
|
710
|
-
external: record.external
|
|
886
|
+
await _optionalChain([this, 'access', _148 => _148.connection, 'optionalAccess', _149 => _149.connect, 'call', _150 => _150(record, {
|
|
887
|
+
context: { origin: _nullishCoalesce(record.origin, () => ( "runtime")), trigger: "runtime-admin" }
|
|
711
888
|
})]);
|
|
712
889
|
},
|
|
713
890
|
unregisterPool: async (name) => {
|
|
714
|
-
|
|
715
|
-
if (typeof _optionalChain([driver, 'optionalAccess', _109 => _109.disconnect]) === "function") await driver.disconnect();
|
|
891
|
+
await _optionalChain([this, 'access', _151 => _151.connection, 'optionalAccess', _152 => _152.disconnect, 'call', _153 => _153(name)]);
|
|
716
892
|
},
|
|
717
893
|
logger
|
|
718
894
|
};
|
|
@@ -750,7 +926,7 @@ var DatasourceAdminServicePlugin = class {
|
|
|
750
926
|
});
|
|
751
927
|
}
|
|
752
928
|
} catch (err) {
|
|
753
|
-
_optionalChain([this, 'access',
|
|
929
|
+
_optionalChain([this, 'access', _154 => _154.options, 'access', _155 => _155.logger, 'optionalAccess', _156 => _156.warn, 'optionalCall', _157 => _157("datasource nav contribution skipped", err)]);
|
|
754
930
|
}
|
|
755
931
|
}
|
|
756
932
|
async start(ctx) {
|
|
@@ -762,12 +938,12 @@ var DatasourceAdminServicePlugin = class {
|
|
|
762
938
|
async restoreRuntimeDatasources(ctx) {
|
|
763
939
|
const engine = safeGetService2(ctx, "data");
|
|
764
940
|
const metadata = safeGetService2(ctx, "metadata");
|
|
765
|
-
if (!_optionalChain([engine, 'optionalAccess',
|
|
941
|
+
if (!_optionalChain([engine, 'optionalAccess', _158 => _158.find]) || !_optionalChain([metadata, 'optionalAccess', _159 => _159.register])) return;
|
|
766
942
|
let rows;
|
|
767
943
|
try {
|
|
768
944
|
rows = await loadDatasourceRows(engine);
|
|
769
945
|
} catch (err) {
|
|
770
|
-
_optionalChain([this, 'access',
|
|
946
|
+
_optionalChain([this, 'access', _160 => _160.options, 'access', _161 => _161.logger, 'optionalAccess', _162 => _162.warn, 'optionalCall', _163 => _163("datasource restore: reading sys_metadata failed", err)]);
|
|
771
947
|
return;
|
|
772
948
|
}
|
|
773
949
|
let restored = 0;
|
|
@@ -778,10 +954,10 @@ var DatasourceAdminServicePlugin = class {
|
|
|
778
954
|
await metadata.register("datasource", name, rec);
|
|
779
955
|
restored += 1;
|
|
780
956
|
} catch (err) {
|
|
781
|
-
_optionalChain([this, 'access',
|
|
957
|
+
_optionalChain([this, 'access', _164 => _164.options, 'access', _165 => _165.logger, 'optionalAccess', _166 => _166.warn, 'optionalCall', _167 => _167(`datasource restore: register '${name}' failed`, err)]);
|
|
782
958
|
}
|
|
783
959
|
}
|
|
784
|
-
if (restored > 0) _optionalChain([this, 'access',
|
|
960
|
+
if (restored > 0) _optionalChain([this, 'access', _168 => _168.options, 'access', _169 => _169.logger, 'optionalAccess', _170 => _170.info, 'optionalCall', _171 => _171(`datasource: restored ${restored} runtime record(s) from sys_metadata`)]);
|
|
785
961
|
}
|
|
786
962
|
/**
|
|
787
963
|
* Boot-time rehydration: list persisted runtime datasources and re-register
|
|
@@ -794,12 +970,12 @@ var DatasourceAdminServicePlugin = class {
|
|
|
794
970
|
*/
|
|
795
971
|
async rehydratePools() {
|
|
796
972
|
const cfg = this.config;
|
|
797
|
-
if (!_optionalChain([cfg, 'optionalAccess',
|
|
973
|
+
if (!_optionalChain([cfg, 'optionalAccess', _172 => _172.registerPool]) || !cfg.listDatasourceRecords) return;
|
|
798
974
|
let records;
|
|
799
975
|
try {
|
|
800
976
|
records = await cfg.listDatasourceRecords();
|
|
801
977
|
} catch (err) {
|
|
802
|
-
_optionalChain([this, 'access',
|
|
978
|
+
_optionalChain([this, 'access', _173 => _173.options, 'access', _174 => _174.logger, 'optionalAccess', _175 => _175.warn, 'optionalCall', _176 => _176("datasource rehydrate: listing records failed", err)]);
|
|
803
979
|
return;
|
|
804
980
|
}
|
|
805
981
|
const runtime = records.filter((r) => r.origin === "runtime" && (_nullishCoalesce(r.active, () => ( true))));
|
|
@@ -810,10 +986,10 @@ var DatasourceAdminServicePlugin = class {
|
|
|
810
986
|
await cfg.registerPool(record);
|
|
811
987
|
registered++;
|
|
812
988
|
} catch (err) {
|
|
813
|
-
_optionalChain([this, 'access',
|
|
989
|
+
_optionalChain([this, 'access', _177 => _177.options, 'access', _178 => _178.logger, 'optionalAccess', _179 => _179.warn, 'optionalCall', _180 => _180(`datasource rehydrate: pool '${record.name}' failed`, err)]);
|
|
814
990
|
}
|
|
815
991
|
}
|
|
816
|
-
_optionalChain([this, 'access',
|
|
992
|
+
_optionalChain([this, 'access', _181 => _181.options, 'access', _182 => _182.logger, 'optionalAccess', _183 => _183.info, 'optionalCall', _184 => _184(
|
|
817
993
|
`Rehydrated ${registered}/${runtime.length} runtime datasource pool(s) on boot`
|
|
818
994
|
)]);
|
|
819
995
|
}
|
|
@@ -821,15 +997,6 @@ var DatasourceAdminServicePlugin = class {
|
|
|
821
997
|
this.service = void 0;
|
|
822
998
|
}
|
|
823
999
|
// --- internals -----------------------------------------------------------
|
|
824
|
-
toSpec(record) {
|
|
825
|
-
return {
|
|
826
|
-
name: record.name,
|
|
827
|
-
driver: record.driver,
|
|
828
|
-
config: _nullishCoalesce(record.config, () => ( {})),
|
|
829
|
-
external: record.external,
|
|
830
|
-
pool: record.pool
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
1000
|
/** Probe a connection via the driver factory: build → connect → ping → close. */
|
|
834
1001
|
async probe(factory, input) {
|
|
835
1002
|
if (!factory) {
|
|
@@ -847,26 +1014,26 @@ var DatasourceAdminServicePlugin = class {
|
|
|
847
1014
|
external: input.external
|
|
848
1015
|
});
|
|
849
1016
|
} catch (err) {
|
|
850
|
-
return { ok: false, error: `Failed to build driver: ${
|
|
1017
|
+
return { ok: false, error: `Failed to build driver: ${errMsg2(err)}` };
|
|
851
1018
|
}
|
|
852
1019
|
const startedAt = monotonicNow();
|
|
853
1020
|
try {
|
|
854
|
-
if (typeof _optionalChain([driver, 'optionalAccess',
|
|
855
|
-
if (typeof _optionalChain([driver, 'optionalAccess',
|
|
856
|
-
else if (typeof _optionalChain([driver, 'optionalAccess',
|
|
857
|
-
else if (typeof _optionalChain([driver, 'optionalAccess',
|
|
1021
|
+
if (typeof _optionalChain([driver, 'optionalAccess', _185 => _185.connect]) === "function") await driver.connect();
|
|
1022
|
+
if (typeof _optionalChain([driver, 'optionalAccess', _186 => _186.ping]) === "function") await driver.ping();
|
|
1023
|
+
else if (typeof _optionalChain([driver, 'optionalAccess', _187 => _187.checkHealth]) === "function") await driver.checkHealth();
|
|
1024
|
+
else if (typeof _optionalChain([driver, 'optionalAccess', _188 => _188.introspectSchema]) === "function") await driver.introspectSchema();
|
|
858
1025
|
const latencyMs = elapsedSince(startedAt);
|
|
859
1026
|
let serverVersion;
|
|
860
1027
|
try {
|
|
861
|
-
serverVersion = typeof _optionalChain([driver, 'optionalAccess',
|
|
1028
|
+
serverVersion = typeof _optionalChain([driver, 'optionalAccess', _189 => _189.serverVersion]) === "function" ? await driver.serverVersion() : void 0;
|
|
862
1029
|
} catch (e4) {
|
|
863
1030
|
}
|
|
864
1031
|
return { ok: true, latencyMs, ...serverVersion ? { serverVersion } : {} };
|
|
865
1032
|
} catch (err) {
|
|
866
|
-
return { ok: false, error:
|
|
1033
|
+
return { ok: false, error: errMsg2(err) };
|
|
867
1034
|
} finally {
|
|
868
1035
|
try {
|
|
869
|
-
if (typeof _optionalChain([driver, 'optionalAccess',
|
|
1036
|
+
if (typeof _optionalChain([driver, 'optionalAccess', _190 => _190.disconnect]) === "function") await driver.disconnect();
|
|
870
1037
|
} catch (e5) {
|
|
871
1038
|
}
|
|
872
1039
|
}
|
|
@@ -879,12 +1046,12 @@ function safeGetService2(ctx, name) {
|
|
|
879
1046
|
return void 0;
|
|
880
1047
|
}
|
|
881
1048
|
}
|
|
882
|
-
function
|
|
1049
|
+
function errMsg2(err) {
|
|
883
1050
|
return err instanceof Error ? err.message : String(err);
|
|
884
1051
|
}
|
|
885
1052
|
function monotonicNow() {
|
|
886
1053
|
const perf = globalThis.performance;
|
|
887
|
-
return typeof _optionalChain([perf, 'optionalAccess',
|
|
1054
|
+
return typeof _optionalChain([perf, 'optionalAccess', _191 => _191.now]) === "function" ? perf.now() : 0;
|
|
888
1055
|
}
|
|
889
1056
|
function elapsedSince(startedAt) {
|
|
890
1057
|
return Math.max(0, Math.round(monotonicNow() - startedAt));
|
|
@@ -909,10 +1076,10 @@ function resolveKind(driverId) {
|
|
|
909
1076
|
}
|
|
910
1077
|
function toHandle(driver, serverVersion) {
|
|
911
1078
|
return {
|
|
912
|
-
connect: typeof _optionalChain([driver, 'optionalAccess',
|
|
913
|
-
disconnect: typeof _optionalChain([driver, 'optionalAccess',
|
|
914
|
-
checkHealth: typeof _optionalChain([driver, 'optionalAccess',
|
|
915
|
-
ping: typeof _optionalChain([driver, 'optionalAccess',
|
|
1079
|
+
connect: typeof _optionalChain([driver, 'optionalAccess', _192 => _192.connect]) === "function" ? () => driver.connect() : void 0,
|
|
1080
|
+
disconnect: typeof _optionalChain([driver, 'optionalAccess', _193 => _193.disconnect]) === "function" ? () => driver.disconnect() : void 0,
|
|
1081
|
+
checkHealth: typeof _optionalChain([driver, 'optionalAccess', _194 => _194.checkHealth]) === "function" ? () => driver.checkHealth() : void 0,
|
|
1082
|
+
ping: typeof _optionalChain([driver, 'optionalAccess', _195 => _195.checkHealth]) === "function" ? () => driver.checkHealth() : void 0,
|
|
916
1083
|
...serverVersion ? { serverVersion } : {},
|
|
917
1084
|
driver
|
|
918
1085
|
};
|
|
@@ -957,7 +1124,7 @@ function createDefaultDatasourceDriverFactory() {
|
|
|
957
1124
|
if (!kind) {
|
|
958
1125
|
throw new Error(`Unsupported driver id '${spec.driver}'.`);
|
|
959
1126
|
}
|
|
960
|
-
const schemaMode = _nullishCoalesce(_optionalChain([spec, 'access',
|
|
1127
|
+
const schemaMode = _nullishCoalesce(_optionalChain([spec, 'access', _196 => _196.external, 'optionalAccess', _197 => _197.schemaMode]), () => ( _optionalChain([spec, 'access', _198 => _198.config, 'optionalAccess', _199 => _199.schemaMode])));
|
|
961
1128
|
if (kind === "postgres") {
|
|
962
1129
|
const { SqlDriver } = await Promise.resolve().then(() => _interopRequireWildcard(require("@objectstack/driver-sql")));
|
|
963
1130
|
const driver = new SqlDriver({
|
|
@@ -984,7 +1151,7 @@ function createDefaultDatasourceDriverFactory() {
|
|
|
984
1151
|
({ MongoDBDriver } = await Promise.resolve().then(() => _interopRequireWildcard(require("@objectstack/driver-mongodb"))));
|
|
985
1152
|
} catch (err) {
|
|
986
1153
|
throw new Error(
|
|
987
|
-
`mongodb driver requested but @objectstack/driver-mongodb is not installed (${_nullishCoalesce(_optionalChain([err, 'optionalAccess',
|
|
1154
|
+
`mongodb driver requested but @objectstack/driver-mongodb is not installed (${_nullishCoalesce(_optionalChain([err, 'optionalAccess', _200 => _200.message]), () => ( err))}).`
|
|
988
1155
|
);
|
|
989
1156
|
}
|
|
990
1157
|
const driver = new MongoDBDriver({ url: buildMongoUrl(spec) });
|
|
@@ -996,12 +1163,12 @@ function createDefaultDatasourceDriverFactory() {
|
|
|
996
1163
|
};
|
|
997
1164
|
}
|
|
998
1165
|
async function sqlServerVersion(driver, client) {
|
|
999
|
-
if (typeof _optionalChain([driver, 'optionalAccess',
|
|
1166
|
+
if (typeof _optionalChain([driver, 'optionalAccess', _201 => _201.execute]) !== "function") return void 0;
|
|
1000
1167
|
try {
|
|
1001
1168
|
const sql = client === "pg" ? "SELECT version() AS v" : "SELECT sqlite_version() AS v";
|
|
1002
1169
|
const rows = await driver.execute(sql);
|
|
1003
|
-
const first = Array.isArray(rows) ? rows[0] : Array.isArray(_optionalChain([rows, 'optionalAccess',
|
|
1004
|
-
const v = _nullishCoalesce(_nullishCoalesce(_optionalChain([first, 'optionalAccess',
|
|
1170
|
+
const first = Array.isArray(rows) ? rows[0] : Array.isArray(_optionalChain([rows, 'optionalAccess', _202 => _202.rows])) ? rows.rows[0] : rows;
|
|
1171
|
+
const v = _nullishCoalesce(_nullishCoalesce(_optionalChain([first, 'optionalAccess', _203 => _203.v]), () => ( _optionalChain([first, 'optionalAccess', _204 => _204.version]))), () => ( _optionalChain([first, 'optionalAccess', _205 => _205["sqlite_version()"]])));
|
|
1005
1172
|
return typeof v === "string" ? v : void 0;
|
|
1006
1173
|
} catch (e7) {
|
|
1007
1174
|
return void 0;
|
|
@@ -1014,7 +1181,7 @@ function toCredentialsRef(handleId) {
|
|
|
1014
1181
|
return `${REF_PREFIX}${handleId}`;
|
|
1015
1182
|
}
|
|
1016
1183
|
function parseCredentialsRef(ref) {
|
|
1017
|
-
return _optionalChain([ref, 'optionalAccess',
|
|
1184
|
+
return _optionalChain([ref, 'optionalAccess', _206 => _206.startsWith, 'call', _207 => _207(REF_PREFIX)]) ? ref.slice(REF_PREFIX.length) : void 0;
|
|
1018
1185
|
}
|
|
1019
1186
|
function createDatasourceSecretBinder(deps) {
|
|
1020
1187
|
const { engine, cryptoProvider } = deps;
|
|
@@ -1051,9 +1218,9 @@ function createDatasourceSecretBinder(deps) {
|
|
|
1051
1218
|
// skip the tenant-audit warning (mirrors SettingsService's store).
|
|
1052
1219
|
bypassTenantAudit: true
|
|
1053
1220
|
});
|
|
1054
|
-
const rows = _nullishCoalesce((Array.isArray(result) ? result : _optionalChain([result, 'optionalAccess',
|
|
1221
|
+
const rows = _nullishCoalesce((Array.isArray(result) ? result : _optionalChain([result, 'optionalAccess', _208 => _208.data])), () => ( []));
|
|
1055
1222
|
const row = rows[0];
|
|
1056
|
-
if (!_optionalChain([row, 'optionalAccess',
|
|
1223
|
+
if (!_optionalChain([row, 'optionalAccess', _209 => _209.ciphertext])) return void 0;
|
|
1057
1224
|
return await cryptoProvider.decrypt(
|
|
1058
1225
|
{
|
|
1059
1226
|
id: row.id,
|
|
@@ -1183,7 +1350,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1183
1350
|
};
|
|
1184
1351
|
server.get(root, async (_req, res) => {
|
|
1185
1352
|
const svc = adminService();
|
|
1186
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1353
|
+
if (!_optionalChain([svc, 'optionalAccess', _210 => _210.listDatasources])) return unavailable(res);
|
|
1187
1354
|
const datasources = await svc.listDatasources();
|
|
1188
1355
|
res.json({ datasources });
|
|
1189
1356
|
});
|
|
@@ -1192,7 +1359,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1192
1359
|
});
|
|
1193
1360
|
server.get(`${root}/:name/remote-tables`, async (req, res) => {
|
|
1194
1361
|
const svc = externalService();
|
|
1195
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1362
|
+
if (!_optionalChain([svc, 'optionalAccess', _211 => _211.listRemoteTables])) return unavailable(res);
|
|
1196
1363
|
try {
|
|
1197
1364
|
const tables = await svc.listRemoteTables(req.params.name);
|
|
1198
1365
|
res.json({ tables });
|
|
@@ -1202,7 +1369,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1202
1369
|
});
|
|
1203
1370
|
server.get(`${root}/:name`, async (req, res) => {
|
|
1204
1371
|
const svc = adminService();
|
|
1205
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1372
|
+
if (!_optionalChain([svc, 'optionalAccess', _212 => _212.getDatasource])) return unavailable(res);
|
|
1206
1373
|
try {
|
|
1207
1374
|
const datasource = await svc.getDatasource(req.params.name);
|
|
1208
1375
|
if (!datasource) return res.status(404).json({ error: "not_found" });
|
|
@@ -1213,7 +1380,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1213
1380
|
});
|
|
1214
1381
|
server.post(`${root}/:name/test`, async (req, res) => {
|
|
1215
1382
|
const svc = externalService();
|
|
1216
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1383
|
+
if (!_optionalChain([svc, 'optionalAccess', _213 => _213.testConnection])) return unavailable(res);
|
|
1217
1384
|
try {
|
|
1218
1385
|
const result = await svc.testConnection(req.params.name);
|
|
1219
1386
|
res.json(result);
|
|
@@ -1223,7 +1390,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1223
1390
|
});
|
|
1224
1391
|
server.post(`${root}/:name/object-draft`, async (req, res) => {
|
|
1225
1392
|
const svc = externalService();
|
|
1226
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1393
|
+
if (!_optionalChain([svc, 'optionalAccess', _214 => _214.generateObjectDraft])) return unavailable(res);
|
|
1227
1394
|
const { table, ...opts } = _nullishCoalesce(req.body, () => ( {}));
|
|
1228
1395
|
if (!table) return badRequest(res, new Error('Body field "table" is required.'));
|
|
1229
1396
|
try {
|
|
@@ -1235,7 +1402,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1235
1402
|
});
|
|
1236
1403
|
server.post(`${root}/test`, async (req, res) => {
|
|
1237
1404
|
const svc = adminService();
|
|
1238
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1405
|
+
if (!_optionalChain([svc, 'optionalAccess', _215 => _215.testConnection])) return unavailable(res);
|
|
1239
1406
|
const { draft, secret } = splitSecret(req.body);
|
|
1240
1407
|
try {
|
|
1241
1408
|
const result = await svc.testConnection(draft, secret);
|
|
@@ -1246,7 +1413,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1246
1413
|
});
|
|
1247
1414
|
server.post(root, async (req, res) => {
|
|
1248
1415
|
const svc = adminService();
|
|
1249
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1416
|
+
if (!_optionalChain([svc, 'optionalAccess', _216 => _216.createDatasource])) return unavailable(res);
|
|
1250
1417
|
const { draft, secret } = splitSecret(req.body);
|
|
1251
1418
|
try {
|
|
1252
1419
|
const datasource = await svc.createDatasource(draft, secret);
|
|
@@ -1257,7 +1424,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1257
1424
|
});
|
|
1258
1425
|
server.patch(`${root}/:name`, async (req, res) => {
|
|
1259
1426
|
const svc = adminService();
|
|
1260
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1427
|
+
if (!_optionalChain([svc, 'optionalAccess', _217 => _217.updateDatasource])) return unavailable(res);
|
|
1261
1428
|
const { draft, secret } = splitSecret(req.body);
|
|
1262
1429
|
try {
|
|
1263
1430
|
const datasource = await svc.updateDatasource(req.params.name, draft, secret);
|
|
@@ -1268,7 +1435,7 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1268
1435
|
});
|
|
1269
1436
|
server.delete(`${root}/:name`, async (req, res) => {
|
|
1270
1437
|
const svc = adminService();
|
|
1271
|
-
if (!_optionalChain([svc, 'optionalAccess',
|
|
1438
|
+
if (!_optionalChain([svc, 'optionalAccess', _218 => _218.removeDatasource])) return unavailable(res);
|
|
1272
1439
|
try {
|
|
1273
1440
|
await svc.removeDatasource(req.params.name);
|
|
1274
1441
|
res.status(204).end();
|
|
@@ -1287,5 +1454,8 @@ function registerDatasourceAdminRoutes(server, ctx, basePath = "/api/v1") {
|
|
|
1287
1454
|
|
|
1288
1455
|
|
|
1289
1456
|
|
|
1290
|
-
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
|
|
1460
|
+
exports.DatasourceAdminService = DatasourceAdminService; exports.DatasourceAdminServicePlugin = DatasourceAdminServicePlugin; exports.DatasourceConnectionService = DatasourceConnectionService; exports.ExternalDatasourceService = ExternalDatasourceService; exports.ExternalDatasourceServicePlugin = ExternalDatasourceServicePlugin; exports.allowAllConnectPolicy = _chunkBI2SYWLCcjs.allowAllConnectPolicy; exports.createDatasourceSecretBinder = createDatasourceSecretBinder; exports.createDefaultDatasourceDriverFactory = createDefaultDatasourceDriverFactory; exports.isDatasourceAddressed = isDatasourceAddressed; exports.parseCredentialsRef = parseCredentialsRef; exports.registerDatasourceAdminRoutes = registerDatasourceAdminRoutes; exports.toCredentialsRef = toCredentialsRef;
|
|
1291
1461
|
//# sourceMappingURL=index.cjs.map
|