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