vibora 0.1.10 → 0.1.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/server/index.js CHANGED
@@ -3101,128 +3101,6 @@ var Hono2 = class extends Hono {
3101
3101
  }
3102
3102
  };
3103
3103
 
3104
- // node_modules/hono/dist/utils/encode.js
3105
- var decodeBase64 = (str) => {
3106
- const binary = atob(str);
3107
- const bytes = new Uint8Array(new ArrayBuffer(binary.length));
3108
- const half = binary.length / 2;
3109
- for (let i = 0, j = binary.length - 1;i <= half; i++, j--) {
3110
- bytes[i] = binary.charCodeAt(i);
3111
- bytes[j] = binary.charCodeAt(j);
3112
- }
3113
- return bytes;
3114
- };
3115
-
3116
- // node_modules/hono/dist/utils/basic-auth.js
3117
- var CREDENTIALS_REGEXP = /^ *(?:[Bb][Aa][Ss][Ii][Cc]) +([A-Za-z0-9._~+/-]+=*) *$/;
3118
- var USER_PASS_REGEXP = /^([^:]*):(.*)$/;
3119
- var utf8Decoder = new TextDecoder;
3120
- var auth = (req) => {
3121
- const match2 = CREDENTIALS_REGEXP.exec(req.headers.get("Authorization") || "");
3122
- if (!match2) {
3123
- return;
3124
- }
3125
- let userPass = undefined;
3126
- try {
3127
- userPass = USER_PASS_REGEXP.exec(utf8Decoder.decode(decodeBase64(match2[1])));
3128
- } catch {}
3129
- if (!userPass) {
3130
- return;
3131
- }
3132
- return { username: userPass[1], password: userPass[2] };
3133
- };
3134
-
3135
- // node_modules/hono/dist/utils/crypto.js
3136
- var sha256 = async (data) => {
3137
- const algorithm = { name: "SHA-256", alias: "sha256" };
3138
- const hash = await createHash(data, algorithm);
3139
- return hash;
3140
- };
3141
- var createHash = async (data, algorithm) => {
3142
- let sourceBuffer;
3143
- if (ArrayBuffer.isView(data) || data instanceof ArrayBuffer) {
3144
- sourceBuffer = data;
3145
- } else {
3146
- if (typeof data === "object") {
3147
- data = JSON.stringify(data);
3148
- }
3149
- sourceBuffer = new TextEncoder().encode(String(data));
3150
- }
3151
- if (crypto && crypto.subtle) {
3152
- const buffer = await crypto.subtle.digest({
3153
- name: algorithm.name
3154
- }, sourceBuffer);
3155
- const hash = Array.prototype.map.call(new Uint8Array(buffer), (x) => ("00" + x.toString(16)).slice(-2)).join("");
3156
- return hash;
3157
- }
3158
- return null;
3159
- };
3160
-
3161
- // node_modules/hono/dist/utils/buffer.js
3162
- var timingSafeEqual = async (a, b, hashFunction) => {
3163
- if (!hashFunction) {
3164
- hashFunction = sha256;
3165
- }
3166
- const [sa, sb] = await Promise.all([hashFunction(a), hashFunction(b)]);
3167
- if (!sa || !sb) {
3168
- return false;
3169
- }
3170
- return sa === sb && a === b;
3171
- };
3172
-
3173
- // node_modules/hono/dist/middleware/basic-auth/index.js
3174
- var basicAuth = (options, ...users) => {
3175
- const usernamePasswordInOptions = "username" in options && "password" in options;
3176
- const verifyUserInOptions = "verifyUser" in options;
3177
- if (!(usernamePasswordInOptions || verifyUserInOptions)) {
3178
- throw new Error('basic auth middleware requires options for "username and password" or "verifyUser"');
3179
- }
3180
- if (!options.realm) {
3181
- options.realm = "Secure Area";
3182
- }
3183
- if (!options.invalidUserMessage) {
3184
- options.invalidUserMessage = "Unauthorized";
3185
- }
3186
- if (usernamePasswordInOptions) {
3187
- users.unshift({ username: options.username, password: options.password });
3188
- }
3189
- return async function basicAuth2(ctx, next) {
3190
- const requestUser = auth(ctx.req.raw);
3191
- if (requestUser) {
3192
- if (verifyUserInOptions) {
3193
- if (await options.verifyUser(requestUser.username, requestUser.password, ctx)) {
3194
- await next();
3195
- return;
3196
- }
3197
- } else {
3198
- for (const user of users) {
3199
- const [usernameEqual, passwordEqual] = await Promise.all([
3200
- timingSafeEqual(user.username, requestUser.username, options.hashFunction),
3201
- timingSafeEqual(user.password, requestUser.password, options.hashFunction)
3202
- ]);
3203
- if (usernameEqual && passwordEqual) {
3204
- await next();
3205
- return;
3206
- }
3207
- }
3208
- }
3209
- }
3210
- const status = 401;
3211
- const headers = {
3212
- "WWW-Authenticate": 'Basic realm="' + options.realm?.replace(/"/g, "\\\"") + '"'
3213
- };
3214
- const responseMessage = typeof options.invalidUserMessage === "function" ? await options.invalidUserMessage(ctx) : options.invalidUserMessage;
3215
- const res = typeof responseMessage === "string" ? new Response(responseMessage, { status, headers }) : new Response(JSON.stringify(responseMessage), {
3216
- status,
3217
- headers: {
3218
- ...headers,
3219
- "content-type": "application/json"
3220
- }
3221
- });
3222
- throw new HTTPException(status, { res });
3223
- };
3224
- };
3225
-
3226
3104
  // node_modules/hono/dist/middleware/cors/index.js
