kanban-lite 1.2.2 → 1.2.4

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 (39) hide show
  1. package/dist/cli.js +257 -90
  2. package/dist/extension.js +245 -78
  3. package/dist/mcp-server.js +117 -33
  4. package/dist/sdk/index.cjs +117 -32
  5. package/dist/sdk/index.mjs +117 -32
  6. package/dist/sdk/sdk/KanbanSDK.d.ts +27 -10
  7. package/dist/sdk/sdk/modules/cards.d.ts +11 -2
  8. package/dist/sdk/sdk/plugins/index.d.ts +7 -0
  9. package/dist/sdk/sdk/types.d.ts +12 -27
  10. package/dist/sdk/shared/config.d.ts +17 -1
  11. package/dist/standalone-webview/index.js +38 -38
  12. package/dist/standalone-webview/index.js.map +1 -1
  13. package/dist/standalone.js +307 -125
  14. package/package.json +1 -1
  15. package/src/cli/index.test.ts +157 -0
  16. package/src/cli/index.ts +1 -1
  17. package/src/mcp-server/index.test.ts +76 -0
  18. package/src/mcp-server/index.ts +1 -1
  19. package/src/sdk/KanbanSDK.d.ts +26 -10
  20. package/src/sdk/KanbanSDK.ts +37 -11
  21. package/src/sdk/__tests__/KanbanSDK.test.ts +79 -24
  22. package/src/sdk/integrationCatalog.ts +1 -0
  23. package/src/sdk/modules/cards.ts +13 -24
  24. package/src/sdk/plugins/index.d.ts +7 -0
  25. package/src/sdk/plugins/index.ts +17 -2
  26. package/src/sdk/types.d.ts +10 -26
  27. package/src/sdk/types.ts +11 -24
  28. package/src/sdk/webhooks.ts +19 -2
  29. package/src/shared/config.ts +130 -2
  30. package/src/standalone/__tests__/server.integration.test.ts +81 -2
  31. package/src/standalone/internal/runtime.ts +11 -6
  32. package/src/standalone/internal/websocket.ts +13 -3
  33. package/src/standalone/server.ts +67 -9
  34. package/src/standalone/watcherSetup.ts +9 -0
  35. package/src/webview/standalone-shim.ts +2 -1
  36. package/tmp/screenshots-workspace/.kanban/.active-card.json +5 -0
  37. package/tmp/screenshots-workspace/.kanban/boards/default/deleted/1-dddd.md +17 -0
  38. package/tmp/screenshots-workspace/.kanban/boards/default/deleted/attachments/1.log +1 -0
  39. package/tmp/screenshots-workspace/.kanban.json +59 -0
