@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/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; }// src/external-datasource-service.ts
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', _38 => _38.code, 'optionalAccess', _39 => _39.definedIn]) ? { definedIn: slot.code.definedIn } : {},
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', _40 => _40.external, 'optionalAccess', _41 => _41.credentialsRef]));
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', _42 => _42.driver])) {
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', _43 => _43.external, 'optionalAccess', _44 => _44.queryTimeoutMs]);
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', _45 => _45.value]),
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', _46 => _46.name]));
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', _47 => _47.external, 'optionalAccess', _48 => _48.credentialsRef]) };
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', _49 => _49.external, 'optionalAccess', _50 => _50.credentialsRef]);
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', _51 => _51.external, 'optionalAccess', _52 => _52.credentialsRef])) await this.tryRemoveSecret(existing.external.credentialsRef);
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', _53 => _53.config, 'access', _54 => _54.registerPool, 'optionalCall', _55 => _55(record)]);
727
+ await _optionalChain([this, 'access', _101 => _101.config, 'access', _102 => _102.registerPool, 'optionalCall', _103 => _103(record)]);
551
728
  } catch (err) {
552
- _optionalChain([this, 'access', _56 => _56.logger, 'optionalAccess', _57 => _57.warn, 'call', _58 => _58(`registerPool('${record.name}') failed`, err)]);
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', _59 => _59.config, 'access', _60 => _60.unregisterPool, 'optionalCall', _61 => _61(name)]);
734
+ await _optionalChain([this, 'access', _107 => _107.config, 'access', _108 => _108.unregisterPool, 'optionalCall', _109 => _109(name)]);
558
735
  } catch (err) {
559
- _optionalChain([this, 'access', _62 => _62.logger, 'optionalAccess', _63 => _63.warn, 'call', _64 => _64(`unregisterPool('${name}') failed`, err)]);
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', _65 => _65.config, 'access', _66 => _66.removeSecret, 'optionalCall', _67 => _67(credentialsRef)]);
741
+ await _optionalChain([this, 'access', _113 => _113.config, 'access', _114 => _114.removeSecret, 'optionalCall', _115 => _115(credentialsRef)]);
565
742
  } catch (err) {
566
- _optionalChain([this, 'access', _68 => _68.logger, 'optionalAccess', _69 => _69.warn, 'call', _70 => _70(`removeSecret('${credentialsRef}') failed`, err)]);
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', _71 => _71.insert]) || !engine.findOne) return;
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', _72 => _72.update, 'optionalCall', _73 => _73(
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', _74 => _74.findOne])) return;
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', _75 => _75.update, 'optionalCall', _76 => _76(SYS_METADATA, { state: "inactive" }, { where: { id: existing.id } })]);
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', _77 => _77.find])) return [];
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 (e2) {
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', _78 => _78(), 'optionalAccess', _79 => _79.list, 'call', _80 => _80("datasource")]), async () => ( []));
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', _81 => _81(), 'optionalAccess', _82 => _82.get, 'call', _83 => _83("datasource", name)]);
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', _84 => _84.register])) {
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', _85 => _85.unregister])) {
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', _86 => _86.bind])) {
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', _87 => _87.options, 'access', _88 => _88.secrets, 'optionalAccess', _89 => _89.unbind, 'optionalCall', _90 => _90(ref)]);
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', _91 => _91.listObjects, 'optionalCall', _92 => _92()]), async () => ( await _optionalChain([metadata, 'optionalAccess', _93 => _93.list, 'call', _94 => _94("object")]))), async () => ( []));
691
- return objects.filter((o) => _optionalChain([o, 'optionalAccess', _95 => _95.datasource]) === datasource).length;
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
- const f = factory();
695
- const engine = engineOf();
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
- const driver = _optionalChain([engineOf, 'call', _106 => _106(), 'optionalAccess', _107 => _107.getDriverByName, 'optionalCall', _108 => _108(name)]);
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', _110 => _110.options, 'access', _111 => _111.logger, 'optionalAccess', _112 => _112.warn, 'optionalCall', _113 => _113("datasource nav contribution skipped", err)]);
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', _114 => _114.find]) || !_optionalChain([metadata, 'optionalAccess', _115 => _115.register])) return;
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', _116 => _116.options, 'access', _117 => _117.logger, 'optionalAccess', _118 => _118.warn, 'optionalCall', _119 => _119("datasource restore: reading sys_metadata failed", err)]);
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', _120 => _120.options, 'access', _121 => _121.logger, 'optionalAccess', _122 => _122.warn, 'optionalCall', _123 => _123(`datasource restore: register '${name}' failed`, err)]);
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', _124 => _124.options, 'access', _125 => _125.logger, 'optionalAccess', _126 => _126.info, 'optionalCall', _127 => _127(`datasource: restored ${restored} runtime record(s) from sys_metadata`)]);
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', _128 => _128.registerPool]) || !cfg.listDatasourceRecords) return;
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', _129 => _129.options, 'access', _130 => _130.logger, 'optionalAccess', _131 => _131.warn, 'optionalCall', _132 => _132("datasource rehydrate: listing records failed", err)]);
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', _133 => _133.options, 'access', _134 => _134.logger, 'optionalAccess', _135 => _135.warn, 'optionalCall', _136 => _136(`datasource rehydrate: pool '${record.name}' failed`, err)]);
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', _137 => _137.options, 'access', _138 => _138.logger, 'optionalAccess', _139 => _139.info, 'optionalCall', _140 => _140(
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: ${errMsg(err)}` };
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', _141 => _141.connect]) === "function") await driver.connect();
855
- if (typeof _optionalChain([driver, 'optionalAccess', _142 => _142.ping]) === "function") await driver.ping();
856
- else if (typeof _optionalChain([driver, 'optionalAccess', _143 => _143.checkHealth]) === "function") await driver.checkHealth();
857
- else if (typeof _optionalChain([driver, 'optionalAccess', _144 => _144.introspectSchema]) === "function") await driver.introspectSchema();
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', _145 => _145.serverVersion]) === "function" ? await driver.serverVersion() : void 0;
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: errMsg(err) };
1033
+ return { ok: false, error: errMsg2(err) };
867
1034
  } finally {
868
1035
  try {
869
- if (typeof _optionalChain([driver, 'optionalAccess', _146 => _146.disconnect]) === "function") await driver.disconnect();
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 errMsg(err) {
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', _147 => _147.now]) === "function" ? perf.now() : 0;
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', _148 => _148.connect]) === "function" ? () => driver.connect() : void 0,
913
- disconnect: typeof _optionalChain([driver, 'optionalAccess', _149 => _149.disconnect]) === "function" ? () => driver.disconnect() : void 0,
914
- checkHealth: typeof _optionalChain([driver, 'optionalAccess', _150 => _150.checkHealth]) === "function" ? () => driver.checkHealth() : void 0,
915
- ping: typeof _optionalChain([driver, 'optionalAccess', _151 => _151.checkHealth]) === "function" ? () => driver.checkHealth() : void 0,
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', _152 => _152.external, 'optionalAccess', _153 => _153.schemaMode]), () => ( _optionalChain([spec, 'access', _154 => _154.config, 'optionalAccess', _155 => _155.schemaMode])));
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', _156 => _156.message]), () => ( err))}).`
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', _157 => _157.execute]) !== "function") return void 0;
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', _158 => _158.rows])) ? rows.rows[0] : rows;
1004
- const v = _nullishCoalesce(_nullishCoalesce(_optionalChain([first, 'optionalAccess', _159 => _159.v]), () => ( _optionalChain([first, 'optionalAccess', _160 => _160.version]))), () => ( _optionalChain([first, 'optionalAccess', _161 => _161["sqlite_version()"]])));
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', _162 => _162.startsWith, 'call', _163 => _163(REF_PREFIX)]) ? ref.slice(REF_PREFIX.length) : void 0;
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', _164 => _164.data])), () => ( []));
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', _165 => _165.ciphertext])) return void 0;
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', _166 => _166.listDatasources])) return unavailable(res);
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', _167 => _167.listRemoteTables])) return unavailable(res);
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', _168 => _168.getDatasource])) return unavailable(res);
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', _169 => _169.testConnection])) return unavailable(res);
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', _170 => _170.generateObjectDraft])) return unavailable(res);
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', _171 => _171.testConnection])) return unavailable(res);
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', _172 => _172.createDatasource])) return unavailable(res);
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', _173 => _173.updateDatasource])) return unavailable(res);
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', _174 => _174.removeDatasource])) return unavailable(res);
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
- exports.DatasourceAdminService = DatasourceAdminService; exports.DatasourceAdminServicePlugin = DatasourceAdminServicePlugin; exports.ExternalDatasourceService = ExternalDatasourceService; exports.ExternalDatasourceServicePlugin = ExternalDatasourceServicePlugin; exports.createDatasourceSecretBinder = createDatasourceSecretBinder; exports.createDefaultDatasourceDriverFactory = createDefaultDatasourceDriverFactory; exports.parseCredentialsRef = parseCredentialsRef; exports.registerDatasourceAdminRoutes = registerDatasourceAdminRoutes; exports.toCredentialsRef = toCredentialsRef;
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