3227
3105
  var cors = (options) => {
3228
3106
  const defaults = {
@@ -3368,10 +3246,263 @@ var logger = (fn = console.log) => {
3368
3246
  };
3369
3247
  };
3370
3248
 
3249
+ // node_modules/hono/dist/helper/factory/index.js
3250
+ var Factory = class {
3251
+ initApp;
3252
+ #defaultAppOptions;
3253
+ constructor(init) {
3254
+ this.initApp = init?.initApp;
3255
+ this.#defaultAppOptions = init?.defaultAppOptions;
3256
+ }
3257
+ createApp = (options) => {
3258
+ const app = new Hono2(options && this.#defaultAppOptions ? { ...this.#defaultAppOptions, ...options } : options ?? this.#defaultAppOptions);
3259
+ if (this.initApp) {
3260
+ this.initApp(app);
3261
+ }
3262
+ return app;
3263
+ };
3264
+ createMiddleware = (middleware) => middleware;
3265
+ createHandlers = (...handlers) => {
3266
+ return handlers.filter((handler) => handler !== undefined);
3267
+ };
3268
+ };
3269
+ var createMiddleware = (middleware) => middleware;
3270
+
3271
+ // node_modules/hono/dist/utils/cookie.js
3272
+ var algorithm = { name: "HMAC", hash: "SHA-256" };
3273
+ var getCryptoKey = async (secret) => {
3274
+ const secretBuf = typeof secret === "string" ? new TextEncoder().encode(secret) : secret;
3275
+ return await crypto.subtle.importKey("raw", secretBuf, algorithm, false, ["sign", "verify"]);
3276
+ };
3277
+ var makeSignature = async (value, secret) => {
3278
+ const key = await getCryptoKey(secret);
3279
+ const signature = await crypto.subtle.sign(algorithm.name, key, new TextEncoder().encode(value));
3280
+ return btoa(String.fromCharCode(...new Uint8Array(signature)));
3281
+ };
3282
+ var verifySignature = async (base64Signature, value, secret) => {
3283
+ try {
3284
+ const signatureBinStr = atob(base64Signature);
3285
+ const signature = new Uint8Array(signatureBinStr.length);
3286
+ for (let i = 0, len = signatureBinStr.length;i < len; i++) {
3287
+ signature[i] = signatureBinStr.charCodeAt(i);
3288
+ }
3289
+ return await crypto.subtle.verify(algorithm, secret, signature, new TextEncoder().encode(value));
3290
+ } catch {
3291
+ return false;
3292
+ }
3293
+ };
3294
+ var validCookieNameRegEx = /^[\w!#$%&'*.^`|~+-]+$/;
3295
+ var validCookieValueRegEx = /^[ !#-:<-[\]-~]*$/;
3296
+ var parse = (cookie, name) => {
3297
+ if (name && cookie.indexOf(name) === -1) {
3298
+ return {};
3299
+ }
3300
+ const pairs = cookie.trim().split(";");
3301
+ const parsedCookie = {};
3302
+ for (let pairStr of pairs) {
3303
+ pairStr = pairStr.trim();
3304
+ const valueStartPos = pairStr.indexOf("=");
3305
+ if (valueStartPos === -1) {
3306
+ continue;
3307
+ }
3308
+ const cookieName = pairStr.substring(0, valueStartPos).trim();
3309
+ if (name && name !== cookieName || !validCookieNameRegEx.test(cookieName)) {
3310
+ continue;
3311
+ }
3312
+ let cookieValue = pairStr.substring(valueStartPos + 1).trim();
3313
+ if (cookieValue.startsWith('"') && cookieValue.endsWith('"')) {
3314
+ cookieValue = cookieValue.slice(1, -1);
3315
+ }
3316
+ if (validCookieValueRegEx.test(cookieValue)) {
3317
+ parsedCookie[cookieName] = cookieValue.indexOf("%") !== -1 ? tryDecode(cookieValue, decodeURIComponent_) : cookieValue;
3318
+ if (name) {
3319
+ break;
3320
+ }
3321
+ }
3322
+ }
3323
+ return parsedCookie;
3324
+ };
3325
+ var parseSigned = async (cookie, secret, name) => {
3326
+ const parsedCookie = {};
3327
+ const secretKey = await getCryptoKey(secret);
3328
+ for (const [key, value] of Object.entries(parse(cookie, name))) {
3329
+ const signatureStartPos = value.lastIndexOf(".");
3330
+ if (signatureStartPos < 1) {
3331
+ continue;
3332
+ }
3333
+ const signedValue = value.substring(0, signatureStartPos);
3334
+ const signature = value.substring(signatureStartPos + 1);
3335
+ if (signature.length !== 44 || !signature.endsWith("=")) {
3336
+ continue;
3337
+ }
3338
+ const isVerified = await verifySignature(signature, signedValue, secretKey);
3339
+ parsedCookie[key] = isVerified ? signedValue : false;
3340
+ }
3341
+ return parsedCookie;
3342
+ };
3343
+ var _serialize = (name, value, opt = {}) => {
3344
+ let cookie = `${name}=${value}`;
3345
+ if (name.startsWith("__Secure-") && !opt.secure) {
3346
+ throw new Error("__Secure- Cookie must have Secure attributes");
3347
+ }
3348
+ if (name.startsWith("__Host-")) {
3349
+ if (!opt.secure) {
3350
+ throw new Error("__Host- Cookie must have Secure attributes");
3351
+ }
3352
+ if (opt.path !== "/") {
3353
+ throw new Error('__Host- Cookie must have Path attributes with "/"');
3354
+ }
3355
+ if (opt.domain) {
3356
+ throw new Error("__Host- Cookie must not have Domain attributes");
3357
+ }
3358
+ }
3359
+ if (opt && typeof opt.maxAge === "number" && opt.maxAge >= 0) {
3360
+ if (opt.maxAge > 34560000) {
3361
+ throw new Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");
3362
+ }
3363
+ cookie += `; Max-Age=${opt.maxAge | 0}`;
3364
+ }
3365
+ if (opt.domain && opt.prefix !== "host") {
3366
+ cookie += `; Domain=${opt.domain}`;
3367
+ }
3368
+ if (opt.path) {
3369
+ cookie += `; Path=${opt.path}`;
3370
+ }
3371
+ if (opt.expires) {
3372
+ if (opt.expires.getTime() - Date.now() > 34560000000) {
3373
+ throw new Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");
3374
+ }
3375
+ cookie += `; Expires=${opt.expires.toUTCString()}`;
3376
+ }
3377
+ if (opt.httpOnly) {
3378
+ cookie += "; HttpOnly";
3379
+ }
3380
+ if (opt.secure) {
3381
+ cookie += "; Secure";
3382
+ }
3383
+ if (opt.sameSite) {
3384
+ cookie += `; SameSite=${opt.sameSite.charAt(0).toUpperCase() + opt.sameSite.slice(1)}`;
3385
+ }
3386
+ if (opt.priority) {
3387
+ cookie += `; Priority=${opt.priority.charAt(0).toUpperCase() + opt.priority.slice(1)}`;
3388
+ }
3389
+ if (opt.partitioned) {
3390
+ if (!opt.secure) {
3391
+ throw new Error("Partitioned Cookie must have Secure attributes");
3392
+ }
3393
+ cookie += "; Partitioned";
3394
+ }
3395
+ return cookie;
3396
+ };
3397
+ var serialize = (name, value, opt) => {
3398
+ value = encodeURIComponent(value);
3399
+ return _serialize(name, value, opt);
3400
+ };
3401
+ var serializeSigned = async (name, value, secret, opt = {}) => {
3402
+ const signature = await makeSignature(value, secret);
3403
+ value = `${value}.${signature}`;
3404
+ value = encodeURIComponent(value);
3405
+ return _serialize(name, value, opt);
3406
+ };
3407
+
3408
+ // node_modules/hono/dist/helper/cookie/index.js
3409
+ var getCookie = (c, key, prefix) => {
3410
+ const cookie = c.req.raw.headers.get("Cookie");
3411
+ if (typeof key === "string") {
3412
+ if (!cookie) {
3413
+ return;
3414
+ }
3415
+ let finalKey = key;
3416
+ if (prefix === "secure") {
3417
+ finalKey = "__Secure-" + key;
3418
+ } else if (prefix === "host") {
3419
+ finalKey = "__Host-" + key;
3420
+ }
3421
+ const obj2 = parse(cookie, finalKey);
3422
+ return obj2[finalKey];
3423
+ }
3424
+ if (!cookie) {
3425
+ return {};
3426
+ }
3427
+ const obj = parse(cookie);
3428
+ return obj;
3429
+ };
3430
+ var getSignedCookie = async (c, secret, key, prefix) => {
3431
+ const cookie = c.req.raw.headers.get("Cookie");
3432
+ if (typeof key === "string") {
3433
+ if (!cookie) {
3434
+ return;
3435
+ }
3436
+ let finalKey = key;
3437
+ if (prefix === "secure") {
3438
+ finalKey = "__Secure-" + key;
3439
+ } else if (prefix === "host") {
3440
+ finalKey = "__Host-" + key;
3441
+ }
3442
+ const obj2 = await parseSigned(cookie, secret, finalKey);
3443
+ return obj2[finalKey];
3444
+ }
3445
+ if (!cookie) {
3446
+ return {};
3447
+ }
3448
+ const obj = await parseSigned(cookie, secret);
3449
+ return obj;
3450
+ };
3451
+ var generateCookie = (name, value, opt) => {
3452
+ let cookie;
3453
+ if (opt?.prefix === "secure") {
3454
+ cookie = serialize("__Secure-" + name, value, { path: "/", ...opt, secure: true });
3455
+ } else if (opt?.prefix === "host") {
3456
+ cookie = serialize("__Host-" + name, value, {
3457
+ ...opt,
3458
+ path: "/",
3459
+ secure: true,
3460
+ domain: undefined
3461
+ });
3462
+ } else {
3463
+ cookie = serialize(name, value, { path: "/", ...opt });
3464
+ }
3465
+ return cookie;
3466
+ };
3467
+ var setCookie = (c, name, value, opt) => {
3468
+ const cookie = generateCookie(name, value, opt);
3469
+ c.header("Set-Cookie", cookie, { append: true });
3470
+ };
3471
+ var generateSignedCookie = async (name, value, secret, opt) => {
3472
+ let cookie;
3473
+ if (opt?.prefix === "secure") {
3474
+ cookie = await serializeSigned("__Secure-" + name, value, secret, {
3475
+ path: "/",
3476
+ ...opt,
3477
+ secure: true
3478
+ });
3479
+ } else if (opt?.prefix === "host") {
3480
+ cookie = await serializeSigned("__Host-" + name, value, secret, {
3481
+ ...opt,
3482
+ path: "/",
3483
+ secure: true,
3484
+ domain: undefined
3485
+ });
3486
+ } else {
3487
+ cookie = await serializeSigned(name, value, secret, { path: "/", ...opt });
3488
+ }
3489
+ return cookie;
3490
+ };
3491
+ var setSignedCookie = async (c, name, value, secret, opt) => {
3492
+ const cookie = await generateSignedCookie(name, value, secret, opt);
3493
+ c.header("set-cookie", cookie, { append: true });
3494
+ };
3495
+ var deleteCookie = (c, name, opt) => {
3496
+ const deletedCookie = getCookie(c, name, opt?.prefix);
3497
+ setCookie(c, name, "", { ...opt, maxAge: 0 });
3498
+ return deletedCookie;
3499
+ };
3500
+
3371
3501
  // server/lib/settings.ts
3372
3502
  import * as fs from "fs";
3373
3503
  import * as path from "path";
3374
3504
  import * as os from "os";
3505
+ import * as crypto3 from "crypto";
3375
3506
  var DEFAULT_SETTINGS = {
3376
3507
  port: 3333,
3377
3508
  defaultGitReposDir: os.homedir(),
@@ -3477,6 +3608,13 @@ function getSettings() {
3477
3608
  function getSetting(key) {
3478
3609
  return getSettings()[key];
3479
3610
  }
3611
+ function getSessionSecret() {
3612
+ const settings = getSettings();
3613
+ if (!settings.basicAuthPassword) {
3614
+ return null;
3615
+ }
3616
+ return crypto3.createHash("sha256").update(settings.basicAuthPassword + "vibora-session").digest("hex");
3617
+ }
3480
3618
  function updateSettings(updates) {
3481
3619
  ensureViboraDir();
3482
3620
  const current = getSettings();
@@ -3542,6 +3680,44 @@ function updateNotificationSettings(updates) {
3542
3680
  return updated;
3543
3681
  }
3544
3682
 
3683
+ // server/middleware/auth.ts
3684
+ var SESSION_COOKIE_NAME = "vibora_session";
3685
+ var PUBLIC_PATHS = ["/health", "/api/auth/login", "/api/auth/check"];
3686
+ var sessionAuthMiddleware = createMiddleware(async (c, next) => {
3687
+ const settings = getSettings();
3688
+ if (!settings.basicAuthUsername || !settings.basicAuthPassword) {
3689
+ return next();
3690
+ }
3691
+ const path2 = c.req.path;
3692
+ if (PUBLIC_PATHS.some((p) => path2 === p || path2.startsWith(p + "/"))) {
3693
+ return next();
3694
+ }
3695
+ const secret = getSessionSecret();
3696
+ if (secret) {
3697
+ const sessionCookie = await getSignedCookie(c, secret, SESSION_COOKIE_NAME);
3698
+ if (sessionCookie) {
3699
+ try {
3700
+ const session = JSON.parse(sessionCookie);
3701
+ if (session.exp && session.exp > Date.now()) {
3702
+ return next();
3703
+ }
3704
+ } catch {}
3705
+ }
3706
+ }
3707
+ const authHeader = c.req.header("Authorization");
3708
+ if (authHeader?.startsWith("Basic ")) {
3709
+ const base64Credentials = authHeader.slice(6);
3710
+ try {
3711
+ const credentials = atob(base64Credentials);
3712
+ const [username, password] = credentials.split(":");
3713
+ if (username === settings.basicAuthUsername && password === settings.basicAuthPassword) {
3714
+ return next();
3715
+ }
3716
+ } catch {}
3717
+ }
3718
+ throw new HTTPException(401, { message: "Unauthorized" });
3719
+ });
3720
+
3545
3721
  // server/app.ts
3546
3722
  import { readFile } from "fs/promises";
3547
3723
  import { join as join11 } from "path";
@@ -7439,7 +7615,7 @@ function drizzle(...params) {
7439
7615
  })(drizzle || (drizzle = {}));
7440
7616
 
7441
7617
  // node_modules/drizzle-orm/migrator.js
7442
- import crypto3 from "crypto";
7618
+ import crypto4 from "crypto";
7443
7619
  import fs2 from "fs";
7444
7620
  function readMigrationFiles(config) {
7445
7621
  const migrationFolderTo = config.migrationsFolder;
@@ -7461,7 +7637,7 @@ function readMigrationFiles(config) {
7461
7637
  sql: result,
7462
7638
  bps: journalEntry.breakpoints,
7463
7639
  folderMillis: journalEntry.when,
7464
- hash: crypto3.createHash("sha256").update(query).digest("hex")
7640
+ hash: crypto4.createHash("sha256").update(query).digest("hex")
7465
7641
  });
7466
7642
  } catch {
7467
7643
  throw new Error(`No file ${migrationPath} found in ${migrationFolderTo} folder`);
@@ -138191,6 +138367,37 @@ app3.post("/merge-to-main", async (c) => {
138191
138367
  error: "Failed to determine worktree branch"
138192
138368
  }, 500);
138193
138369
  }
138370
+ try {
138371
+ const worktreeStatus = gitExec(worktreePath, "status --porcelain");
138372
+ if (worktreeStatus.trim()) {
138373
+ const lines = worktreeStatus.trim().split(`
138374
+ `).filter((l) => l);
138375
+ const untracked = [];
138376
+ const uncommitted = [];
138377
+ for (const line of lines) {
138378
+ const statusCode = line.substring(0, 2);
138379
+ const filename = line.substring(3);
138380
+ if (statusCode === "??") {
138381
+ untracked.push(filename);
138382
+ } else {
138383
+ uncommitted.push(filename);
138384
+ }
138385
+ }
138386
+ const messages = [];
138387
+ if (uncommitted.length > 0) {
138388
+ messages.push(`${uncommitted.length} uncommitted change(s)`);
138389
+ }
138390
+ if (untracked.length > 0) {
138391
+ messages.push(`${untracked.length} untracked file(s)`);
138392
+ }
138393
+ return c.json({
138394
+ error: `Worktree has ${messages.join(" and ")}. Please commit or stash changes before merging.`,
138395
+ hasUncommittedChanges: true,
138396
+ uncommittedFiles: uncommitted,
138397
+ untrackedFiles: untracked
138398
+ }, 409);
138399
+ }
138400
+ } catch {}
138194
138401
  const defaultBranch = getDefaultBranch(repoPath, baseBranch);
138195
138402
  let originalBranch;
138196
138403
  try {
@@ -138785,8 +138992,145 @@ app6.post("/", async (c) => {
138785
138992
  });
138786
138993
  var uploads_default = app6;
138787
138994
 
138995
+ // node_modules/hono/dist/utils/stream.js
138996
+ var StreamingApi = class {
138997
+ writer;
138998
+ encoder;
138999
+ writable;
139000
+ abortSubscribers = [];
139001
+ responseReadable;
139002
+ aborted = false;
139003
+ closed = false;
139004
+ constructor(writable, _readable) {
139005
+ this.writable = writable;
139006
+ this.writer = writable.getWriter();
139007
+ this.encoder = new TextEncoder;
139008
+ const reader = _readable.getReader();
139009
+ this.abortSubscribers.push(async () => {
139010
+ await reader.cancel();
139011
+ });
139012
+ this.responseReadable = new ReadableStream({
139013
+ async pull(controller) {
139014
+ const { done, value } = await reader.read();
139015
+ done ? controller.close() : controller.enqueue(value);
139016
+ },
139017
+ cancel: () => {
139018
+ this.abort();
139019
+ }
139020
+ });
139021
+ }
139022
+ async write(input) {
139023
+ try {
139024
+ if (typeof input === "string") {
139025
+ input = this.encoder.encode(input);
139026
+ }
139027
+ await this.writer.write(input);
139028
+ } catch {}
139029
+ return this;
139030
+ }
139031
+ async writeln(input) {
139032
+ await this.write(input + `
139033
+ `);
139034
+ return this;
139035
+ }
139036
+ sleep(ms) {
139037
+ return new Promise((res) => setTimeout(res, ms));
139038
+ }
139039
+ async close() {
139040
+ try {
139041
+ await this.writer.close();
139042
+ } catch {}
139043
+ this.closed = true;
139044
+ }
139045
+ async pipe(body) {
139046
+ this.writer.releaseLock();
139047
+ await body.pipeTo(this.writable, { preventClose: true });
139048
+ this.writer = this.writable.getWriter();
139049
+ }
139050
+ onAbort(listener) {
139051
+ this.abortSubscribers.push(listener);
139052
+ }
139053
+ abort() {
139054
+ if (!this.aborted) {
139055
+ this.aborted = true;
139056
+ this.abortSubscribers.forEach((subscriber) => subscriber());
139057
+ }
139058
+ }
139059
+ };
139060
+
139061
+ // node_modules/hono/dist/helper/streaming/utils.js
139062
+ var isOldBunVersion = () => {
139063
+ const version2 = typeof Bun !== "undefined" ? Bun.version : undefined;
139064
+ if (version2 === undefined) {
139065
+ return false;
139066
+ }
139067
+ const result = version2.startsWith("1.1") || version2.startsWith("1.0") || version2.startsWith("0.");
139068
+ isOldBunVersion = () => result;
139069
+ return result;
139070
+ };
139071
+
139072
+ // node_modules/hono/dist/helper/streaming/sse.js
139073
+ var SSEStreamingApi = class extends StreamingApi {
139074
+ constructor(writable, readable) {
139075
+ super(writable, readable);
139076
+ }
139077
+ async writeSSE(message) {
139078
+ const data = await resolveCallback(message.data, HtmlEscapedCallbackPhase.Stringify, false, {});
139079
+ const dataLines = data.split(`
139080
+ `).map((line) => {
139081
+ return `data: ${line}`;
139082
+ }).join(`
139083
+ `);
139084
+ const sseData = [
139085
+ message.event && `event: ${message.event}`,
139086
+ dataLines,
139087
+ message.id && `id: ${message.id}`,
139088
+ message.retry && `retry: ${message.retry}`
139089
+ ].filter(Boolean).join(`
139090
+ `) + `
139091
+
139092
+ `;
139093
+ await this.write(sseData);
139094
+ }
139095
+ };
139096
+ var run = async (stream2, cb, onError) => {
139097
+ try {
139098
+ await cb(stream2);
139099
+ } catch (e) {
139100
+ if (e instanceof Error && onError) {
139101
+ await onError(e, stream2);
139102
+ await stream2.writeSSE({
139103
+ event: "error",
139104
+ data: e.message
139105
+ });
139106
+ } else {
139107
+ console.error(e);
139108
+ }
139109
+ } finally {
139110
+ stream2.close();
139111
+ }
139112
+ };
139113
+ var contextStash = /* @__PURE__ */ new WeakMap;
139114
+ var streamSSE = (c, cb, onError) => {
139115
+ const { readable, writable } = new TransformStream;
139116
+ const stream2 = new SSEStreamingApi(writable, readable);
139117
+ if (isOldBunVersion()) {
139118
+ c.req.raw.signal.addEventListener("abort", () => {
139119
+ if (!stream2.closed) {
139120
+ stream2.abort();
139121
+ }
139122
+ });
139123
+ }
139124
+ contextStash.set(stream2.responseReadable, c);
139125
+ c.header("Transfer-Encoding", "chunked");
139126
+ c.header("Content-Type", "text/event-stream");
139127
+ c.header("Cache-Control", "no-cache");
139128
+ c.header("Connection", "keep-alive");
139129
+ run(stream2, cb, onError);
139130
+ return c.newResponse(stream2.responseReadable);
139131
+ };
139132
+
138788
139133
  // server/routes/worktrees.ts
138789
- import { execSync as execSync4 } from "child_process";
138790
139134
  import * as fs6 from "fs";
138791
139135
  import * as path8 from "path";
138792
139136
  function formatBytes(bytes) {
@@ -138797,28 +139141,27 @@ function formatBytes(bytes) {
138797
139141
  const i = Math.floor(Math.log(bytes) / Math.log(k));
138798
139142
  return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
138799
139143
  }
138800
- function getDirectorySize(dirPath) {
139144
+ async function getDirectorySizeAsync(dirPath) {
138801
139145
  try {
138802
139146
  const platform = process.platform;
138803
- if (platform === "darwin") {
138804
- const output = execSync4(`du -sk "${dirPath}" 2>/dev/null`, { encoding: "utf-8" });
138805
- const sizeKb = parseInt(output.split("\t")[0], 10);
138806
- return sizeKb * 1024;
138807
- } else {
138808
- const output = execSync4(`du -sb "${dirPath}" 2>/dev/null`, { encoding: "utf-8" });
138809
- return parseInt(output.split("\t")[0], 10);
138810
- }
139147
+ const cmd = platform === "darwin" ? ["du", "-sk", dirPath] : ["du", "-sb", dirPath];
139148
+ const proc2 = Bun.spawn(cmd, { stdout: "pipe", stderr: "pipe" });
139149
+ const output = await new Response(proc2.stdout).text();
139150
+ const sizeValue = parseInt(output.split("\t")[0], 10);
139151
+ return platform === "darwin" ? sizeValue * 1024 : sizeValue;
138811
139152
  } catch {
138812
139153
  return 0;
138813
139154
  }
138814
139155
  }
138815
- function getGitBranch(gitPath) {
139156
+ async function getGitBranchAsync(gitPath) {
138816
139157
  try {
138817
- const branch = execSync4("git rev-parse --abbrev-ref HEAD", {
139158
+ const proc2 = Bun.spawn(["git", "rev-parse", "--abbrev-ref", "HEAD"], {
138818
139159
  cwd: gitPath,
138819
- encoding: "utf-8"
138820
- }).trim();
138821
- return branch;
139160
+ stdout: "pipe",
139161
+ stderr: "pipe"
139162
+ });
139163
+ const output = await new Response(proc2.stdout).text();
139164
+ return output.trim() || "unknown";
138822
139165
  } catch {
138823
139166
  return "unknown";
138824
139167
  }
@@ -138834,91 +139177,131 @@ function destroyTerminalsForWorktree2(worktreePath) {
138834
139177
  }
138835
139178
  } catch {}
138836
139179
  }
138837
- function deleteWorktree(worktreePath, repoPath) {
139180
+ async function deleteWorktree(worktreePath, repoPath) {
138838
139181
  if (!fs6.existsSync(worktreePath))
138839
139182
  return;
138840
139183
  if (repoPath && fs6.existsSync(repoPath)) {
138841
139184
  try {
138842
- execSync4(`git worktree remove "${worktreePath}" --force`, {
139185
+ const proc2 = Bun.spawn(["git", "worktree", "remove", worktreePath, "--force"], {
138843
139186
  cwd: repoPath,
138844
- encoding: "utf-8"
139187
+ stdout: "pipe",
139188
+ stderr: "pipe"
138845
139189
  });
138846
- return;
139190
+ await proc2.exited;
139191
+ if (proc2.exitCode === 0)
139192
+ return;
138847
139193
  } catch {}
138848
139194
  }
138849
139195
  fs6.rmSync(worktreePath, { recursive: true, force: true });
138850
139196
  if (repoPath && fs6.existsSync(repoPath)) {
138851
139197
  try {
138852
- execSync4("git worktree prune", { cwd: repoPath, encoding: "utf-8" });
139198
+ Bun.spawn(["git", "worktree", "prune"], { cwd: repoPath });
138853
139199
  } catch {}
138854
139200
  }
138855
139201
  }
138856
139202
  var app7 = new Hono2;
138857
139203
  app7.get("/", (c) => {
138858
- const worktreeBasePath = getWorktreeBasePath();
138859
- if (!fs6.existsSync(worktreeBasePath)) {
138860
- const response2 = {
138861
- worktrees: [],
138862
- summary: {
138863
- total: 0,
138864
- orphaned: 0,
138865
- totalSize: 0,
138866
- totalSizeFormatted: "0 B"
139204
+ return streamSSE(c, async (stream3) => {
139205
+ const worktreeBasePath = getWorktreeBasePath();
139206
+ if (!fs6.existsSync(worktreeBasePath)) {
139207
+ await stream3.writeSSE({
139208
+ event: "worktree:basic",
139209
+ data: JSON.stringify([])
139210
+ });
139211
+ await stream3.writeSSE({
139212
+ event: "worktree:complete",
139213
+ data: JSON.stringify({
139214
+ total: 0,
139215
+ orphaned: 0,
139216
+ totalSize: 0,
139217
+ totalSizeFormatted: "0 B"
139218
+ })
139219
+ });
139220
+ return;
139221
+ }
139222
+ const allTasks = db.select().from(tasks).all();
139223
+ const worktreeToTask = new Map;
139224
+ for (const task of allTasks) {
139225
+ if (task.worktreePath) {
139226
+ worktreeToTask.set(task.worktreePath, task);
138867
139227
  }
138868
- };
138869
- return c.json(response2);
138870
- }
138871
- const allTasks = db.select().from(tasks).all();
138872
- const worktreeToTask = new Map;
138873
- for (const task of allTasks) {
138874
- if (task.worktreePath) {
138875
- worktreeToTask.set(task.worktreePath, task);
138876
139228
  }
138877
- }
138878
- const entries = fs6.readdirSync(worktreeBasePath, { withFileTypes: true });
138879
- const worktrees = [];
138880
- for (const entry of entries) {
138881
- if (!entry.isDirectory())
138882
- continue;
138883
- const fullPath = path8.join(worktreeBasePath, entry.name);
138884
- const gitPath = path8.join(fullPath, ".git");
138885
- if (!fs6.existsSync(gitPath))
138886
- continue;
138887
- const size = getDirectorySize(fullPath);
138888
- const branch = getGitBranch(fullPath);
138889
- const stats = fs6.statSync(fullPath);
138890
- const linkedTask = worktreeToTask.get(fullPath);
138891
- worktrees.push({
138892
- path: fullPath,
138893
- name: entry.name,
138894
- size,
138895
- sizeFormatted: formatBytes(size),
138896
- branch,
138897
- lastModified: stats.mtime.toISOString(),
138898
- isOrphaned: !linkedTask,
138899
- taskId: linkedTask?.id,
138900
- taskTitle: linkedTask?.title,
138901
- repoPath: linkedTask?.repoPath
139229
+ const entries = fs6.readdirSync(worktreeBasePath, { withFileTypes: true });
139230
+ const basicWorktrees = [];
139231
+ const pathsToProcess = [];
139232
+ for (const entry of entries) {
139233
+ if (!entry.isDirectory())
139234
+ continue;
139235
+ const fullPath = path8.join(worktreeBasePath, entry.name);
139236
+ const gitPath = path8.join(fullPath, ".git");
139237
+ if (!fs6.existsSync(gitPath))
139238
+ continue;
139239
+ const stats = fs6.statSync(fullPath);
139240
+ const linkedTask = worktreeToTask.get(fullPath);
139241
+ basicWorktrees.push({
139242
+ path: fullPath,
139243
+ name: entry.name,
139244
+ lastModified: stats.mtime.toISOString(),
139245
+ isOrphaned: !linkedTask,
139246
+ taskId: linkedTask?.id,
139247
+ taskTitle: linkedTask?.title,
139248
+ taskStatus: linkedTask?.status,
139249
+ repoPath: linkedTask?.repoPath
139250
+ });
139251
+ pathsToProcess.push(fullPath);
139252
+ }
139253
+ basicWorktrees.sort((a, b) => {
139254
+ if (a.isOrphaned !== b.isOrphaned) {
139255
+ return a.isOrphaned ? -1 : 1;
139256
+ }
139257
+ return new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime();
138902
139258
  });
138903
- }
138904
- worktrees.sort((a, b) => {
138905
- if (a.isOrphaned !== b.isOrphaned) {
138906
- return a.isOrphaned ? -1 : 1;
139259
+ await stream3.writeSSE({
139260
+ event: "worktree:basic",
139261
+ data: JSON.stringify(basicWorktrees)
139262
+ });
139263
+ let totalSize = 0;
139264
+ const CONCURRENCY = 4;
139265
+ async function processWorktree(fullPath) {
139266
+ try {
139267
+ const [size, branch] = await Promise.all([
139268
+ getDirectorySizeAsync(fullPath),
139269
+ getGitBranchAsync(fullPath)
139270
+ ]);
139271
+ totalSize += size;
139272
+ await stream3.writeSSE({
139273
+ event: "worktree:details",
139274
+ data: JSON.stringify({
139275
+ path: fullPath,
139276
+ size,
139277
+ sizeFormatted: formatBytes(size),
139278
+ branch
139279
+ })
139280
+ });
139281
+ } catch (error) {
139282
+ await stream3.writeSSE({
139283
+ event: "worktree:error",
139284
+ data: JSON.stringify({
139285
+ path: fullPath,
139286
+ error: error instanceof Error ? error.message : "Unknown error"
139287
+ })
139288
+ });
139289
+ }
138907
139290
  }
138908
- return new Date(b.lastModified).getTime() - new Date(a.lastModified).getTime();
138909
- });
138910
- const totalSize = worktrees.reduce((sum, w) => sum + w.size, 0);
138911
- const orphanedCount = worktrees.filter((w) => w.isOrphaned).length;
138912
- const response = {
138913
- worktrees,
138914
- summary: {
138915
- total: worktrees.length,
138916
- orphaned: orphanedCount,
138917
- totalSize,
138918
- totalSizeFormatted: formatBytes(totalSize)
139291
+ for (let i = 0;i < pathsToProcess.length; i += CONCURRENCY) {
139292
+ const batch = pathsToProcess.slice(i, i + CONCURRENCY);
139293
+ await Promise.all(batch.map(processWorktree));
138919
139294
  }
138920
- };
138921
- return c.json(response);
139295
+ await stream3.writeSSE({
139296
+ event: "worktree:complete",
139297
+ data: JSON.stringify({
139298
+ total: basicWorktrees.length,
139299
+ orphaned: basicWorktrees.filter((w) => w.isOrphaned).length,
139300
+ totalSize,
139301
+ totalSizeFormatted: formatBytes(totalSize)
139302
+ })
139303
+ });
139304
+ });
138922
139305
  });
138923
139306
  app7.delete("/", async (c) => {
138924
139307
  try {
@@ -138936,7 +139319,7 @@ app7.delete("/", async (c) => {
138936
139319
  }
138937
139320
  const linkedTask = db.select().from(tasks).where(eq(tasks.worktreePath, body.worktreePath)).get();
138938
139321
  destroyTerminalsForWorktree2(body.worktreePath);
138939
- deleteWorktree(body.worktreePath, body.repoPath || linkedTask?.repoPath);
139322
+ await deleteWorktree(body.worktreePath, body.repoPath || linkedTask?.repoPath);
138940
139323
  let deletedTaskId;
138941
139324
  if (linkedTask) {
138942
139325
  const columnTasks = db.select().from(tasks).where(eq(tasks.status, linkedTask.status)).all();
@@ -139446,7 +139829,7 @@ function expand2(template, context) {
139446
139829
  return template.replace(/\/$/, "");
139447
139830
  }
139448
139831
  }
139449
- function parse(options) {
139832
+ function parse2(options) {
139450
139833
  let method = options.method.toUpperCase();
139451
139834
  let url = (options.url || "/").replace(/:([a-z]\w+)/g, "{$1}");
139452
139835
  let headers = Object.assign({}, options.headers);
@@ -139501,7 +139884,7 @@ function parse(options) {
139501
139884
  return Object.assign({ method, url, headers }, typeof body !== "undefined" ? { body } : null, options.request ? { request: options.request } : null);
139502
139885
  }
139503
139886
  function endpointWithDefaults(defaults2, route, options) {
139504
- return parse(merge(defaults2, route, options));
139887
+ return parse2(merge(defaults2, route, options));
139505
139888
  }
139506
139889
  function withDefaults(oldDefaults, newDefaults) {
139507
139890
  const DEFAULTS2 = merge(oldDefaults, newDefaults);
@@ -139510,7 +139893,7 @@ function withDefaults(oldDefaults, newDefaults) {
139510
139893
  DEFAULTS: DEFAULTS2,
139511
139894
  defaults: withDefaults.bind(null, DEFAULTS2),
139512
139895
  merge: merge.bind(null, DEFAULTS2),
139513
- parse
139896
+ parse: parse2
139514
139897
  });
139515
139898
  }
139516
139899
  var endpoint = withDefaults(null, DEFAULTS);
@@ -139861,7 +140244,7 @@ var b64url = "(?:[a-zA-Z0-9_-]+)";
139861
140244
  var sep3 = "\\.";
139862
140245
  var jwtRE = new RegExp(`^${b64url}${sep3}${b64url}${sep3}${b64url}$`);
139863
140246
  var isJWT = jwtRE.test.bind(jwtRE);
139864
- async function auth2(token) {
140247
+ async function auth(token) {
139865
140248
  const isApp = isJWT(token);
139866
140249
  const isInstallation = token.startsWith("v1.") || token.startsWith("ghs_");
139867
140250
  const isUserToServer = token.startsWith("ghu_");
@@ -139891,7 +140274,7 @@ var createTokenAuth = function createTokenAuth2(token) {
139891
140274
  throw new Error("[@octokit/auth-token] Token passed to createTokenAuth is not a string");
139892
140275
  }
139893
140276
  token = token.replace(/^(token|bearer) +/i, "");
139894
- return Object.assign(auth2.bind(null, token), {
140277
+ return Object.assign(auth.bind(null, token), {
139895
140278
  hook: hook.bind(null, token)
139896
140279
  });
139897
140280
  };
@@ -139978,20 +140361,20 @@ class Octokit {
139978
140361
  type: "unauthenticated"
139979
140362
  });
139980
140363
  } else {
139981
- const auth3 = createTokenAuth(options.auth);
139982
- hook2.wrap("request", auth3.hook);
139983
- this.auth = auth3;
140364
+ const auth2 = createTokenAuth(options.auth);
140365
+ hook2.wrap("request", auth2.hook);
140366
+ this.auth = auth2;
139984
140367
  }
139985
140368
  } else {
139986
140369
  const { authStrategy, ...otherOptions } = options;
139987
- const auth3 = authStrategy(Object.assign({
140370
+ const auth2 = authStrategy(Object.assign({
139988
140371
  request: this.request,
139989
140372
  log: this.log,
139990
140373
  octokit: this,
139991
140374
  octokitOptions: otherOptions
139992
140375
  }, options.auth));
139993
- hook2.wrap("request", auth3.hook);
139994
- this.auth = auth3;
140376
+ hook2.wrap("request", auth2.hook);
140377
+ this.auth = auth2;
139995
140378
  }
139996
140379
  const classConstructor = this.constructor;
139997
140380
  for (let i = 0;i < classConstructor.plugins.length; ++i) {
@@ -142816,6 +143199,59 @@ app11.get("/prs", async (c) => {
142816
143199
  });
142817
143200
  var github_default = app11;
142818
143201
 
143202
+ // server/routes/auth.ts
143203
+ var SESSION_COOKIE_NAME2 = "vibora_session";
143204
+ var SESSION_EXPIRY_MS = 14 * 24 * 60 * 60 * 1000;
143205
+ var app12 = new Hono2;
143206
+ app12.post("/login", async (c) => {
143207
+ const { username, password } = await c.req.json();
143208
+ const settings = getSettings();
143209
+ if (!settings.basicAuthUsername || !settings.basicAuthPassword) {
143210
+ return c.json({ error: "Authentication not configured" }, 500);
143211
+ }
143212
+ if (username !== settings.basicAuthUsername || password !== settings.basicAuthPassword) {
143213
+ return c.json({ error: "Invalid credentials" }, 401);
143214
+ }
143215
+ const secret = getSessionSecret();
143216
+ if (!secret) {
143217
+ return c.json({ error: "Session secret not available" }, 500);
143218
+ }
143219
+ const expiry = Date.now() + SESSION_EXPIRY_MS;
143220
+ const sessionData = JSON.stringify({ exp: expiry });
143221
+ await setSignedCookie(c, SESSION_COOKIE_NAME2, sessionData, secret, {
143222
+ path: "/",
143223
+ httpOnly: true,
143224
+ sameSite: "Strict",
143225
+ maxAge: SESSION_EXPIRY_MS / 1000
143226
+ });
143227
+ return c.json({ success: true, expiresAt: new Date(expiry).toISOString() });
143228
+ });
143229
+ app12.post("/logout", async (c) => {
143230
+ deleteCookie(c, SESSION_COOKIE_NAME2, { path: "/" });
143231
+ return c.json({ success: true });
143232
+ });
143233
+ app12.get("/check", async (c) => {
143234
+ const settings = getSettings();
143235
+ if (!settings.basicAuthUsername || !settings.basicAuthPassword) {
143236
+ return c.json({ authRequired: false, authenticated: true });
143237
+ }
143238
+ const secret = getSessionSecret();
143239
+ if (!secret) {
143240
+ return c.json({ authRequired: true, authenticated: false });
143241
+ }
143242
+ const sessionCookie = await getSignedCookie(c, secret, SESSION_COOKIE_NAME2);
143243
+ if (sessionCookie) {
143244
+ try {
143245
+ const session = JSON.parse(sessionCookie);
143246
+ if (session.exp && session.exp > Date.now()) {
143247
+ return c.json({ authRequired: true, authenticated: true });
143248
+ }
143249
+ } catch {}
143250
+ }
143251
+ return c.json({ authRequired: true, authenticated: false });
143252
+ });
143253
+ var auth_default = app12;
143254
+
142819
143255
  // server/app.ts
142820
143256
  function getDistPath() {
142821
143257
  if (process.env.VIBORA_PACKAGE_ROOT) {
@@ -142824,31 +143260,26 @@ function getDistPath() {
142824
143260
  return join11(process.cwd(), "dist");
142825
143261
  }
142826
143262
  function createApp() {
142827
- const app12 = new Hono2;
142828
- app12.use("*", logger());
142829
- app12.use("*", cors({
143263
+ const app13 = new Hono2;
143264
+ app13.use("*", logger());
143265
+ app13.use("*", cors({
142830
143266
  origin: "*",
142831
143267
  allowMethods: ["GET", "POST", "PATCH", "PUT", "DELETE", "OPTIONS"],
142832
143268
  allowHeaders: ["Content-Type", "Authorization"]
142833
143269
  }));
142834
- const settings = getSettings();
142835
- if (settings.basicAuthUsername && settings.basicAuthPassword) {
142836
- app12.use("*", basicAuth({
142837
- username: settings.basicAuthUsername,
142838
- password: settings.basicAuthPassword
142839
- }));
142840
- }
142841
- app12.route("/health", health_default);
142842
- app12.route("/api/tasks", tasks_default);
142843
- app12.route("/api/git", git_default);
142844
- app12.route("/api/fs", filesystem_default);
142845
- app12.route("/api/config", config_default);
142846
- app12.route("/api/uploads", uploads_default);
142847
- app12.route("/api/worktrees", worktrees_default);
142848
- app12.route("/api/terminal-view-state", terminal_view_state_default);
142849
- app12.route("/api/repositories", repositories_default);
142850
- app12.route("/api/linear", linear_default);
142851
- app12.route("/api/github", github_default);
143270
+ app13.use("*", sessionAuthMiddleware);
143271
+ app13.route("/health", health_default);
143272
+ app13.route("/api/tasks", tasks_default);
143273
+ app13.route("/api/git", git_default);
143274
+ app13.route("/api/fs", filesystem_default);
143275
+ app13.route("/api/config", config_default);
143276
+ app13.route("/api/uploads", uploads_default);
143277
+ app13.route("/api/worktrees", worktrees_default);
143278
+ app13.route("/api/terminal-view-state", terminal_view_state_default);
143279
+ app13.route("/api/repositories", repositories_default);
143280
+ app13.route("/api/linear", linear_default);
143281
+ app13.route("/api/github", github_default);
143282
+ app13.route("/api/auth", auth_default);
142852
143283
  if (process.env.VIBORA_PACKAGE_ROOT) {
142853
143284
  const distPath = getDistPath();
142854
143285
  const serveFile = async (filePath) => {
@@ -142871,7 +143302,7 @@ function createApp() {
142871
143302
  headers: { "Content-Type": mimeTypes[ext2 || ""] || "application/octet-stream" }
142872
143303
  });
142873
143304
  };
142874
- app12.get("/assets/*", async (c) => {
143305
+ app13.get("/assets/*", async (c) => {
142875
143306
  const assetPath = join11(distPath, c.req.path);
142876
143307
  if (existsSync10(assetPath)) {
142877
143308
  return serveFile(assetPath);
@@ -142880,7 +143311,7 @@ function createApp() {
142880
143311
  });
142881
143312
  const staticFiles = ["favicon.ico", "vibora-icon.png", "vibora-logo.jpeg", "vite.svg"];
142882
143313
  for (const file of staticFiles) {
142883
- app12.get(`/${file}`, async () => {
143314
+ app13.get(`/${file}`, async () => {
142884
143315
  const filePath = join11(distPath, file);
142885
143316
  if (existsSync10(filePath)) {
142886
143317
  return serveFile(filePath);
@@ -142888,7 +143319,7 @@ function createApp() {
142888
143319
  return new Response("Not Found", { status: 404 });
142889
143320
  });
142890
143321
  }
142891
- app12.get("*", async (c, next) => {
143322
+ app13.get("*", async (c, next) => {
142892
143323
  const path9 = c.req.path;
142893
143324
  if (path9.startsWith("/api/") || path9.startsWith("/ws/") || path9 === "/health") {
142894
143325
  return next();
@@ -142897,11 +143328,11 @@ function createApp() {
142897
143328
  return c.html(html);
142898
143329
  });
142899
143330
  }
142900
- return app12;
143331
+ return app13;
142901
143332
  }
142902
143333
 
142903
143334
  // server/services/pr-monitor.ts
142904
- import { execSync as execSync5 } from "child_process";
143335
+ import { execSync as execSync4 } from "child_process";
142905
143336
  var POLL_INTERVAL = 60000;
142906
143337
  function parsePrUrl(url) {
142907
143338
  const match3 = url.match(/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/);
@@ -142916,7 +143347,7 @@ function checkPrStatus(prUrl) {
142916
143347
  return null;
142917
143348
  }
142918
143349
  try {
142919
- const output = execSync5(`gh pr view ${parsed.number} --repo ${parsed.owner}/${parsed.repo} --json state,mergedAt`, { encoding: "utf-8", timeout: 1e4, stdio: ["pipe", "pipe", "pipe"] });
143350
+ const output = execSync4(`gh pr view ${parsed.number} --repo ${parsed.owner}/${parsed.repo} --json state,mergedAt`, { encoding: "utf-8", timeout: 1e4, stdio: ["pipe", "pipe", "pipe"] });
142920
143351
  const data = JSON.parse(output);
142921
143352
  return {
142922
143353
  state: data.state,
@@ -142983,11 +143414,11 @@ setBroadcastDestroyed((terminalId) => {
142983
143414
  payload: { terminalId }
142984
143415
  });
142985
143416
  });
142986
- var app12 = createApp();
142987
- var { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: app12 });
142988
- app12.get("/ws/terminal", upgradeWebSocket(() => terminalWebSocketHandlers));
143417
+ var app13 = createApp();
143418
+ var { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: app13 });
143419
+ app13.get("/ws/terminal", upgradeWebSocket(() => terminalWebSocketHandlers));
142989
143420
  var server = serve({
142990
- fetch: app12.fetch,
143421
+ fetch: app13.fetch,
142991
143422
  port: PORT,
142992
143423
  hostname: "0.0.0.0"
142993
143424
  }, (info) => {