@@ -433,42 +433,42 @@ var require_queue = __commonJS({
433
433
  queue.drained = drained;
434
434
  return queue;
435
435
  function push(value) {
436
- var p = new Promise(function(resolve9, reject) {
436
+ var p = new Promise(function(resolve10, reject) {
437
437
  pushCb(value, function(err, result) {
438
438
  if (err) {
439
439
  reject(err);
440
440
  return;
441
441
  }
442
- resolve9(result);
442
+ resolve10(result);
443
443
  });
444
444
  });
445
445
  p.catch(noop);
446
446
  return p;
447
447
  }
448
448
  function unshift(value) {
449
- var p = new Promise(function(resolve9, reject) {
449
+ var p = new Promise(function(resolve10, reject) {
450
450
  unshiftCb(value, function(err, result) {
451
451
  if (err) {
452
452
  reject(err);
453
453
  return;
454
454
  }
455
- resolve9(result);
455
+ resolve10(result);
456
456
  });
457
457
  });
458
458
  p.catch(noop);
459
459
  return p;
460
460
  }
461
461
  function drained() {
462
- var p = new Promise(function(resolve9) {
462
+ var p = new Promise(function(resolve10) {
463
463
  process.nextTick(function() {
464
464
  if (queue.idle()) {
465
- resolve9();
465
+ resolve10();
466
466
  } else {
467
467
  var previousDrain = queue.drain;
468
468
  queue.drain = function() {
469
469
  if (typeof previousDrain === "function")
470
470
  previousDrain();
471
- resolve9();
471
+ resolve10();
472
472
  queue.drain = previousDrain;
473
473
  };
474
474
  }
@@ -813,8 +813,8 @@ var require_create_promise = __commonJS({
813
813
  reject: null,
814
814
  promise: null
815
815
  };
816
- obj.promise = new Promise((resolve9, reject) => {
817
- obj.resolve = resolve9;
816
+ obj.promise = new Promise((resolve10, reject) => {
817
+ obj.resolve = resolve10;
818
818
  obj.reject = reject;
819
819
  });
820
820
  return obj;
@@ -1083,11 +1083,11 @@ var require_thenify = __commonJS({
1083
1083
  return;
1084
1084
  }
1085
1085
  debug("thenify");
1086
- return (resolve9, reject) => {
1086
+ return (resolve10, reject) => {
1087
1087
  const p = this._loadRegistered();
1088
1088
  return p.then(() => {
1089
1089
  this[kThenifyDoNotWrap] = true;
1090
- return resolve9(this._server);
1090
+ return resolve10(this._server);
1091
1091
  }, reject);
1092
1092
  };
1093
1093
  }
@@ -1224,12 +1224,12 @@ var require_boot = __commonJS({
1224
1224
  inherits(Boot, EE);
1225
1225
  if ("asyncDispose" in Symbol) {
1226
1226
  Boot.prototype[Symbol.asyncDispose] = function() {
1227
- return new Promise((resolve9, reject) => {
1227
+ return new Promise((resolve10, reject) => {
1228
1228
  this.close((err) => {
1229
1229
  if (err) {
1230
1230
  return reject(err);
1231
1231
  }
1232
- resolve9();
1232
+ resolve10();
1233
1233
  });
1234
1234
  });
1235
1235
  };
@@ -1376,12 +1376,12 @@ var require_boot = __commonJS({
1376
1376
  throw new AVV_ERR_CALLBACK_NOT_FN("close", typeof func);
1377
1377
  }
1378
1378
  } else {
1379
- promise = new Promise(function(resolve9, reject) {
1379
+ promise = new Promise(function(resolve10, reject) {
1380
1380
  func = function(err) {
1381
1381
  if (err) {
1382
1382
  return reject(err);
1383
1383
  }
1384
- resolve9();
1384
+ resolve10();
1385
1385
  };
1386
1386
  });
1387
1387
  }
@@ -1401,7 +1401,7 @@ var require_boot = __commonJS({
1401
1401
  queueMicrotask(this.start.bind(this));
1402
1402
  return;
1403
1403
  }
1404
- return new Promise((resolve9, reject) => {
1404
+ return new Promise((resolve10, reject) => {
1405
1405
  this._readyQ.push(readyPromiseCB);
1406
1406
  this.start();
1407
1407
  const relativeContext = this._current[0].server;
@@ -1409,7 +1409,7 @@ var require_boot = __commonJS({
1409
1409
  if (err) {
1410
1410
  reject(err);
1411
1411
  } else {
1412
- resolve9(relativeContext);
1412
+ resolve10(relativeContext);
1413
1413
  }
1414
1414
  process.nextTick(done);
1415
1415
  }
@@ -2691,8 +2691,8 @@ var require_promise = __commonJS({
2691
2691
  var { kTestInternals } = require_symbols2();
2692
2692
  function withResolvers() {
2693
2693
  let res, rej;
2694
- const promise = new Promise((resolve9, reject) => {
2695
- res = resolve9;
2694
+ const promise = new Promise((resolve10, reject) => {
2695
+ res = resolve10;
2696
2696
  rej = reject;
2697
2697
  });
2698
2698
  return { promise, resolve: res, reject: rej };
@@ -2791,15 +2791,15 @@ var require_server = __commonJS({
2791
2791
  if (cb === void 0) {
2792
2792
  const listening = listenPromise.call(this, server2, listenOptions);
2793
2793
  return listening.then((address) => {
2794
- const { promise, resolve: resolve9 } = PonyPromise.withResolvers();
2794
+ const { promise, resolve: resolve10 } = PonyPromise.withResolvers();
2795
2795
  if (host === "localhost") {
2796
2796
  multipleBindings.call(this, server2, httpHandler, options, listenOptions, () => {
2797
2797
  this[kState].listening = true;
2798
- resolve9(address);
2798
+ resolve10(address);
2799
2799
  onListenHookRunner(this);
2800
2800
  });
2801
2801
  } else {
2802
- resolve9(address);
2802
+ resolve10(address);
2803
2803
  onListenHookRunner(this);
2804
2804
  }
2805
2805
  return promise;
@@ -2928,7 +2928,7 @@ var require_server = __commonJS({
2928
2928
  return this.ready().then(() => {
2929
2929
  if (this[kState].aborted)
2930
2930
  return;
2931
- const { promise, resolve: resolve9, reject } = PonyPromise.withResolvers();
2931
+ const { promise, resolve: resolve10, reject } = PonyPromise.withResolvers();
2932
2932
  const errEventHandler = (err) => {
2933
2933
  cleanup();
2934
2934
  this[kState].listening = false;
@@ -2937,7 +2937,7 @@ var require_server = __commonJS({
2937
2937
  const listeningEventHandler = () => {
2938
2938
  cleanup();
2939
2939
  this[kState].listening = true;
2940
- resolve9(logServerAddress.call(
2940
+ resolve10(logServerAddress.call(
2941
2941
  this,
2942
2942
  server2,
2943
2943
  listenOptions.listenTextResolver || defaultResolveServerListeningText
@@ -5660,7 +5660,7 @@ var require_thread_stream = __commonJS({
5660
5660
  var { version } = require_package();
5661
5661
  var { EventEmitter: EventEmitter3 } = require("events");
5662
5662
  var { Worker } = require("worker_threads");
5663
- var { join: join20 } = require("path");
5663
+ var { join: join21 } = require("path");
5664
5664
  var { pathToFileURL } = require("url");
5665
5665
  var { wait } = require_wait();
5666
5666
  var {
@@ -5696,7 +5696,7 @@ var require_thread_stream = __commonJS({
5696
5696
  function createWorker(stream, opts) {
5697
5697
  const { filename, workerData } = opts;
5698
5698
  const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
5699
- const toExecute = bundlerOverrides["thread-stream-worker"] || join20(__dirname, "lib", "worker.js");
5699
+ const toExecute = bundlerOverrides["thread-stream-worker"] || join21(__dirname, "lib", "worker.js");
5700
5700
  const worker = new Worker(toExecute, {
5701
5701
  ...opts.workerOpts,
5702
5702
  trackUnmanagedFds: false,
@@ -6087,7 +6087,7 @@ var require_transport = __commonJS({
6087
6087
  var { createRequire: createRequire2 } = require("module");
6088
6088
  var { existsSync: existsSync4 } = require("node:fs");
6089
6089
  var getCallers = require_caller();
6090
- var { join: join20, isAbsolute: isAbsolute2, sep: sep2 } = require("node:path");
6090
+ var { join: join21, isAbsolute: isAbsolute2, sep: sep2 } = require("node:path");
6091
6091
  var { fileURLToPath: fileURLToPath2 } = require("node:url");
6092
6092
  var sleep = require_atomic_sleep();
6093
6093
  var onExit = require_on_exit_leak_free();
@@ -6240,7 +6240,7 @@ var require_transport = __commonJS({
6240
6240
  throw new Error("only one of target or targets can be specified");
6241
6241
  }
6242
6242
  if (targets) {
6243
- target = bundlerOverrides["pino-worker"] || join20(__dirname, "worker.js");
6243
+ target = bundlerOverrides["pino-worker"] || join21(__dirname, "worker.js");
6244
6244
  options.targets = targets.filter((dest) => dest.target).map((dest) => {
6245
6245
  return {
6246
6246
  ...dest,
@@ -6258,7 +6258,7 @@ var require_transport = __commonJS({
6258
6258
  });
6259
6259
  });
6260
6260
  } else if (pipeline) {
6261
- target = bundlerOverrides["pino-worker"] || join20(__dirname, "worker.js");
6261
+ target = bundlerOverrides["pino-worker"] || join21(__dirname, "worker.js");
6262
6262
  options.pipelines = [pipeline.map((dest) => {
6263
6263
  return {
6264
6264
  ...dest,
@@ -6281,7 +6281,7 @@ var require_transport = __commonJS({
6281
6281
  return origin;
6282
6282
  }
6283
6283
  if (origin === "pino/file") {
6284
- return join20(__dirname, "..", "file.js");
6284
+ return join21(__dirname, "..", "file.js");
6285
6285
  }
6286
6286
  let fixTarget2;
6287
6287
  for (const filePath of callers) {
@@ -7271,7 +7271,7 @@ var require_safe_stable_stringify = __commonJS({
7271
7271
  return circularValue;
7272
7272
  }
7273
7273
  let res = "";
7274
- let join20 = ",";
7274
+ let join21 = ",";
7275
7275
  const originalIndentation = indentation;
7276
7276
  if (Array.isArray(value)) {
7277
7277
  if (value.length === 0) {
@@ -7285,7 +7285,7 @@ var require_safe_stable_stringify = __commonJS({
7285
7285
  indentation += spacer;
7286
7286
  res += `
7287
7287
  ${indentation}`;
7288
- join20 = `,
7288
+ join21 = `,
7289
7289
  ${indentation}`;
7290
7290
  }
7291
7291
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -7293,13 +7293,13 @@ ${indentation}`;
7293
7293
  for (; i < maximumValuesToStringify - 1; i++) {
7294
7294
  const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
7295
7295
  res += tmp2 !== void 0 ? tmp2 : "null";
7296
- res += join20;
7296
+ res += join21;
7297
7297
  }
7298
7298
  const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
7299
7299
  res += tmp !== void 0 ? tmp : "null";
7300
7300
  if (value.length - 1 > maximumBreadth) {
7301
7301
  const removedKeys = value.length - maximumBreadth - 1;
7302
- res += `${join20}"... ${getItemCount(removedKeys)} not stringified"`;
7302
+ res += `${join21}"... ${getItemCount(removedKeys)} not stringified"`;
7303
7303
  }
7304
7304
  if (spacer !== "") {
7305
7305
  res += `
@@ -7320,7 +7320,7 @@ ${originalIndentation}`;
7320
7320
  let separator = "";
7321
7321
  if (spacer !== "") {
7322
7322
  indentation += spacer;
7323
- join20 = `,
7323
+ join21 = `,
7324
7324
  ${indentation}`;
7325
7325
  whitespace = " ";
7326
7326
  }
@@ -7334,13 +7334,13 @@ ${indentation}`;
7334
7334
  const tmp = stringifyFnReplacer(key2, value, stack, replacer, spacer, indentation);
7335
7335
  if (tmp !== void 0) {
7336
7336
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
7337
- separator = join20;
7337
+ separator = join21;
7338
7338
  }
7339
7339
  }
7340
7340
  if (keyLength > maximumBreadth) {
7341
7341
  const removedKeys = keyLength - maximumBreadth;
7342
7342
  res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
7343
- separator = join20;
7343
+ separator = join21;
7344
7344
  }
7345
7345
  if (spacer !== "" && separator.length > 1) {
7346
7346
  res = `
@@ -7380,7 +7380,7 @@ ${originalIndentation}`;
7380
7380
  }
7381
7381
  const originalIndentation = indentation;
7382
7382
  let res = "";
7383
- let join20 = ",";
7383
+ let join21 = ",";
7384
7384
  if (Array.isArray(value)) {
7385
7385
  if (value.length === 0) {
7386
7386
  return "[]";
@@ -7393,7 +7393,7 @@ ${originalIndentation}`;
7393
7393
  indentation += spacer;
7394
7394
  res += `
7395
7395
  ${indentation}`;
7396
- join20 = `,
7396
+ join21 = `,
7397
7397
  ${indentation}`;
7398
7398
  }
7399
7399
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
@@ -7401,13 +7401,13 @@ ${indentation}`;
7401
7401
  for (; i < maximumValuesToStringify - 1; i++) {
7402
7402
  const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
7403
7403
  res += tmp2 !== void 0 ? tmp2 : "null";
7404
- res += join20;
7404
+ res += join21;
7405
7405
  }
7406
7406
  const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
7407
7407
  res += tmp !== void 0 ? tmp : "null";
7408
7408
  if (value.length - 1 > maximumBreadth) {
7409
7409
  const removedKeys = value.length - maximumBreadth - 1;
7410
- res += `${join20}"... ${getItemCount(removedKeys)} not stringified"`;
7410
+ res += `${join21}"... ${getItemCount(removedKeys)} not stringified"`;
7411
7411
  }
7412
7412
  if (spacer !== "") {
7413
7413
  res += `
@@ -7420,7 +7420,7 @@ ${originalIndentation}`;
7420
7420
  let whitespace = "";
7421
7421
  if (spacer !== "") {
7422
7422
  indentation += spacer;
7423
- join20 = `,
7423
+ join21 = `,
7424
7424
  ${indentation}`;
7425
7425
  whitespace = " ";
7426
7426
  }
@@ -7429,7 +7429,7 @@ ${indentation}`;
7429
7429
  const tmp = stringifyArrayReplacer(key2, value[key2], stack, replacer, spacer, indentation);
7430
7430
  if (tmp !== void 0) {
7431
7431
  res += `${separator}${strEscape(key2)}:${whitespace}${tmp}`;
7432
- separator = join20;
7432
+ separator = join21;
7433
7433
  }
7434
7434
  }
7435
7435
  if (spacer !== "" && separator.length > 1) {
@@ -7486,20 +7486,20 @@ ${originalIndentation}`;
7486
7486
  indentation += spacer;
7487
7487
  let res2 = `
7488
7488
  ${indentation}`;
7489
- const join21 = `,
7489
+ const join22 = `,
7490
7490
  ${indentation}`;
7491
7491
  const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
7492
7492
  let i = 0;
7493
7493
  for (; i < maximumValuesToStringify - 1; i++) {
7494
7494
  const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
7495
7495
  res2 += tmp2 !== void 0 ? tmp2 : "null";
7496
- res2 += join21;
7496
+ res2 += join22;
7497
7497
  }
7498
7498
  const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
7499
7499
  res2 += tmp !== void 0 ? tmp : "null";
7500
7500
  if (value.length - 1 > maximumBreadth) {
7501
7501
  const removedKeys = value.length - maximumBreadth - 1;
7502
- res2 += `${join21}"... ${getItemCount(removedKeys)} not stringified"`;
7502
+ res2 += `${join22}"... ${getItemCount(removedKeys)} not stringified"`;
7503
7503
  }
7504
7504
  res2 += `
7505
7505
  ${originalIndentation}`;
@@ -7515,16 +7515,16 @@ ${originalIndentation}`;
7515
7515
  return '"[Object]"';
7516
7516
  }
7517
7517
  indentation += spacer;
7518
- const join20 = `,
7518
+ const join21 = `,
7519
7519
  ${indentation}`;
7520
7520
  let res = "";
7521
7521
  let separator = "";
7522
7522
  let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
7523
7523
  if (isTypedArrayWithEntries(value)) {
7524
- res += stringifyTypedArray(value, join20, maximumBreadth);
7524
+ res += stringifyTypedArray(value, join21, maximumBreadth);
7525
7525
  keys = keys.slice(value.length);
7526
7526
  maximumPropertiesToStringify -= value.length;
7527
- separator = join20;
7527
+ separator = join21;
7528
7528
  }
7529
7529
  if (deterministic) {
7530
7530
  keys = sort(keys, comparator);
@@ -7535,13 +7535,13 @@ ${indentation}`;
7535
7535
  const tmp = stringifyIndent(key2, value[key2], stack, spacer, indentation);
7536
7536
  if (tmp !== void 0) {
7537
7537
  res += `${separator}${strEscape(key2)}: ${tmp}`;
7538
- separator = join20;
7538
+ separator = join21;
7539
7539
  }
7540
7540
  }
7541
7541
  if (keyLength > maximumBreadth) {
7542
7542
  const removedKeys = keyLength - maximumBreadth;
7543
7543
  res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
7544
- separator = join20;
7544
+ separator = join21;
7545
7545
  }
7546
7546
  if (separator !== "") {
7547
7547
  res = `
@@ -15429,7 +15429,7 @@ var require_compile = __commonJS({
15429
15429
  const schOrFunc = root.refs[ref];
15430
15430
  if (schOrFunc)
15431
15431
  return schOrFunc;
15432
- let _sch = resolve9.call(this, root, ref);
15432
+ let _sch = resolve10.call(this, root, ref);
15433
15433
  if (_sch === void 0) {
15434
15434
  const schema2 = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
15435
15435
  const { schemaId } = this.opts;
@@ -15456,7 +15456,7 @@ var require_compile = __commonJS({
15456
15456
  function sameSchemaEnv(s1, s2) {
15457
15457
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
15458
15458
  }
15459
- function resolve9(root, ref) {
15459
+ function resolve10(root, ref) {
15460
15460
  let sch;
15461
15461
  while (typeof (sch = this.refs[ref]) == "string")
15462
15462
  ref = sch;
@@ -16032,7 +16032,7 @@ var require_fast_uri = __commonJS({
16032
16032
  }
16033
16033
  return uri;
16034
16034
  }
16035
- function resolve9(baseURI, relativeURI, options) {
16035
+ function resolve10(baseURI, relativeURI, options) {
16036
16036
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
16037
16037
  const resolved = resolveComponent(parse2(baseURI, schemelessOptions), parse2(relativeURI, schemelessOptions), schemelessOptions, true);
16038
16038
  schemelessOptions.skipEscape = true;
@@ -16260,7 +16260,7 @@ var require_fast_uri = __commonJS({
16260
16260
  var fastUri = {
16261
16261
  SCHEMES,
16262
16262
  normalize: normalize2,
16263
- resolve: resolve9,
16263
+ resolve: resolve10,
16264
16264
  resolveComponent,
16265
16265
  equal,
16266
16266
  serialize,
@@ -33670,9 +33670,9 @@ var require_light_my_request = __commonJS({
33670
33670
  const res = new Response(req, callback);
33671
33671
  return makeRequest(dispatchFunc, server2, req, res);
33672
33672
  } else {
33673
- return new Promise((resolve9, reject) => {
33673
+ return new Promise((resolve10, reject) => {
33674
33674
  const req = new RequestConstructor(options);
33675
- const res = new Response(req, resolve9, reject);
33675
+ const res = new Response(req, resolve10, reject);
33676
33676
  makeRequest(dispatchFunc, server2, req, res);
33677
33677
  });
33678
33678
  }
@@ -38573,7 +38573,7 @@ var require_eventemitter2 = __commonJS({
38573
38573
  var callbacks;
38574
38574
  var timer = 0;
38575
38575
  var subscriptionClosed;
38576
- var promise = new Promise2(function(resolve9, reject, onCancel) {
38576
+ var promise = new Promise2(function(resolve10, reject, onCancel) {
38577
38577
  options = resolveOptions(options, {
38578
38578
  timeout: 0,
38579
38579
  overload: false
@@ -38598,7 +38598,7 @@ var require_eventemitter2 = __commonJS({
38598
38598
  }
38599
38599
  var _resolve = function(value) {
38600
38600
  cleanup();
38601
- resolve9(value);
38601
+ resolve10(value);
38602
38602
  };
38603
38603
  var _reject = function(err) {
38604
38604
  cleanup();
@@ -38915,8 +38915,8 @@ var require_eventemitter2 = __commonJS({
38915
38915
  var args = arguments;
38916
38916
  var context = this;
38917
38917
  var event2 = this.event;
38918
- return promisify6 ? nextTick ? Promise.resolve() : new Promise(function(resolve9) {
38919
- _setImmediate(resolve9);
38918
+ return promisify6 ? nextTick ? Promise.resolve() : new Promise(function(resolve10) {
38919
+ _setImmediate(resolve10);
38920
38920
  }).then(function() {
38921
38921
  context.event = event2;
38922
38922
  return _listener.apply(context, args);
@@ -39516,7 +39516,7 @@ var require_eventemitter2 = __commonJS({
39516
39516
  filter: functionReducer,
39517
39517
  Promise: constructorReducer
39518
39518
  });
39519
- return makeCancelablePromise(options.Promise, function(resolve9, reject, onCancel) {
39519
+ return makeCancelablePromise(options.Promise, function(resolve10, reject, onCancel) {
39520
39520
  function listener() {
39521
39521
  var filter = options.filter;
39522
39522
  if (filter && !filter.apply(self2, arguments)) {
@@ -39525,9 +39525,9 @@ var require_eventemitter2 = __commonJS({
39525
39525
  self2.off(event, listener);
39526
39526
  if (options.handleError) {
39527
39527
  var err = arguments[0];
39528
- err ? reject(err) : resolve9(toArray2.apply(null, arguments).slice(1));
39528
+ err ? reject(err) : resolve10(toArray2.apply(null, arguments).slice(1));
39529
39529
  } else {
39530
- resolve9(toArray2.apply(null, arguments));
39530
+ resolve10(toArray2.apply(null, arguments));
39531
39531
  }
39532
39532
  }
39533
39533
  onCancel(function() {
@@ -39548,11 +39548,11 @@ var require_eventemitter2 = __commonJS({
39548
39548
  Promise: constructorReducer
39549
39549
  });
39550
39550
  var _Promise = options.Promise;
39551
- return makeCancelablePromise(_Promise, function(resolve9, reject, onCancel) {
39551
+ return makeCancelablePromise(_Promise, function(resolve10, reject, onCancel) {
39552
39552
  var handler;
39553
39553
  if (typeof emitter.addEventListener === "function") {
39554
39554
  handler = function() {
39555
- resolve9(toArray2.apply(null, arguments));
39555
+ resolve10(toArray2.apply(null, arguments));
39556
39556
  };
39557
39557
  onCancel(function() {
39558
39558
  emitter.removeEventListener(name, handler);
@@ -39566,7 +39566,7 @@ var require_eventemitter2 = __commonJS({
39566
39566
  }
39567
39567
  var eventListener = function() {
39568
39568
  errorListener && emitter.removeListener("error", errorListener);
39569
- resolve9(toArray2.apply(null, arguments));
39569
+ resolve10(toArray2.apply(null, arguments));
39570
39570
  };
39571
39571
  var errorListener;
39572
39572
  if (name !== "error") {
@@ -49639,14 +49639,14 @@ var init_open = __esm({
49639
49639
  }
49640
49640
  const subprocess = import_node_child_process5.default.spawn(command, cliArguments, childProcessOptions);
49641
49641
  if (options.wait) {
49642
- return new Promise((resolve9, reject) => {
49642
+ return new Promise((resolve10, reject) => {
49643
49643
  subprocess.once("error", reject);
49644
49644
  subprocess.once("close", (exitCode) => {
49645
49645
  if (!options.allowNonzeroExitCode && exitCode > 0) {
49646
49646
  reject(new Error(`Exited with code ${exitCode}`));
49647
49647
  return;
49648
49648
  }
49649
- resolve9(subprocess);
49649
+ resolve10(subprocess);
49650
49650
  });
49651
49651
  });
49652
49652
  }
@@ -49894,11 +49894,87 @@ function migrateConfigV1ToV2(raw) {
49894
49894
  }
49895
49895
  return v2;
49896
49896
  }
49897
+ function loadDotEnv(dir2) {
49898
+ const envPath = path.join(dir2, ".env");
49899
+ let content;
49900
+ try {
49901
+ content = fs.readFileSync(envPath, "utf-8");
49902
+ } catch {
49903
+ return;
49904
+ }
49905
+ for (const line of content.split("\n")) {
49906
+ const trimmed = line.trim();
49907
+ if (!trimmed || trimmed.startsWith("#"))
49908
+ continue;
49909
+ const eqIdx = trimmed.indexOf("=");
49910
+ if (eqIdx < 1)
49911
+ continue;
49912
+ const key = trimmed.slice(0, eqIdx).trim();
49913
+ let val = trimmed.slice(eqIdx + 1).trim();
49914
+ if (val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'")) {
49915
+ val = val.slice(1, -1);
49916
+ }
49917
+ if (process.env[key] === void 0) {
49918
+ process.env[key] = val;
49919
+ }
49920
+ }
49921
+ }
49922
+ function resolveConfigEnvVars(node, configFileName, nodePath = "") {
49923
+ const isFormDefaultDataPath = /^\.forms\.(?:[^.]+|"[^"]+")\.data(?:$|[.\[])/.test(nodePath);
49924
+ if (isFormDefaultDataPath) {
49925
+ return node;
49926
+ }
49927
+ if (typeof node === "string") {
49928
+ return node.replace(/\$\{([^}]+)\}/g, (_match, varName) => {
49929
+ const envValue = process.env[varName];
49930
+ if (envValue === void 0) {
49931
+ throw new Error(
49932
+ `missing ${varName} in ${configFileName}: ${nodePath} "${node}"`
49933
+ );
49934
+ }
49935
+ return envValue;
49936
+ });
49937
+ }
49938
+ if (Array.isArray(node)) {
49939
+ for (let i = 0; i < node.length; i++) {
49940
+ node[i] = resolveConfigEnvVars(node[i], configFileName, `${nodePath}[${i}]`);
49941
+ }
49942
+ return node;
49943
+ }
49944
+ if (node !== null && typeof node === "object") {
49945
+ const obj = node;
49946
+ for (const key of Object.keys(obj)) {
49947
+ const jsonKey = /[^a-zA-Z0-9_]/.test(key) ? `"${key}"` : key;
49948
+ const childPath = nodePath ? `${nodePath}.${jsonKey}` : `.${jsonKey}`;
49949
+ obj[key] = resolveConfigEnvVars(obj[key], configFileName, childPath);
49950
+ }
49951
+ return obj;
49952
+ }
49953
+ return node;
49954
+ }
49897
49955
  function readConfig(workspaceRoot2) {
49898
49956
  const filePath = configPath(workspaceRoot2);
49899
49957
  const defaults = { ...DEFAULT_CONFIG, boards: { default: { ...DEFAULT_BOARD_CONFIG, columns: [...DEFAULT_COLUMNS] } } };
49958
+ let raw;
49959
+ try {
49960
+ raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
49961
+ } catch {
49962
+ return defaults;
49963
+ }
49964
+ loadDotEnv(workspaceRoot2);
49965
+ try {
49966
+ resolveConfigEnvVars(raw, CONFIG_FILENAME);
49967
+ } catch (err) {
49968
+ const msg = err instanceof Error ? err.message : String(err);
49969
+ process.stderr.write(`
49970
+ Configuration error: ${msg}
49971
+
49972
+ Set the missing environment variable before starting the server.
49973
+
49974
+ `);
49975
+ process.exit(1);
49976
+ }
49900
49977
  try {
49901
- const raw = JSON.parse(fs.readFileSync(filePath, "utf-8"));
49902
49978
  const isV1 = raw.version === 1 || !raw.version && !(typeof raw.boards === "object" && raw.boards !== null && !Array.isArray(raw.boards));
49903
49979
  if (isV1) {
49904
49980
  const v2 = migrateConfigV1ToV2(raw);
@@ -55238,7 +55314,7 @@ var NodeFsHandler = class {
55238
55314
  this._addToNodeFs(path23, initialAdd, wh, depth + 1);
55239
55315
  }
55240
55316
  }).on(EV.ERROR, this._boundHandleError);
55241
- return new Promise((resolve9, reject) => {
55317
+ return new Promise((resolve10, reject) => {
55242
55318
  if (!stream)
55243
55319
  return reject();
55244
55320
  stream.once(STR_END, () => {
@@ -55247,7 +55323,7 @@ var NodeFsHandler = class {
55247
55323
  return;
55248
55324
  }
55249
55325
  const wasThrottled = throttler ? throttler.clear() : false;
55250
- resolve9(void 0);
55326
+ resolve10(void 0);
55251
55327
  previous.getChildren().filter((item) => {
55252
55328
  return item !== directory && !current.has(item);
55253
55329
  }).forEach((item) => {
@@ -56338,6 +56414,13 @@ function setupWatcher(ctx, server2) {
56338
56414
  ctx.wss.close();
56339
56415
  });
56340
56416
  }
56417
+ const configFilePath = path7.join(ctx.workspaceRoot, ".kanban.json");
56418
+ const configWatcher = esm_default.watch(configFilePath, {
56419
+ ignoreInitial: true,
56420
+ awaitWriteFinish: { stabilityThreshold: 100 }
56421
+ });
56422
+ configWatcher.on("change", () => handleFileChange(ctx, debounceRef));
56423
+ server2.on("close", () => configWatcher.close());
56341
56424
  }
56342
56425
 
56343
56426
  // src/standalone/httpUtils.ts
@@ -56368,13 +56451,13 @@ function readBody(req) {
56368
56451
  return Promise.reject(err);
56369
56452
  }
56370
56453
  }
56371
- return new Promise((resolve9, reject) => {
56454
+ return new Promise((resolve10, reject) => {
56372
56455
  const chunks = [];
56373
56456
  req.on("data", (chunk) => chunks.push(chunk));
56374
56457
  req.on("end", () => {
56375
56458
  try {
56376
56459
  const text = Buffer.concat(chunks).toString("utf-8");
56377
- resolve9(text ? JSON.parse(text) : {});
56460
+ resolve10(text ? JSON.parse(text) : {});
56378
56461
  } catch (err) {
56379
56462
  reject(err);
56380
56463
  }
@@ -56694,7 +56777,7 @@ var EventBus = class {
56694
56777
  * Wildcard patterns are supported.
56695
56778
  */
56696
56779
  waitFor(event, options) {
56697
- return new Promise((resolve9, reject) => {
56780
+ return new Promise((resolve10, reject) => {
56698
56781
  let timer;
56699
56782
  const unsubscribe = this.on(event, (payload) => {
56700
56783
  try {
@@ -56703,7 +56786,7 @@ var EventBus = class {
56703
56786
  if (timer)
56704
56787
  clearTimeout(timer);
56705
56788
  unsubscribe();
56706
- resolve9(payload);
56789
+ resolve10(payload);
56707
56790
  } catch (error) {
56708
56791
  if (timer)
56709
56792
  clearTimeout(timer);
@@ -56928,7 +57011,7 @@ function resolveAuthIdentityPlugin(ref) {
56928
57011
  if (ref.provider === "rbac")
56929
57012
  return RBAC_IDENTITY_PLUGIN;
56930
57013
  const packageName = AUTH_PROVIDER_ALIASES.get(ref.provider) ?? ref.provider;
56931
- return loadExternalAuthIdentityPlugin(packageName, ref.provider);
57014
+ return loadExternalAuthIdentityPlugin(packageName, ref.provider, ref.options);
56932
57015
  }
56933
57016
  function resolveAuthPolicyPlugin(ref) {
56934
57017
  if (ref.provider === "noop")
@@ -57154,8 +57237,13 @@ function selectAuthPolicyPlugin(mod, providerId) {
57154
57237
  return direct;
57155
57238
  return null;
57156
57239
  }
57157
- function loadExternalAuthIdentityPlugin(packageName, providerId) {
57240
+ function loadExternalAuthIdentityPlugin(packageName, providerId, options) {
57158
57241
  const mod = loadExternalModule(packageName);
57242
+ if (options !== void 0 && typeof mod.createAuthIdentityPlugin === "function") {
57243
+ const created = mod.createAuthIdentityPlugin(options);
57244
+ if (isValidAuthIdentityPlugin(created, providerId))
57245
+ return created;
57246
+ }
57159
57247
  const plugin = selectAuthIdentityPlugin(mod, providerId);
57160
57248
  if (!plugin) {
57161
57249
  throw new Error(
@@ -60158,29 +60246,10 @@ async function updateCard(ctx, { cardId, updates, boardId }) {
60158
60246
  return card;
60159
60247
  }
60160
60248
  async function triggerAction(ctx, { cardId, action, boardId }) {
60161
- const config = readConfig(ctx.workspaceRoot);
60162
- const { actionWebhookUrl } = config;
60163
- if (!actionWebhookUrl) {
60164
- throw new Error("No action webhook URL configured. Set actionWebhookUrl in .kanban.json");
60165
- }
60166
60249
  const card = await getCard(ctx, { cardId, boardId });
60167
60250
  if (!card)
60168
60251
  throw new Error(`Card not found: ${cardId}`);
60169
60252
  const resolvedBoardId = card.boardId || ctx._resolveBoardId(boardId);
60170
- const payload = {
60171
- action,
60172
- board: resolvedBoardId,
60173
- list: card.status,
60174
- card: sanitizeCard(card)
60175
- };
60176
- const response = await fetch(actionWebhookUrl, {
60177
- method: "POST",
60178
- headers: { "Content-Type": "application/json" },
60179
- body: JSON.stringify(payload)
60180
- });
60181
- if (!response.ok) {
60182
- throw new Error(`Action webhook responded with ${response.status}: ${response.statusText}`);
60183
- }
60184
60253
  await appendActivityLog(ctx, {
60185
60254
  cardId,
60186
60255
  boardId: resolvedBoardId,
@@ -60191,6 +60260,12 @@ async function triggerAction(ctx, { cardId, action, boardId }) {
60191
60260
  }
60192
60261
  }).catch(() => {
60193
60262
  });
60263
+ return {
60264
+ action,
60265
+ board: resolvedBoardId,
60266
+ list: card.status,
60267
+ card: sanitizeCard(card)
60268
+ };
60194
60269
  }
60195
60270
  async function submitForm(ctx, input) {
60196
60271
  const card = await getCard(ctx, { cardId: input.cardId, boardId: input.boardId });
@@ -61607,6 +61682,25 @@ var KanbanSDK = class _KanbanSDK {
61607
61682
  get workspaceRoot() {
61608
61683
  return path17.dirname(this.kanbanDir);
61609
61684
  }
61685
+ /**
61686
+ * Returns a cloned read-only snapshot of the current workspace config.
61687
+ *
61688
+ * The returned snapshot is created from a fresh config read and deep-cloned
61689
+ * before being returned, so callers receive an isolated view of the current
61690
+ * `.kanban.json` state rather than a live mutable runtime object. Mutating the
61691
+ * returned snapshot does not update persisted config or affect this SDK instance.
61692
+ *
61693
+ * @returns A cloned read-only snapshot of the current {@link KanbanConfig}.
61694
+ *
61695
+ * @example
61696
+ * ```ts
61697
+ * const config = sdk.getConfigSnapshot()
61698
+ * console.log(config.defaultBoard)
61699
+ * ```
61700
+ */
61701
+ getConfigSnapshot() {
61702
+ return structuredClone(readConfig(this.workspaceRoot));
61703
+ }
61610
61704
  // --- Board resolution helpers ---
61611
61705
  /** @internal */
61612
61706
  _resolveBoardId(boardId) {
@@ -62073,21 +62167,17 @@ var KanbanSDK = class _KanbanSDK {
62073
62167
  return result;
62074
62168
  }
62075
62169
  /**
62076
- * Triggers a named action for a card by POSTing to the global `actionWebhookUrl`
62077
- * configured in `.kanban.json`.
62170
+ * Triggers a named action for a card.
62078
62171
  *
62079
- * The payload sent to the webhook is:
62080
- * ```json
62081
- * { "action": "retry", "board": "default", "list": "in-progress", "card": { ...sanitizedCard } }
62082
- * ```
62172
+ * Validates the card, appends an activity log entry, and emits the
62173
+ * `card.action.triggered` after-event so registered webhooks receive
62174
+ * the action payload automatically.
62083
62175
  *
62084
62176
  * @param cardId - The ID of the card to trigger the action for.
62085
62177
  * @param action - The action name string (e.g. `'retry'`, `'sendEmail'`).
62086
62178
  * @param boardId - Optional board ID. Defaults to the workspace's default board.
62087
- * @returns A promise resolving when the webhook responds with 2xx.
62088
- * @throws {Error} If no `actionWebhookUrl` is configured in `.kanban.json`.
62179
+ * @returns A promise that resolves when the action has been processed.
62089
62180
  * @throws {Error} If the card is not found.
62090
- * @throws {Error} If the webhook responds with a non-2xx status.
62091
62181
  *
62092
62182
  * @example
62093
62183
  * ```ts
@@ -62097,7 +62187,8 @@ var KanbanSDK = class _KanbanSDK {
62097
62187
  */
62098
62188
  async triggerAction(cardId, action, boardId) {
62099
62189
  const mergedInput = await this._runBeforeEvent("card.action.trigger", { cardId, action, boardId }, void 0, boardId);
62100
- return triggerAction(this, mergedInput);
62190
+ const payload = await triggerAction(this, mergedInput);
62191
+ this._runAfterEvent("card.action.triggered", payload, void 0, payload.board);
62101
62192
  }
62102
62193
  /**
62103
62194
  * Moves a card to a different status column and/or position within that column.
@@ -63066,20 +63157,24 @@ var KanbanSDK = class _KanbanSDK {
63066
63157
  };
63067
63158
 
63068
63159
  // src/standalone/internal/runtime.ts
63069
- var indexHtml = `<!DOCTYPE html>
63160
+ function getIndexHtml(basePath = "") {
63161
+ return `<!DOCTYPE html>
63070
63162
  <html lang="en">
63071
63163
  <head>
63072
63164
  <meta charset="UTF-8">
63073
63165
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
63074
- <link rel="icon" type="image/svg+xml" href="/favicon.svg">
63075
- <link href="/style.css" rel="stylesheet">
63166
+ <link rel="icon" type="image/svg+xml" href="${basePath}/favicon.svg">
63167
+ <link href="${basePath}/style.css" rel="stylesheet">
63076
63168
  <title>Kanban Board</title>
63169
+ <script>window.__KB_BASE__ = ${JSON.stringify(basePath)}</script>
63077
63170
  </head>
63078
63171
  <body>
63079
63172
  <div id="root"></div>
63080
- <script type="module" src="/index.js"></script>
63173
+ <script type="module" src="${basePath}/index.js"></script>
63081
63174
  </body>
63082
63175
  </html>`;
63176
+ }
63177
+ var indexHtml = getIndexHtml();
63083
63178
  function resolveStandaloneWebviewDir(webviewDir) {
63084
63179
  if (webviewDir)
63085
63180
  return webviewDir;
@@ -63093,12 +63188,12 @@ function resolveStandaloneWebviewDir(webviewDir) {
63093
63188
  }
63094
63189
  return candidates[0];
63095
63190
  }
63096
- function createStandaloneRuntime(kanbanDir, webviewDir, httpServer) {
63191
+ function createStandaloneRuntime(kanbanDir, webviewDir, httpServer, basePath) {
63097
63192
  const absoluteKanbanDir = path18.resolve(kanbanDir);
63098
63193
  const workspaceRoot2 = path18.dirname(absoluteKanbanDir);
63099
63194
  const resolvedWebviewDir = resolveStandaloneWebviewDir(webviewDir);
63100
63195
  const server2 = httpServer ?? http.createServer();
63101
- const wss = new import_websocket_server.default({ server: server2, path: "/ws" });
63196
+ const wss = new import_websocket_server.default({ server: server2, path: (basePath || "") + "/ws" });
63102
63197
  const ctx = {};
63103
63198
  const sdk = new KanbanSDK(absoluteKanbanDir, {
63104
63199
  onEvent: (event, data) => {
@@ -65118,6 +65213,7 @@ async function handleMessage(ctx, ws, message, authContext) {
65118
65213
  const updatedCard = ctx.cards.find((card) => card.id === cardId);
65119
65214
  if (updatedCard) {
65120
65215
  await broadcastCardContentToEditingClients(ctx, updatedCard);
65216
+ await broadcastLogsUpdatedToEditingClients(ctx, cardId);
65121
65217
  }
65122
65218
  ws.send(JSON.stringify({ type: "actionResult", callbackKey }));
65123
65219
  } catch (err) {
@@ -65145,9 +65241,14 @@ async function handleMessage(ctx, ws, message, authContext) {
65145
65241
  }
65146
65242
 
65147
65243
  // src/standalone/internal/websocket.ts
65148
- function attachWebSocketHandlers(ctx) {
65149
- ctx.wss.on("connection", (ws, req) => {
65150
- const authContext = extractAuthContext(req);
65244
+ function attachWebSocketHandlers(ctx, resolveAuthContext) {
65245
+ ctx.wss.on("connection", async (ws, req) => {
65246
+ let authContext;
65247
+ try {
65248
+ authContext = resolveAuthContext ? await resolveAuthContext(req) : extractAuthContext(req);
65249
+ } catch {
65250
+ authContext = extractAuthContext(req);
65251
+ }
65151
65252
  setClientEditingCard(ctx, ws, null);
65152
65253
  ws.on("message", (data) => {
65153
65254
  let message;
@@ -65314,6 +65415,7 @@ function isPageRequest(method, pathname) {
65314
65415
  function collectStandaloneHttpHandlers(requestType, ctx) {
65315
65416
  const plugins = ctx.sdk.capabilities?.standaloneHttpPlugins ?? [];
65316
65417
  const registrationOptions = {
65418
+ sdk: ctx.sdk,
65317
65419
  workspaceRoot: ctx.workspaceRoot,
65318
65420
  kanbanDir: ctx.absoluteKanbanDir,
65319
65421
  capabilities: ctx.sdk.capabilities?.providers ?? {
@@ -65331,7 +65433,7 @@ function collectStandaloneHttpHandlers(requestType, ctx) {
65331
65433
  return handlers ? [...handlers] : [];
65332
65434
  });
65333
65435
  }
65334
- function createRequestContext(ctx, req, res, resolvedWebviewDir) {
65436
+ function createRequestContext(ctx, req, res, resolvedWebviewDir, resolvedIndexHtml) {
65335
65437
  const url = new URL(req.url || "/", `http://${req.headers.host}`);
65336
65438
  const pathname = url.pathname;
65337
65439
  const method = req.method || "GET";
@@ -65346,7 +65448,7 @@ function createRequestContext(ctx, req, res, resolvedWebviewDir) {
65346
65448
  pathname,
65347
65449
  method,
65348
65450
  resolvedWebviewDir,
65349
- indexHtml,
65451
+ indexHtml: resolvedIndexHtml,
65350
65452
  route: createRouteMatcher(method, pathname, matchRoute),
65351
65453
  isApiRequest: isApiRequestPath(pathname),
65352
65454
  isPageRequest: isPageRequest(method, pathname),
@@ -65371,16 +65473,33 @@ function startServer(kanbanDir, port2, webviewDir, resolvedConfigPath) {
65371
65473
  const swaggerUiStaticDir = resolveSwaggerUiStaticDir();
65372
65474
  const swaggerUiLogoPath = swaggerUiStaticDir ? path20.join(swaggerUiStaticDir, "logo.svg") : void 0;
65373
65475
  const swaggerUiLogo = swaggerUiLogoPath && fs15.existsSync(swaggerUiLogoPath) ? { type: "image/svg+xml", content: fs15.readFileSync(swaggerUiLogoPath) } : null;
65374
- const runtime = createStandaloneRuntime(kanbanDir, webviewDir, fastify.server);
65476
+ const workspaceRoot2 = path20.dirname(path20.resolve(kanbanDir));
65477
+ const config = readConfig(workspaceRoot2);
65478
+ const rawBase = config.basePath ?? "";
65479
+ const basePath = rawBase ? (rawBase.startsWith("/") ? rawBase : "/" + rawBase).replace(/\/+$/, "") : "";
65480
+ const runtime = createStandaloneRuntime(kanbanDir, webviewDir, fastify.server, basePath);
65375
65481
  const { ctx, resolvedWebviewDir } = runtime;
65482
+ let resolvedIndexHtml = getIndexHtml(basePath);
65483
+ let customHead = config.customHeadHtml || "";
65484
+ if (config.customHeadHtmlFile) {
65485
+ try {
65486
+ const filePath = path20.resolve(ctx.workspaceRoot, config.customHeadHtmlFile);
65487
+ customHead = fs15.readFileSync(filePath, "utf-8");
65488
+ } catch {
65489
+ }
65490
+ }
65491
+ if (customHead) {
65492
+ resolvedIndexHtml = resolvedIndexHtml.replace("</head>", `${customHead}
65493
+ </head>`);
65494
+ }
65376
65495
  const standaloneHttpPlugins = ctx.sdk.capabilities?.standaloneHttpPlugins ?? [];
65377
65496
  const standaloneOpenApiSpec = buildStandaloneOpenApiSpec(standaloneHttpPlugins);
65378
65497
  fastify.register(import_swagger.default, { openapi: standaloneOpenApiSpec });
65379
65498
  fastify.register(import_swagger_ui.default, {
65380
- routePrefix: "/api/docs",
65499
+ routePrefix: `${basePath}/api/docs`,
65381
65500
  uiConfig: { docExpansion: "list", deepLinking: false },
65382
- ...swaggerUiStaticDir ? { baseDir: swaggerUiStaticDir } : {},
65383
- ...swaggerUiLogo ? { logo: swaggerUiLogo } : {}
65501
+ logo: swaggerUiLogo,
65502
+ ...swaggerUiStaticDir ? { baseDir: swaggerUiStaticDir } : {}
65384
65503
  });
65385
65504
  fastify.removeAllContentTypeParsers();
65386
65505
  fastify.addContentTypeParser("*", { parseAs: "buffer" }, (_req, body, done) => {
@@ -65409,14 +65528,77 @@ function startServer(kanbanDir, port2, webviewDir, resolvedConfigPath) {
65409
65528
  if (request.body instanceof Buffer && request.body.length > 0) {
65410
65529
  req._rawBody = request.body;
65411
65530
  }
65412
- const requestContext = createRequestContext(ctx, req, reply.raw, resolvedWebviewDir);
65531
+ if (basePath) {
65532
+ const rawUrl = req.url ?? "/";
65533
+ if (rawUrl === basePath) {
65534
+ req.url = "/";
65535
+ } else if (rawUrl.startsWith(basePath + "/") || rawUrl.startsWith(basePath + "?")) {
65536
+ req.url = rawUrl.slice(basePath.length);
65537
+ }
65538
+ }
65539
+ const requestContext = createRequestContext(ctx, req, reply.raw, resolvedWebviewDir, resolvedIndexHtml);
65413
65540
  await dispatchRequest(requestContext, middlewareHandlers);
65414
65541
  if (!reply.sent && !reply.raw.writableEnded) {
65415
65542
  await dispatchRequest(requestContext, handlers);
65416
65543
  }
65417
65544
  reply.hijack();
65418
65545
  });
65419
- attachWebSocketHandlers(ctx);
65546
+ const resolveWsAuthContext = async (req) => {
65547
+ const silentRes = /* @__PURE__ */ (() => {
65548
+ const r = {
65549
+ writableEnded: false,
65550
+ writeHead() {
65551
+ return r;
65552
+ },
65553
+ setHeader() {
65554
+ return r;
65555
+ },
65556
+ removeHeader() {
65557
+ },
65558
+ getHeader() {
65559
+ return void 0;
65560
+ },
65561
+ getHeaders() {
65562
+ return {};
65563
+ },
65564
+ end(..._args) {
65565
+ r.writableEnded = true;
65566
+ return r;
65567
+ },
65568
+ write() {
65569
+ return false;
65570
+ }
65571
+ };
65572
+ return r;
65573
+ })();
65574
+ const reqWithBody = req;
65575
+ const wsUrl = new URL(req.url || "/", `http://${req.headers.host || "localhost"}`);
65576
+ const requestContext = {
65577
+ ctx,
65578
+ sdk: ctx.sdk,
65579
+ workspaceRoot: ctx.workspaceRoot,
65580
+ kanbanDir: ctx.absoluteKanbanDir,
65581
+ req: reqWithBody,
65582
+ res: silentRes,
65583
+ url: wsUrl,
65584
+ pathname: wsUrl.pathname,
65585
+ method: "GET",
65586
+ resolvedWebviewDir,
65587
+ indexHtml: resolvedIndexHtml,
65588
+ route: createRouteMatcher("GET", wsUrl.pathname, matchRoute),
65589
+ isApiRequest: false,
65590
+ isPageRequest: false,
65591
+ getAuthContext: () => getRequestAuthContext(req),
65592
+ setAuthContext: (auth) => setRequestAuthContext(req, auth),
65593
+ mergeAuthContext: (auth) => mergeRequestAuthContext(req, auth)
65594
+ };
65595
+ for (const handler of middlewareHandlers) {
65596
+ if (await handler(requestContext))
65597
+ break;
65598
+ }
65599
+ return extractAuthContext(req);
65600
+ };
65601
+ attachWebSocketHandlers(ctx, resolveWsAuthContext);
65420
65602
  setupStandaloneLifecycle(ctx, fastify.server);
65421
65603
  const effectiveConfigPath = resolvedConfigPath ?? configPath(path20.dirname(ctx.absoluteKanbanDir));
65422
65604
  fastify.listen({ port: port2, host: "0.0.0.0" }, (err) => {
@@ -65424,7 +65606,7 @@ function startServer(kanbanDir, port2, webviewDir, resolvedConfigPath) {
65424
65606
  console.error("Failed to start server:", err);
65425
65607
  process.exit(1);
65426
65608
  }
65427
- console.log(`Kanban board running at http://localhost:${port2}`);
65609
+ console.log(`Kanban board running at http://localhost:${port2}${basePath}`);
65428
65610
  console.log(`API available at http://localhost:${port2}/api`);
65429
65611
  console.log(`Kanban config: ${effectiveConfigPath}`);
65430
65612
  console.log(`Kanban directory: ${ctx.absoluteKanbanDir}`);