@hasna/domains 0.0.46 → 0.0.47
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/README.md +1 -1
- package/dist/cli/index.js +413 -158
- package/dist/db/database.d.ts +5 -3
- package/dist/db/database.d.ts.map +1 -1
- package/dist/index.js +340 -104
- package/dist/lib/app-home.d.ts +60 -0
- package/dist/lib/app-home.d.ts.map +1 -0
- package/dist/lib/config.d.ts +4 -3
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/mcp/index.js +360 -124
- package/dist/sdk/index.js +93 -15
- package/dist/server/migrations.d.ts +35 -0
- package/dist/server/migrations.d.ts.map +1 -1
- package/package.json +5 -3
- package/postinstall.js +42 -0
package/dist/index.js
CHANGED
|
@@ -316,22 +316,129 @@ var init_migrations = __esm(() => {
|
|
|
316
316
|
];
|
|
317
317
|
});
|
|
318
318
|
|
|
319
|
+
// ../../node_modules/.bun/@hasna+paths@0.1.0/node_modules/@hasna/paths/dist/index.js
|
|
320
|
+
import { homedir } from "os";
|
|
321
|
+
import { join as join2 } from "path";
|
|
322
|
+
function assertApp(app) {
|
|
323
|
+
if (typeof app !== "string" || app.length === 0) {
|
|
324
|
+
throw new TypeError("paths: app must be a non-empty string");
|
|
325
|
+
}
|
|
326
|
+
if (!APP_SLUG_RE.test(app)) {
|
|
327
|
+
throw new TypeError(`paths: invalid app slug "${app}" \u2014 expected lowercase kebab-case ([a-z0-9]+(-[a-z0-9]+)*)`);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
function envOf(options) {
|
|
331
|
+
return options.env ?? process.env;
|
|
332
|
+
}
|
|
333
|
+
function envValue(options, kind) {
|
|
334
|
+
const value = envOf(options)[KIND_ENV[kind]];
|
|
335
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
336
|
+
}
|
|
337
|
+
function isMacOS(platform) {
|
|
338
|
+
return platform === "darwin";
|
|
339
|
+
}
|
|
340
|
+
function baseDir(kind, options) {
|
|
341
|
+
const override = envValue(options, kind);
|
|
342
|
+
if (override)
|
|
343
|
+
return override;
|
|
344
|
+
const home = options.home ?? homedir();
|
|
345
|
+
const platform = options.platform ?? process.platform;
|
|
346
|
+
if (isMacOS(platform)) {
|
|
347
|
+
switch (kind) {
|
|
348
|
+
case "config":
|
|
349
|
+
case "data":
|
|
350
|
+
return join2(home, "Library", "Application Support", "Hasna");
|
|
351
|
+
case "cache":
|
|
352
|
+
return join2(home, "Library", "Caches", "Hasna");
|
|
353
|
+
case "state":
|
|
354
|
+
return join2(home, "Library", "Logs", "Hasna");
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
switch (kind) {
|
|
358
|
+
case "config":
|
|
359
|
+
return join2(home, ".config", "hasna");
|
|
360
|
+
case "data":
|
|
361
|
+
return join2(home, ".local", "share", "hasna");
|
|
362
|
+
case "state":
|
|
363
|
+
return join2(home, ".local", "state", "hasna");
|
|
364
|
+
case "cache":
|
|
365
|
+
return join2(home, ".cache", "hasna");
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
function resolvePath(kind, options) {
|
|
369
|
+
assertApp(options.app);
|
|
370
|
+
const appSegment = options.internal === true ? join2("internal", options.app) : options.app;
|
|
371
|
+
return join2(baseDir(kind, options), appSegment);
|
|
372
|
+
}
|
|
373
|
+
function dataDir(options) {
|
|
374
|
+
return resolvePath("data", options);
|
|
375
|
+
}
|
|
376
|
+
var KIND_ENV, APP_SLUG_RE;
|
|
377
|
+
var init_dist = __esm(() => {
|
|
378
|
+
KIND_ENV = {
|
|
379
|
+
config: "HASNA_CONFIG_HOME",
|
|
380
|
+
data: "HASNA_DATA_HOME",
|
|
381
|
+
state: "HASNA_STATE_HOME",
|
|
382
|
+
cache: "HASNA_CACHE_HOME"
|
|
383
|
+
};
|
|
384
|
+
APP_SLUG_RE = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
// src/lib/app-home.ts
|
|
388
|
+
import { existsSync } from "fs";
|
|
389
|
+
import { homedir as homedir2 } from "os";
|
|
390
|
+
import { join as join3, resolve } from "path";
|
|
391
|
+
function effectiveHome(env = process.env) {
|
|
392
|
+
return env["HOME"] || env["USERPROFILE"] || homedir2();
|
|
393
|
+
}
|
|
394
|
+
function legacyHomeDir(env = process.env) {
|
|
395
|
+
return join3(effectiveHome(env), ".hasna", APP);
|
|
396
|
+
}
|
|
397
|
+
function resolverHome(env = process.env) {
|
|
398
|
+
const home = env["HOME"] || env["USERPROFILE"];
|
|
399
|
+
return dataDir({ app: APP, home, env });
|
|
400
|
+
}
|
|
401
|
+
function adoptResolverHome(resolved, env = process.env) {
|
|
402
|
+
const dataOverride = env.HASNA_DATA_HOME;
|
|
403
|
+
if (typeof dataOverride === "string" && dataOverride.trim().length > 0)
|
|
404
|
+
return true;
|
|
405
|
+
return existsSync(join3(resolved, "domains.db"));
|
|
406
|
+
}
|
|
407
|
+
function exactAppOverride(env = process.env) {
|
|
408
|
+
const override = env["HASNA_DOMAINS_HOME"] ?? env["DOMAINS_HOME"] ?? env["HASNA_DOMAINS_DIR"] ?? env["DOMAINS_DIR"];
|
|
409
|
+
return override && override.trim() ? override.trim() : undefined;
|
|
410
|
+
}
|
|
411
|
+
function appHome(env = process.env) {
|
|
412
|
+
const override = exactAppOverride(env);
|
|
413
|
+
if (override)
|
|
414
|
+
return resolve(override);
|
|
415
|
+
const resolved = resolverHome(env);
|
|
416
|
+
return adoptResolverHome(resolved, env) ? resolve(resolved) : resolve(legacyHomeDir(env));
|
|
417
|
+
}
|
|
418
|
+
function getDefaultDbPath(env = process.env) {
|
|
419
|
+
return join3(appHome(env), `${APP}.db`);
|
|
420
|
+
}
|
|
421
|
+
var APP = "domains";
|
|
422
|
+
var init_app_home = __esm(() => {
|
|
423
|
+
init_dist();
|
|
424
|
+
});
|
|
425
|
+
|
|
319
426
|
// src/db/database.ts
|
|
320
427
|
import { Database } from "bun:sqlite";
|
|
321
428
|
import { createHash } from "crypto";
|
|
322
429
|
import {
|
|
323
430
|
copyFileSync,
|
|
324
|
-
existsSync,
|
|
431
|
+
existsSync as existsSync2,
|
|
325
432
|
mkdirSync,
|
|
326
433
|
readFileSync as readFileSync2,
|
|
327
434
|
readdirSync,
|
|
328
435
|
statSync as statSync2,
|
|
329
436
|
writeFileSync
|
|
330
437
|
} from "fs";
|
|
331
|
-
import { dirname, join as
|
|
332
|
-
import { homedir } from "os";
|
|
438
|
+
import { dirname, join as join4, resolve as resolve2 } from "path";
|
|
439
|
+
import { homedir as homedir3 } from "os";
|
|
333
440
|
function canonicalHome(env) {
|
|
334
|
-
return env["HOME"] || env["USERPROFILE"] ||
|
|
441
|
+
return env["HOME"] || env["USERPROFILE"] || homedir3();
|
|
335
442
|
}
|
|
336
443
|
function sha256File(path) {
|
|
337
444
|
return createHash("sha256").update(readFileSync2(path)).digest("hex");
|
|
@@ -339,20 +446,20 @@ function sha256File(path) {
|
|
|
339
446
|
function migrateLegacyDataDir(env = process.env, dryRun = false) {
|
|
340
447
|
const report = { dryRun, wouldCopy: [], copied: [] };
|
|
341
448
|
const home = canonicalHome(env);
|
|
342
|
-
const xdgData = env["XDG_DATA_HOME"]?.trim() ||
|
|
343
|
-
const oldDir =
|
|
344
|
-
const oldDb =
|
|
345
|
-
if (!
|
|
449
|
+
const xdgData = env["XDG_DATA_HOME"]?.trim() || join4(home, ".local", "share");
|
|
450
|
+
const oldDir = join4(xdgData, "open-domains");
|
|
451
|
+
const oldDb = join4(oldDir, "domains.db");
|
|
452
|
+
if (!existsSync2(oldDb))
|
|
346
453
|
return report;
|
|
347
|
-
const canonicalDir =
|
|
348
|
-
const newDb =
|
|
349
|
-
if (
|
|
454
|
+
const canonicalDir = join4(home, ".hasna", "domains");
|
|
455
|
+
const newDb = join4(canonicalDir, "domains.db");
|
|
456
|
+
if (existsSync2(newDb))
|
|
350
457
|
return report;
|
|
351
|
-
if (
|
|
458
|
+
if (existsSync2(join4(canonicalDir, ".migrated-from-xdg.receipt.json")))
|
|
352
459
|
return report;
|
|
353
460
|
if (dryRun) {
|
|
354
461
|
for (const name of ["domains.db", "domains.db-wal", "domains.db-shm"]) {
|
|
355
|
-
if (
|
|
462
|
+
if (existsSync2(join4(oldDir, name)) && !existsSync2(join4(canonicalDir, name))) {
|
|
356
463
|
report.wouldCopy.push(name);
|
|
357
464
|
}
|
|
358
465
|
}
|
|
@@ -361,11 +468,11 @@ function migrateLegacyDataDir(env = process.env, dryRun = false) {
|
|
|
361
468
|
mkdirSync(canonicalDir, { recursive: true });
|
|
362
469
|
const copied = [];
|
|
363
470
|
for (const name of ["domains.db", "domains.db-wal", "domains.db-shm"]) {
|
|
364
|
-
const from =
|
|
365
|
-
if (!
|
|
471
|
+
const from = join4(oldDir, name);
|
|
472
|
+
if (!existsSync2(from))
|
|
366
473
|
continue;
|
|
367
|
-
const to =
|
|
368
|
-
if (
|
|
474
|
+
const to = join4(canonicalDir, name);
|
|
475
|
+
if (existsSync2(to))
|
|
369
476
|
continue;
|
|
370
477
|
copyFileSync(from, to);
|
|
371
478
|
copied.push({ name, bytes: statSync2(to).size, sha256: sha256File(to) });
|
|
@@ -374,7 +481,7 @@ function migrateLegacyDataDir(env = process.env, dryRun = false) {
|
|
|
374
481
|
if (statSync2(newDb).size !== statSync2(oldDb).size || sha256File(newDb) !== sha256File(oldDb)) {
|
|
375
482
|
throw new Error(`Refusing migration: copied ${newDb} does not byte-match ${oldDb}; the canonical root was not populated.`);
|
|
376
483
|
}
|
|
377
|
-
writeFileSync(
|
|
484
|
+
writeFileSync(join4(canonicalDir, ".migrated-from-xdg.receipt.json"), `${JSON.stringify({
|
|
378
485
|
migratedAt: new Date().toISOString(),
|
|
379
486
|
from: oldDir,
|
|
380
487
|
to: canonicalDir,
|
|
@@ -388,26 +495,26 @@ function getDbPath(env = process.env) {
|
|
|
388
495
|
return env["DOMAINS_DB_PATH"];
|
|
389
496
|
if (env["HASNA_DOMAINS_DB_PATH"])
|
|
390
497
|
return env["HASNA_DOMAINS_DB_PATH"];
|
|
391
|
-
const explicit = env
|
|
498
|
+
const explicit = exactAppOverride(env);
|
|
392
499
|
if (explicit) {
|
|
393
|
-
return
|
|
500
|
+
return join4(explicit, "domains.db");
|
|
394
501
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
return
|
|
502
|
+
if (!adoptResolverHome(resolverHome(env), env)) {
|
|
503
|
+
migrateLegacyDataDir(env);
|
|
504
|
+
migrateDotfile("domains", legacyHomeDir(env), env);
|
|
505
|
+
}
|
|
506
|
+
return getDefaultDbPath(env);
|
|
400
507
|
}
|
|
401
508
|
function migrateDotfile(name, newDir, env) {
|
|
402
509
|
const home = canonicalHome(env);
|
|
403
|
-
const oldDir =
|
|
404
|
-
if (!
|
|
510
|
+
const oldDir = join4(home, `.${name}`);
|
|
511
|
+
if (!existsSync2(oldDir) || existsSync2(newDir))
|
|
405
512
|
return;
|
|
406
513
|
mkdirSync(newDir, { recursive: true });
|
|
407
514
|
for (const file of readdirSync(oldDir)) {
|
|
408
|
-
const oldPath =
|
|
515
|
+
const oldPath = join4(oldDir, file);
|
|
409
516
|
if (statSync2(oldPath).isFile())
|
|
410
|
-
copyFileSync(oldPath,
|
|
517
|
+
copyFileSync(oldPath, join4(newDir, file));
|
|
411
518
|
}
|
|
412
519
|
}
|
|
413
520
|
function getDatabase() {
|
|
@@ -415,7 +522,7 @@ function getDatabase() {
|
|
|
415
522
|
return _db;
|
|
416
523
|
const dbPath = getDbPath();
|
|
417
524
|
if (dbPath !== ":memory:") {
|
|
418
|
-
const dir = dirname(
|
|
525
|
+
const dir = dirname(resolve2(dbPath));
|
|
419
526
|
mkdirSync(dir, { recursive: true });
|
|
420
527
|
}
|
|
421
528
|
_db = new Database(dbPath);
|
|
@@ -448,6 +555,7 @@ function getDatabase() {
|
|
|
448
555
|
var _db = null;
|
|
449
556
|
var init_database = __esm(() => {
|
|
450
557
|
init_migrations();
|
|
558
|
+
init_app_home();
|
|
451
559
|
});
|
|
452
560
|
|
|
453
561
|
// src/db/domain-records.ts
|
|
@@ -2163,7 +2271,7 @@ var require_client = __commonJS((exports) => {
|
|
|
2163
2271
|
};
|
|
2164
2272
|
};
|
|
2165
2273
|
var sleep = (seconds) => {
|
|
2166
|
-
return new Promise((
|
|
2274
|
+
return new Promise((resolve4) => setTimeout(resolve4, seconds * 1000));
|
|
2167
2275
|
};
|
|
2168
2276
|
var waiterServiceDefaults = {
|
|
2169
2277
|
minDelay: 2,
|
|
@@ -2292,8 +2400,8 @@ var require_client = __commonJS((exports) => {
|
|
|
2292
2400
|
};
|
|
2293
2401
|
var abortTimeout = (abortSignal) => {
|
|
2294
2402
|
let onAbort;
|
|
2295
|
-
const promise = new Promise((
|
|
2296
|
-
onAbort = () =>
|
|
2403
|
+
const promise = new Promise((resolve4) => {
|
|
2404
|
+
onAbort = () => resolve4({ state: WaiterState.ABORTED });
|
|
2297
2405
|
if (typeof abortSignal.addEventListener === "function") {
|
|
2298
2406
|
abortSignal.addEventListener("abort", onAbort);
|
|
2299
2407
|
} else {
|
|
@@ -2946,8 +3054,8 @@ var require_client = __commonJS((exports) => {
|
|
|
2946
3054
|
|
|
2947
3055
|
// ../../node_modules/.bun/@smithy+core@3.33.2/node_modules/@smithy/core/dist-cjs/submodules/config/index.js
|
|
2948
3056
|
var require_config = __commonJS((exports) => {
|
|
2949
|
-
var { homedir:
|
|
2950
|
-
var { sep, join:
|
|
3057
|
+
var { homedir: homedir4 } = __require("os");
|
|
3058
|
+
var { sep, join: join5 } = __require("path");
|
|
2951
3059
|
var { createHash: createHash2 } = __require("crypto");
|
|
2952
3060
|
var { readFile: readFile$1 } = __require("fs/promises");
|
|
2953
3061
|
var { IniSectionType } = require_dist_cjs();
|
|
@@ -3096,7 +3204,7 @@ var require_config = __commonJS((exports) => {
|
|
|
3096
3204
|
return `${HOMEDRIVE}${HOMEPATH}`;
|
|
3097
3205
|
const homeDirCacheKey = getHomeDirCacheKey();
|
|
3098
3206
|
if (!homeDirCache[homeDirCacheKey])
|
|
3099
|
-
homeDirCache[homeDirCacheKey] =
|
|
3207
|
+
homeDirCache[homeDirCacheKey] = homedir4();
|
|
3100
3208
|
return homeDirCache[homeDirCacheKey];
|
|
3101
3209
|
};
|
|
3102
3210
|
var ENV_PROFILE = "AWS_PROFILE";
|
|
@@ -3105,7 +3213,7 @@ var require_config = __commonJS((exports) => {
|
|
|
3105
3213
|
var getSSOTokenFilepath = (id) => {
|
|
3106
3214
|
const hasher = createHash2("sha1");
|
|
3107
3215
|
const cacheName = hasher.update(id).digest("hex");
|
|
3108
|
-
return
|
|
3216
|
+
return join5(getHomeDir(), ".aws", "sso", "cache", `${cacheName}.json`);
|
|
3109
3217
|
};
|
|
3110
3218
|
var tokenIntercept = {};
|
|
3111
3219
|
var getSSOTokenFromFile = async (id) => {
|
|
@@ -3132,9 +3240,9 @@ var require_config = __commonJS((exports) => {
|
|
|
3132
3240
|
...data.default && { default: data.default }
|
|
3133
3241
|
});
|
|
3134
3242
|
var ENV_CONFIG_PATH = "AWS_CONFIG_FILE";
|
|
3135
|
-
var getConfigFilepath = () => process.env[ENV_CONFIG_PATH] ||
|
|
3243
|
+
var getConfigFilepath = () => process.env[ENV_CONFIG_PATH] || join5(getHomeDir(), ".aws", "config");
|
|
3136
3244
|
var ENV_CREDENTIALS_PATH = "AWS_SHARED_CREDENTIALS_FILE";
|
|
3137
|
-
var getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] ||
|
|
3245
|
+
var getCredentialsFilepath = () => process.env[ENV_CREDENTIALS_PATH] || join5(getHomeDir(), ".aws", "credentials");
|
|
3138
3246
|
var prefixKeyRegex = /^([\w-]+)\s(["'])?([\w-@+.%:/]+)\2$/;
|
|
3139
3247
|
var profileNameBlockList = ["__proto__", "profile __proto__"];
|
|
3140
3248
|
var parseIni = (iniData) => {
|
|
@@ -3200,11 +3308,11 @@ var require_config = __commonJS((exports) => {
|
|
|
3200
3308
|
const relativeHomeDirPrefix = "~/";
|
|
3201
3309
|
let resolvedFilepath = filepath;
|
|
3202
3310
|
if (filepath.startsWith(relativeHomeDirPrefix)) {
|
|
3203
|
-
resolvedFilepath =
|
|
3311
|
+
resolvedFilepath = join5(homeDir2, filepath.slice(2));
|
|
3204
3312
|
}
|
|
3205
3313
|
let resolvedConfigFilepath = configFilepath;
|
|
3206
3314
|
if (configFilepath.startsWith(relativeHomeDirPrefix)) {
|
|
3207
|
-
resolvedConfigFilepath =
|
|
3315
|
+
resolvedConfigFilepath = join5(homeDir2, configFilepath.slice(2));
|
|
3208
3316
|
}
|
|
3209
3317
|
const parsedFiles = await Promise.all([
|
|
3210
3318
|
readFile(resolvedConfigFilepath, {
|
|
@@ -3421,7 +3529,7 @@ var require_config = __commonJS((exports) => {
|
|
|
3421
3529
|
};
|
|
3422
3530
|
var imdsRequest = async (options) => {
|
|
3423
3531
|
const { request } = __require("http");
|
|
3424
|
-
return new Promise((
|
|
3532
|
+
return new Promise((resolve4, reject) => {
|
|
3425
3533
|
const req = request({
|
|
3426
3534
|
hostname: options.hostname,
|
|
3427
3535
|
port: options.port,
|
|
@@ -3449,7 +3557,7 @@ var require_config = __commonJS((exports) => {
|
|
|
3449
3557
|
const chunks = [];
|
|
3450
3558
|
res.on("data", (chunk) => chunks.push(chunk));
|
|
3451
3559
|
res.on("end", () => {
|
|
3452
|
-
|
|
3560
|
+
resolve4(Buffer.concat(chunks));
|
|
3453
3561
|
req.destroy();
|
|
3454
3562
|
});
|
|
3455
3563
|
});
|
|
@@ -5800,7 +5908,7 @@ ${value}\r
|
|
|
5800
5908
|
if (isReadableStream(stream)) {
|
|
5801
5909
|
return headStream$1(stream, bytes);
|
|
5802
5910
|
}
|
|
5803
|
-
return new Promise((
|
|
5911
|
+
return new Promise((resolve4, reject) => {
|
|
5804
5912
|
const collector = new Collector$1;
|
|
5805
5913
|
collector.limit = bytes;
|
|
5806
5914
|
stream.pipe(collector);
|
|
@@ -5811,7 +5919,7 @@ ${value}\r
|
|
|
5811
5919
|
collector.on("error", reject);
|
|
5812
5920
|
collector.on("finish", function() {
|
|
5813
5921
|
const bytes2 = concatBytes(this.buffers);
|
|
5814
|
-
|
|
5922
|
+
resolve4(bytes2);
|
|
5815
5923
|
});
|
|
5816
5924
|
});
|
|
5817
5925
|
};
|
|
@@ -5925,7 +6033,7 @@ ${value}\r
|
|
|
5925
6033
|
if (isReadableStream(stream)) {
|
|
5926
6034
|
return collectReadableStream(stream);
|
|
5927
6035
|
}
|
|
5928
|
-
return new Promise((
|
|
6036
|
+
return new Promise((resolve4, reject) => {
|
|
5929
6037
|
const collector = new Collector;
|
|
5930
6038
|
const nodeStream = stream;
|
|
5931
6039
|
nodeStream.pipe(collector);
|
|
@@ -5936,7 +6044,7 @@ ${value}\r
|
|
|
5936
6044
|
collector.on("error", reject);
|
|
5937
6045
|
collector.on("finish", function() {
|
|
5938
6046
|
const bytes = concatBytes(this.bufferedBytes);
|
|
5939
|
-
|
|
6047
|
+
resolve4(bytes);
|
|
5940
6048
|
});
|
|
5941
6049
|
});
|
|
5942
6050
|
};
|
|
@@ -6128,7 +6236,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
6128
6236
|
callback();
|
|
6129
6237
|
}
|
|
6130
6238
|
}
|
|
6131
|
-
var fileStreamHasher = (hashCtor, fileStream) => new Promise((
|
|
6239
|
+
var fileStreamHasher = (hashCtor, fileStream) => new Promise((resolve4, reject) => {
|
|
6132
6240
|
if (!isReadStream(fileStream)) {
|
|
6133
6241
|
reject(new Error("Unable to calculate hash for non-file streams."));
|
|
6134
6242
|
return;
|
|
@@ -6146,7 +6254,7 @@ var require_checksum = __commonJS((exports) => {
|
|
|
6146
6254
|
});
|
|
6147
6255
|
hashCalculator.on("error", reject);
|
|
6148
6256
|
hashCalculator.on("finish", function() {
|
|
6149
|
-
hash.digest().then(
|
|
6257
|
+
hash.digest().then(resolve4).catch(reject);
|
|
6150
6258
|
});
|
|
6151
6259
|
});
|
|
6152
6260
|
var isReadStream = (stream) => typeof stream.path === "string";
|
|
@@ -6157,14 +6265,14 @@ var require_checksum = __commonJS((exports) => {
|
|
|
6157
6265
|
const hash = new hashCtor;
|
|
6158
6266
|
const hashCalculator = new HashCalculator(hash);
|
|
6159
6267
|
readableStream.pipe(hashCalculator);
|
|
6160
|
-
return new Promise((
|
|
6268
|
+
return new Promise((resolve4, reject) => {
|
|
6161
6269
|
readableStream.on("error", (err) => {
|
|
6162
6270
|
hashCalculator.end();
|
|
6163
6271
|
reject(err);
|
|
6164
6272
|
});
|
|
6165
6273
|
hashCalculator.on("error", reject);
|
|
6166
6274
|
hashCalculator.on("finish", () => {
|
|
6167
|
-
hash.digest().then(
|
|
6275
|
+
hash.digest().then(resolve4).catch(reject);
|
|
6168
6276
|
});
|
|
6169
6277
|
});
|
|
6170
6278
|
};
|
|
@@ -7270,7 +7378,7 @@ var require_event_streams = __commonJS((exports) => {
|
|
|
7270
7378
|
streamEnded = true;
|
|
7271
7379
|
});
|
|
7272
7380
|
while (!generationEnded) {
|
|
7273
|
-
const value = await new Promise((
|
|
7381
|
+
const value = await new Promise((resolve4) => setTimeout(() => resolve4(records.shift()), 0));
|
|
7274
7382
|
if (value) {
|
|
7275
7383
|
yield value;
|
|
7276
7384
|
}
|
|
@@ -8150,8 +8258,8 @@ var require_protocols = __commonJS((exports) => {
|
|
|
8150
8258
|
async build() {
|
|
8151
8259
|
const { hostname, protocol = "https", port, path: basePath } = await this.context.endpoint();
|
|
8152
8260
|
this.path = basePath;
|
|
8153
|
-
for (const
|
|
8154
|
-
|
|
8261
|
+
for (const resolvePath2 of this.resolvePathStack) {
|
|
8262
|
+
resolvePath2(this.path);
|
|
8155
8263
|
}
|
|
8156
8264
|
return new HttpRequest({
|
|
8157
8265
|
protocol,
|
|
@@ -8765,7 +8873,7 @@ var require_retry = __commonJS((exports) => {
|
|
|
8765
8873
|
}
|
|
8766
8874
|
};
|
|
8767
8875
|
}
|
|
8768
|
-
var cooldown = (ms) => new Promise((
|
|
8876
|
+
var cooldown = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
8769
8877
|
var isRetryStrategyV2 = (retryStrategy) => typeof retryStrategy.acquireInitialRetryToken !== "undefined" && typeof retryStrategy.refreshRetryTokenForRetry !== "undefined" && typeof retryStrategy.recordSuccess !== "undefined";
|
|
8770
8878
|
var getRetryErrorInfo = (error, logger) => {
|
|
8771
8879
|
const errorInfo = {
|
|
@@ -8864,7 +8972,7 @@ var require_retry = __commonJS((exports) => {
|
|
|
8864
8972
|
this.refillTokenBucket();
|
|
8865
8973
|
while (amount > this.availableTokens) {
|
|
8866
8974
|
const delay = (amount - this.availableTokens) / this.fillRate * 1000;
|
|
8867
|
-
await new Promise((
|
|
8975
|
+
await new Promise((resolve4) => DefaultRateLimiter.setTimeoutFn(resolve4, delay));
|
|
8868
8976
|
this.refillTokenBucket();
|
|
8869
8977
|
}
|
|
8870
8978
|
this.availableTokens = this.availableTokens - amount;
|
|
@@ -9206,7 +9314,7 @@ var require_retry = __commonJS((exports) => {
|
|
|
9206
9314
|
const delayFromResponse = getDelayFromRetryAfterHeader(err.$response);
|
|
9207
9315
|
const delay = Math.max(delayFromResponse || 0, delayFromDecider);
|
|
9208
9316
|
totalDelay += delay;
|
|
9209
|
-
await new Promise((
|
|
9317
|
+
await new Promise((resolve4) => setTimeout(resolve4, delay));
|
|
9210
9318
|
continue;
|
|
9211
9319
|
}
|
|
9212
9320
|
if (!err.$metadata) {
|
|
@@ -12539,7 +12647,7 @@ var init_node_http = () => {};
|
|
|
12539
12647
|
|
|
12540
12648
|
// ../../node_modules/.bun/@smithy+credential-provider-imds@4.5.2/node_modules/@smithy/credential-provider-imds/dist-es/remoteProvider/httpRequest.js
|
|
12541
12649
|
function httpRequest(options) {
|
|
12542
|
-
return new Promise((
|
|
12650
|
+
return new Promise((resolve4, reject) => {
|
|
12543
12651
|
const req = node_http.request({
|
|
12544
12652
|
method: "GET",
|
|
12545
12653
|
...options,
|
|
@@ -12564,7 +12672,7 @@ function httpRequest(options) {
|
|
|
12564
12672
|
chunks.push(chunk);
|
|
12565
12673
|
});
|
|
12566
12674
|
res.on("end", () => {
|
|
12567
|
-
|
|
12675
|
+
resolve4(Buffer.concat(chunks));
|
|
12568
12676
|
req.destroy();
|
|
12569
12677
|
});
|
|
12570
12678
|
});
|
|
@@ -12788,9 +12896,9 @@ var import_config6, IMDS_PATH = "/latest/meta-data/iam/security-credentials/", I
|
|
|
12788
12896
|
let fallbackBlockedFromProcessEnv = false;
|
|
12789
12897
|
const configValue = await import_config6.loadConfig({
|
|
12790
12898
|
environmentVariableSelector: (env) => {
|
|
12791
|
-
const
|
|
12792
|
-
fallbackBlockedFromProcessEnv = !!
|
|
12793
|
-
if (
|
|
12899
|
+
const envValue2 = env[AWS_EC2_METADATA_V1_DISABLED];
|
|
12900
|
+
fallbackBlockedFromProcessEnv = !!envValue2 && envValue2 !== "false";
|
|
12901
|
+
if (envValue2 === undefined) {
|
|
12794
12902
|
throw new import_config6.CredentialsProviderError(`${AWS_EC2_METADATA_V1_DISABLED} not set in env, checking config file next.`, { logger: init.logger });
|
|
12795
12903
|
}
|
|
12796
12904
|
return fallbackBlockedFromProcessEnv;
|
|
@@ -13058,21 +13166,21 @@ var require_dist_cjs4 = __commonJS((exports) => {
|
|
|
13058
13166
|
let sendBody = true;
|
|
13059
13167
|
if (!externalAgent && expect === "100-continue") {
|
|
13060
13168
|
sendBody = await Promise.race([
|
|
13061
|
-
new Promise((
|
|
13062
|
-
timeoutId = Number(timing.setTimeout(() =>
|
|
13169
|
+
new Promise((resolve4) => {
|
|
13170
|
+
timeoutId = Number(timing.setTimeout(() => resolve4(true), Math.max(MIN_WAIT_TIME, maxContinueTimeoutMs)));
|
|
13063
13171
|
}),
|
|
13064
|
-
new Promise((
|
|
13172
|
+
new Promise((resolve4) => {
|
|
13065
13173
|
httpRequest2.on("continue", () => {
|
|
13066
13174
|
timing.clearTimeout(timeoutId);
|
|
13067
|
-
|
|
13175
|
+
resolve4(true);
|
|
13068
13176
|
});
|
|
13069
13177
|
httpRequest2.on("response", () => {
|
|
13070
13178
|
timing.clearTimeout(timeoutId);
|
|
13071
|
-
|
|
13179
|
+
resolve4(false);
|
|
13072
13180
|
});
|
|
13073
13181
|
httpRequest2.on("error", () => {
|
|
13074
13182
|
timing.clearTimeout(timeoutId);
|
|
13075
|
-
|
|
13183
|
+
resolve4(false);
|
|
13076
13184
|
});
|
|
13077
13185
|
})
|
|
13078
13186
|
]);
|
|
@@ -13147,13 +13255,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
13147
13255
|
return socketWarningTimestamp;
|
|
13148
13256
|
}
|
|
13149
13257
|
constructor(options) {
|
|
13150
|
-
this.configProvider = new Promise((
|
|
13258
|
+
this.configProvider = new Promise((resolve4, reject) => {
|
|
13151
13259
|
if (typeof options === "function") {
|
|
13152
13260
|
options().then((_options) => {
|
|
13153
|
-
|
|
13261
|
+
resolve4(this.resolveDefaultConfig(_options));
|
|
13154
13262
|
}).catch(reject);
|
|
13155
13263
|
} else {
|
|
13156
|
-
|
|
13264
|
+
resolve4(this.resolveDefaultConfig(options));
|
|
13157
13265
|
}
|
|
13158
13266
|
});
|
|
13159
13267
|
}
|
|
@@ -13185,7 +13293,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
13185
13293
|
timing.clearTimeout(socketTimeoutId);
|
|
13186
13294
|
timing.clearTimeout(keepAliveTimeoutId);
|
|
13187
13295
|
};
|
|
13188
|
-
const
|
|
13296
|
+
const resolve4 = async (arg) => {
|
|
13189
13297
|
await writeRequestBodyPromise;
|
|
13190
13298
|
clearTimeouts();
|
|
13191
13299
|
_resolve(arg);
|
|
@@ -13249,7 +13357,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
13249
13357
|
headers: getTransformedHeaders(res.headers),
|
|
13250
13358
|
body: res
|
|
13251
13359
|
});
|
|
13252
|
-
|
|
13360
|
+
resolve4({ response: httpResponse });
|
|
13253
13361
|
});
|
|
13254
13362
|
req.on("error", (err) => {
|
|
13255
13363
|
if (NODEJS_TIMEOUT_ERROR_CODES.includes(err.code)) {
|
|
@@ -13581,13 +13689,13 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
13581
13689
|
return new NodeHttp2Handler(instanceOrOptions);
|
|
13582
13690
|
}
|
|
13583
13691
|
constructor(options) {
|
|
13584
|
-
this.configProvider = new Promise((
|
|
13692
|
+
this.configProvider = new Promise((resolve4, reject) => {
|
|
13585
13693
|
if (typeof options === "function") {
|
|
13586
13694
|
options().then((opts) => {
|
|
13587
|
-
|
|
13695
|
+
resolve4(opts || {});
|
|
13588
13696
|
}).catch(reject);
|
|
13589
13697
|
} else {
|
|
13590
|
-
|
|
13698
|
+
resolve4(options || {});
|
|
13591
13699
|
}
|
|
13592
13700
|
});
|
|
13593
13701
|
}
|
|
@@ -13612,7 +13720,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
13612
13720
|
return new Promise((_resolve, _reject) => {
|
|
13613
13721
|
let fulfilled = false;
|
|
13614
13722
|
let writeRequestBodyPromise = undefined;
|
|
13615
|
-
const
|
|
13723
|
+
const resolve4 = async (arg) => {
|
|
13616
13724
|
await writeRequestBodyPromise;
|
|
13617
13725
|
_resolve(arg);
|
|
13618
13726
|
};
|
|
@@ -13697,7 +13805,7 @@ or increase socketAcquisitionWarningTimeout=(millis) in the NodeHttpHandler conf
|
|
|
13697
13805
|
body: clientHttp2Stream
|
|
13698
13806
|
});
|
|
13699
13807
|
fulfilled = true;
|
|
13700
|
-
|
|
13808
|
+
resolve4({ response: httpResponse });
|
|
13701
13809
|
if (useIsolatedSession) {
|
|
13702
13810
|
session.close();
|
|
13703
13811
|
}
|
|
@@ -13823,7 +13931,7 @@ var retryWrapper = (toRetry, maxRetries, delayMs) => {
|
|
|
13823
13931
|
try {
|
|
13824
13932
|
return await toRetry();
|
|
13825
13933
|
} catch (e) {
|
|
13826
|
-
await new Promise((
|
|
13934
|
+
await new Promise((resolve4) => setTimeout(resolve4, delayMs));
|
|
13827
13935
|
}
|
|
13828
13936
|
}
|
|
13829
13937
|
return await toRetry();
|
|
@@ -23031,8 +23139,8 @@ var require_signin = __commonJS((exports) => {
|
|
|
23031
23139
|
// ../../node_modules/.bun/@aws-sdk+credential-provider-login@3.972.76/node_modules/@aws-sdk/credential-provider-login/dist-es/LoginCredentialsFetcher.js
|
|
23032
23140
|
import { createHash as createHash2, createPrivateKey, createPublicKey, sign } from "crypto";
|
|
23033
23141
|
import { promises as fs2 } from "fs";
|
|
23034
|
-
import { homedir as
|
|
23035
|
-
import { dirname as dirname3, join as
|
|
23142
|
+
import { homedir as homedir4 } from "os";
|
|
23143
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
23036
23144
|
var import_config20, import_protocols3, LoginCredentialsFetcher;
|
|
23037
23145
|
var init_LoginCredentialsFetcher = __esm(() => {
|
|
23038
23146
|
import_config20 = __toESM(require_config(), 1);
|
|
@@ -23199,10 +23307,10 @@ var init_LoginCredentialsFetcher = __esm(() => {
|
|
|
23199
23307
|
await fs2.writeFile(tokenFilePath, JSON.stringify(token, null, 2), "utf8");
|
|
23200
23308
|
}
|
|
23201
23309
|
getTokenFilePath() {
|
|
23202
|
-
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ??
|
|
23310
|
+
const directory = process.env.AWS_LOGIN_CACHE_DIRECTORY ?? join5(homedir4(), ".aws", "login", "cache");
|
|
23203
23311
|
const loginSessionBytes = Buffer.from(this.loginSession, "utf8");
|
|
23204
23312
|
const loginSessionSha256 = createHash2("sha256").update(loginSessionBytes).digest("hex");
|
|
23205
|
-
return
|
|
23313
|
+
return join5(directory, `${loginSessionSha256}.json`);
|
|
23206
23314
|
}
|
|
23207
23315
|
derToRawSignature(derSignature) {
|
|
23208
23316
|
let offset = 2;
|
|
@@ -23627,6 +23735,7 @@ var init_dist_es9 = __esm(() => {
|
|
|
23627
23735
|
// ../contracts/dist/client/storage.js
|
|
23628
23736
|
import { isIP } from "net";
|
|
23629
23737
|
import { readFileSync, statSync } from "fs";
|
|
23738
|
+
import { createRequire } from "module";
|
|
23630
23739
|
import { join } from "path";
|
|
23631
23740
|
function envToken(name) {
|
|
23632
23741
|
return name.toUpperCase().replace(/-/g, "_");
|
|
@@ -23642,6 +23751,9 @@ function credentialOverrideEnvKey(name) {
|
|
|
23642
23751
|
return `HASNA_${envToken(name)}_API_KEY_OVERRIDE`;
|
|
23643
23752
|
}
|
|
23644
23753
|
var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE";
|
|
23754
|
+
function credentialPointerEnvKey(name) {
|
|
23755
|
+
return `HASNA_${envToken(name)}_API_KEY_REF`;
|
|
23756
|
+
}
|
|
23645
23757
|
|
|
23646
23758
|
class CredentialResolutionError extends Error {
|
|
23647
23759
|
appName;
|
|
@@ -23654,31 +23766,55 @@ class CredentialResolutionError extends Error {
|
|
|
23654
23766
|
}
|
|
23655
23767
|
}
|
|
23656
23768
|
var HASNA_STATE_DIR = ".hasna";
|
|
23657
|
-
var FLEET_CREDENTIAL_DIR = "
|
|
23769
|
+
var FLEET_CREDENTIAL_DIR = "fleet-env";
|
|
23770
|
+
var LEGACY_CLOUD_DIR = "cloud";
|
|
23658
23771
|
var CONFIG_DIR = ".config";
|
|
23659
23772
|
var CONFIG_NAMESPACE = "hasna";
|
|
23773
|
+
var LEGACY_CLOUD_REMOVAL_DEADLINE = "2026-10-01";
|
|
23660
23774
|
var MAX_CREDENTIAL_FILE_BYTES = 64 * 1024;
|
|
23661
23775
|
var SAFE_APP_SLUG = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
23662
23776
|
var SAFE_PROFILE = /^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/;
|
|
23663
23777
|
var ILLEGAL_IN_HEADER_VALUE = /[^\t\x20-\x7e]/;
|
|
23778
|
+
var VAULT_POINTER_SHAPE = /^[a-z0-9][a-z0-9-]*(?:\/[a-z0-9][a-z0-9-_.]*){2,}$/;
|
|
23664
23779
|
function homeDir(env) {
|
|
23665
23780
|
const home = env.HOME?.trim();
|
|
23666
23781
|
return home ? home : null;
|
|
23667
23782
|
}
|
|
23668
|
-
function
|
|
23669
|
-
return profileDiskSources(name, env, null);
|
|
23670
|
-
}
|
|
23671
|
-
function profileDiskSources(name, env, profile) {
|
|
23783
|
+
function credentialDiskSourceList(name, env, profile = null) {
|
|
23672
23784
|
const home = homeDir(env);
|
|
23673
23785
|
if (!home || !SAFE_APP_SLUG.test(name))
|
|
23674
23786
|
return [];
|
|
23675
23787
|
const stem = profile ? `${name}.${profile}` : name;
|
|
23676
23788
|
const configStem = profile ? `${name}-${profile}` : name;
|
|
23677
23789
|
return [
|
|
23678
|
-
|
|
23679
|
-
|
|
23790
|
+
{
|
|
23791
|
+
path: join(home, HASNA_STATE_DIR, FLEET_CREDENTIAL_DIR, `${stem}.env`),
|
|
23792
|
+
tier: "fleet-env",
|
|
23793
|
+
deprecated: false
|
|
23794
|
+
},
|
|
23795
|
+
{
|
|
23796
|
+
path: join(home, HASNA_STATE_DIR, LEGACY_CLOUD_DIR, `${stem}.env`),
|
|
23797
|
+
tier: "legacy-cloud",
|
|
23798
|
+
deprecated: true
|
|
23799
|
+
},
|
|
23800
|
+
{
|
|
23801
|
+
path: join(home, CONFIG_DIR, CONFIG_NAMESPACE, `${configStem}.env`),
|
|
23802
|
+
tier: "config",
|
|
23803
|
+
deprecated: false
|
|
23804
|
+
},
|
|
23805
|
+
{
|
|
23806
|
+
path: join(home, CONFIG_DIR, CONFIG_NAMESPACE, `${configStem}-cloud.env`),
|
|
23807
|
+
tier: "config-legacy",
|
|
23808
|
+
deprecated: true
|
|
23809
|
+
}
|
|
23680
23810
|
];
|
|
23681
23811
|
}
|
|
23812
|
+
function credentialDiskSources(name, env) {
|
|
23813
|
+
return credentialDiskSourceList(name, env, null).map((s) => s.path);
|
|
23814
|
+
}
|
|
23815
|
+
function profileDiskSources(name, env, profile) {
|
|
23816
|
+
return credentialDiskSourceList(name, env, profile).map((s) => s.path);
|
|
23817
|
+
}
|
|
23682
23818
|
function parseEnvFile(text) {
|
|
23683
23819
|
const values = new Map;
|
|
23684
23820
|
for (const rawLine of text.split(/\r?\n/)) {
|
|
@@ -23746,6 +23882,9 @@ function appConfigDiskValue(name, env, keys) {
|
|
|
23746
23882
|
return null;
|
|
23747
23883
|
}
|
|
23748
23884
|
function assertUsableCredential(appName, source, value) {
|
|
23885
|
+
if (VAULT_POINTER_SHAPE.test(value)) {
|
|
23886
|
+
throw new CredentialResolutionError(appName, `The credential from ${source} looks like a secrets-vault pointer (a path-shaped reference like ` + `'namespace/app/live/api_key'). A vault path is NEVER accepted as a literal API key. ` + `Use ${credentialPointerEnvKey(appName)} to resolve the key through the vault, or provide the actual key value.`, [source]);
|
|
23887
|
+
}
|
|
23749
23888
|
if (!ILLEGAL_IN_HEADER_VALUE.test(value))
|
|
23750
23889
|
return;
|
|
23751
23890
|
throw new CredentialResolutionError(appName, `The credential from ${source} contains characters that cannot be sent in an HTTP header ` + `(a control character or non-ASCII byte). A file written with CR-only line endings is the usual ` + `cause. Rewrite that credential file with one LF-terminated KEY=value line. ` + `The value is not shown here, and is deliberately never logged.`, [source]);
|
|
@@ -23770,6 +23909,14 @@ function sealCredential(fields) {
|
|
|
23770
23909
|
writable: false,
|
|
23771
23910
|
configurable: false
|
|
23772
23911
|
});
|
|
23912
|
+
if (fields.pointerVaultKey !== undefined) {
|
|
23913
|
+
Object.defineProperty(sealed, "pointerVaultKey", {
|
|
23914
|
+
value: fields.pointerVaultKey,
|
|
23915
|
+
enumerable: false,
|
|
23916
|
+
writable: false,
|
|
23917
|
+
configurable: false
|
|
23918
|
+
});
|
|
23919
|
+
}
|
|
23773
23920
|
Object.defineProperty(sealed, INSPECT_CUSTOM, {
|
|
23774
23921
|
value: () => ({ ...visible, apiKey: "[redacted]" }),
|
|
23775
23922
|
enumerable: false,
|
|
@@ -23821,7 +23968,8 @@ function validateAndSealResolvedCredential(appName, credential) {
|
|
|
23821
23968
|
deliberate: credential.deliberate,
|
|
23822
23969
|
deprecated: credential.deprecated,
|
|
23823
23970
|
diskCandidates: credential.diskCandidates,
|
|
23824
|
-
warning: credential.warning
|
|
23971
|
+
warning: credential.warning,
|
|
23972
|
+
...credential.pointerVaultKey !== undefined ? { pointerVaultKey: credential.pointerVaultKey } : {}
|
|
23825
23973
|
});
|
|
23826
23974
|
}
|
|
23827
23975
|
function firstEnvValue(env, keys) {
|
|
@@ -23882,6 +24030,27 @@ function resolveCredential(name, env, options = {}) {
|
|
|
23882
24030
|
warning: null
|
|
23883
24031
|
});
|
|
23884
24032
|
}
|
|
24033
|
+
const pointerKeyName = credentialPointerEnvKey(name);
|
|
24034
|
+
const pointerRaw = env[pointerKeyName];
|
|
24035
|
+
if (pointerRaw !== undefined) {
|
|
24036
|
+
const pointer = pointerRaw.trim();
|
|
24037
|
+
if (!pointer) {
|
|
24038
|
+
throw new CredentialResolutionError(name, `${pointerKeyName} is set but empty. It is a deliberate vault pointer, so it is not resolved around: ` + `either give it a vault item key or unset it to fall back to the credential on disk.`, [pointerKeyName]);
|
|
24039
|
+
}
|
|
24040
|
+
if (!VAULT_POINTER_SHAPE.test(pointer)) {
|
|
24041
|
+
throw new CredentialResolutionError(name, `${pointerKeyName} must name a vault ITEM KEY (a path-shaped reference like ` + `'namespace/app/live/api_key'), not a credential value. A pointer that carries a literal is refused.`, [pointerKeyName]);
|
|
24042
|
+
}
|
|
24043
|
+
return sealCredential({
|
|
24044
|
+
apiKey: "",
|
|
24045
|
+
pointerVaultKey: pointer,
|
|
24046
|
+
tier: "pointer",
|
|
24047
|
+
source: pointerKeyName,
|
|
24048
|
+
deliberate: true,
|
|
24049
|
+
deprecated: false,
|
|
24050
|
+
diskCandidates: diskPaths,
|
|
24051
|
+
warning: null
|
|
24052
|
+
});
|
|
24053
|
+
}
|
|
23885
24054
|
const profile = options.profile?.trim() || env[CREDENTIAL_PROFILE_ENV_KEY]?.trim();
|
|
23886
24055
|
if (profile) {
|
|
23887
24056
|
const profileSource = options.profile?.trim() ? "explicit profile argument" : CREDENTIAL_PROFILE_ENV_KEY;
|
|
@@ -23906,26 +24075,42 @@ function resolveCredential(name, env, options = {}) {
|
|
|
23906
24075
|
}
|
|
23907
24076
|
throw new CredentialResolutionError(name, `Profile '${profile}' (from ${profileSource}) has no ${apiKeyKeys[0]} for '${name}'. ` + `Looked in: ${paths.join(", ") || "<no HOME in this environment>"}. ` + `A profile names WHICH identity to use, so it is never resolved around \u2014 ` + `create the profile's credential file or unset ${CREDENTIAL_PROFILE_ENV_KEY}.`, paths);
|
|
23908
24077
|
}
|
|
23909
|
-
const
|
|
24078
|
+
const diskSourceList = credentialDiskSourceList(name, env, null);
|
|
24079
|
+
const diskHits = diskSourceList.map((src) => ({ src, value: readCredentialFile(src.path, apiKeyKeys) })).filter((hit) => hit.value !== null);
|
|
23910
24080
|
if (diskHits.length > 0) {
|
|
23911
24081
|
const winner = diskHits[0];
|
|
23912
|
-
assertUsableCredential(name, winner.path, winner.value);
|
|
24082
|
+
assertUsableCredential(name, winner.src.path, winner.value);
|
|
23913
24083
|
const divergentSources = [
|
|
23914
|
-
...diskHits.slice(1).filter((hit) => hit.value !== winner.value).map((hit) => hit.path),
|
|
24084
|
+
...diskHits.slice(1).filter((hit) => hit.value !== winner.value).map((hit) => hit.src.path),
|
|
23915
24085
|
...(() => {
|
|
23916
24086
|
const legacyHit = firstEnvValue(env, apiKeyKeys);
|
|
23917
24087
|
return legacyHit && legacyHit.value !== winner.value ? [legacyHit.key] : [];
|
|
23918
24088
|
})()
|
|
23919
24089
|
];
|
|
23920
|
-
const warning = divergentSources.length > 0 ? `Credential sources disagree for '${name}': ${winner.path} and ` + `${divergentSources.join(", ")} hold different keys. ${winner.path} wins, because a file on ` + `disk is re-read on every call while an environment variable is a snapshot. Reconcile them \u2014 ` + `a rotation that updated only one leaves the other to fail 401 wherever it is loaded first.` : null;
|
|
24090
|
+
const warning = divergentSources.length > 0 ? `Credential sources disagree for '${name}': ${winner.src.path} and ` + `${divergentSources.join(", ")} hold different keys. ${winner.src.path} wins, because a file on ` + `disk is re-read on every call while an environment variable is a snapshot. Reconcile them \u2014 ` + `a rotation that updated only one leaves the other to fail 401 wherever it is loaded first.` : null;
|
|
24091
|
+
let deprecated = winner.src.deprecated;
|
|
24092
|
+
let finalWarning = warning;
|
|
24093
|
+
if (winner.src.deprecated) {
|
|
24094
|
+
deprecated = true;
|
|
24095
|
+
const sink = options.onDeprecation ?? defaultDeprecationSink;
|
|
24096
|
+
const notified = deprecationNotified();
|
|
24097
|
+
const noticeKey = `${name}:${winner.src.path}`;
|
|
24098
|
+
if (!notified.has(noticeKey)) {
|
|
24099
|
+
notified.add(noticeKey);
|
|
24100
|
+
const target = diskSourceList[0]?.path ?? "<none>";
|
|
24101
|
+
const message = `[${name}] DEPRECATED: the API key came from ${winner.src.path} \u2014 a legacy credential location. ` + `The primary location is ${target} (~/.hasna/fleet-env/<app>.env). The legacy 'cloud' tiers are ` + `removed after ${LEGACY_CLOUD_REMOVAL_DEADLINE}. Migrate the key to the primary location.`;
|
|
24102
|
+
sink(message);
|
|
24103
|
+
}
|
|
24104
|
+
finalWarning = [warning, `Legacy credential source: ${winner.src.path}. Removed after ${LEGACY_CLOUD_REMOVAL_DEADLINE}.`].filter(Boolean).join(" ") || null;
|
|
24105
|
+
}
|
|
23921
24106
|
return sealCredential({
|
|
23922
24107
|
apiKey: winner.value,
|
|
23923
|
-
tier:
|
|
23924
|
-
source: winner.path,
|
|
24108
|
+
tier: winner.src.tier,
|
|
24109
|
+
source: winner.src.path,
|
|
23925
24110
|
deliberate: false,
|
|
23926
|
-
deprecated
|
|
24111
|
+
deprecated,
|
|
23927
24112
|
diskCandidates: diskPaths,
|
|
23928
|
-
warning
|
|
24113
|
+
warning: finalWarning
|
|
23929
24114
|
});
|
|
23930
24115
|
}
|
|
23931
24116
|
const legacy = firstEnvValue(env, apiKeyKeys);
|
|
@@ -23951,6 +24136,47 @@ function resolveCredential(name, env, options = {}) {
|
|
|
23951
24136
|
}
|
|
23952
24137
|
return null;
|
|
23953
24138
|
}
|
|
24139
|
+
var SECRETS_PACKAGE_SPECIFIER = "@hasna/" + "secrets";
|
|
24140
|
+
var requireSecretsSdk = createRequire(import.meta.url);
|
|
24141
|
+
async function completePointerCredential(name, pointerResolution, env = process.env) {
|
|
24142
|
+
const vaultKey = pointerResolution.pointerVaultKey;
|
|
24143
|
+
const pointerEnvKey = pointerResolution.source;
|
|
24144
|
+
if (!vaultKey) {
|
|
24145
|
+
throw new CredentialResolutionError(name, `Pointer resolution from ${pointerEnvKey} carries no vault item key; this is a defect in the resolver.`, [pointerEnvKey]);
|
|
24146
|
+
}
|
|
24147
|
+
let secretsSdk;
|
|
24148
|
+
try {
|
|
24149
|
+
secretsSdk = requireSecretsSdk(SECRETS_PACKAGE_SPECIFIER);
|
|
24150
|
+
} catch {
|
|
24151
|
+
throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets SDK (@hasna/secrets) is not installed ` + `in this process. A vault pointer is TERMINAL: install @hasna/secrets to resolve it, or unset ${pointerEnvKey}.`, [pointerEnvKey]);
|
|
24152
|
+
}
|
|
24153
|
+
let client;
|
|
24154
|
+
try {
|
|
24155
|
+
client = secretsSdk.createSecretsClientFromEnv(env);
|
|
24156
|
+
} catch {
|
|
24157
|
+
throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the secrets client could not be configured from this ` + `environment (the secrets service URL and key env are missing or invalid). A vault pointer is TERMINAL and ` + `never falls through to a literal or disk credential.`, [pointerEnvKey]);
|
|
24158
|
+
}
|
|
24159
|
+
let secret;
|
|
24160
|
+
try {
|
|
24161
|
+
secret = await client.getSecret({ key: vaultKey });
|
|
24162
|
+
} catch {
|
|
24163
|
+
throw new CredentialResolutionError(name, `${pointerEnvKey} names vault item '${vaultKey}', but the vault could not be reached or the item is ` + `unavailable. A vault pointer is TERMINAL and never falls through to a literal or disk credential.`, [pointerEnvKey]);
|
|
24164
|
+
}
|
|
24165
|
+
const value = secret.value;
|
|
24166
|
+
if (!value) {
|
|
24167
|
+
throw new CredentialResolutionError(name, `${pointerEnvKey} resolved vault item '${vaultKey}', but it holds no value. A vault pointer is TERMINAL.`, [pointerEnvKey]);
|
|
24168
|
+
}
|
|
24169
|
+
assertUsableCredential(name, `${pointerEnvKey} -> vault:${vaultKey}`, value);
|
|
24170
|
+
return sealCredential({
|
|
24171
|
+
apiKey: value,
|
|
24172
|
+
tier: "pointer",
|
|
24173
|
+
source: `${pointerEnvKey} -> vault:${vaultKey}`,
|
|
24174
|
+
deliberate: true,
|
|
24175
|
+
deprecated: false,
|
|
24176
|
+
diskCandidates: pointerResolution.diskCandidates,
|
|
24177
|
+
warning: null
|
|
24178
|
+
});
|
|
24179
|
+
}
|
|
23954
24180
|
var ASCII_CONTROL_PATTERN = /[\u0000-\u001f\u007f]/;
|
|
23955
24181
|
var DNS_LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
23956
24182
|
function isValidDnsDomain(value) {
|
|
@@ -24196,6 +24422,13 @@ function currentCredential(name, apiKey) {
|
|
|
24196
24422
|
}
|
|
24197
24423
|
return explicitCredential(name, apiKey);
|
|
24198
24424
|
}
|
|
24425
|
+
async function resolveRequestCredential(name, apiKey, env = process.env) {
|
|
24426
|
+
const resolved = currentCredential(name, apiKey);
|
|
24427
|
+
if (resolved.tier === "pointer") {
|
|
24428
|
+
return completePointerCredential(name, resolved, env);
|
|
24429
|
+
}
|
|
24430
|
+
return resolved;
|
|
24431
|
+
}
|
|
24199
24432
|
function authFailureGuidance(credential) {
|
|
24200
24433
|
const origin = `The API key for this request came from ${credential.source}`;
|
|
24201
24434
|
if (credential.deliberate) {
|
|
@@ -24351,7 +24584,7 @@ function createHasnaHttpTransport(options) {
|
|
|
24351
24584
|
const retry = resolveRetry(opts.retry);
|
|
24352
24585
|
const methodRetryable = IDEMPOTENT_METHODS.has(upper) || Boolean(opts.idempotencyKey);
|
|
24353
24586
|
const maxAttempts = retry && methodRetryable ? retry.retries + 1 : 1;
|
|
24354
|
-
const credential =
|
|
24587
|
+
const credential = await resolveRequestCredential(options.name, options.apiKey);
|
|
24355
24588
|
let last = null;
|
|
24356
24589
|
for (let attempt = 1;attempt <= maxAttempts; attempt++) {
|
|
24357
24590
|
const result = await once(upper, rel, url, body, opts, credential);
|
|
@@ -24516,6 +24749,7 @@ function resolveStorageClient(name, env = process.env, overrides) {
|
|
|
24516
24749
|
}
|
|
24517
24750
|
|
|
24518
24751
|
// ../contracts/dist/client/transport.js
|
|
24752
|
+
import { createRequire as createRequire2 } from "module";
|
|
24519
24753
|
function envToken2(name) {
|
|
24520
24754
|
return name.toUpperCase().replace(/-/g, "_");
|
|
24521
24755
|
}
|
|
@@ -24530,6 +24764,8 @@ var MAX_CREDENTIAL_FILE_BYTES2 = 64 * 1024;
|
|
|
24530
24764
|
var INSPECT_CUSTOM2 = Symbol.for("nodejs.util.inspect.custom");
|
|
24531
24765
|
var CREDENTIAL_SEAL2 = Symbol.for("hasna:contracts:sealedCredential");
|
|
24532
24766
|
var DEPRECATION_REGISTRY2 = Symbol.for("hasna:contracts:credentialDeprecationNotices");
|
|
24767
|
+
var SECRETS_PACKAGE_SPECIFIER2 = "@hasna/" + "secrets";
|
|
24768
|
+
var requireSecretsSdk2 = createRequire2(import.meta.url);
|
|
24533
24769
|
var IDEMPOTENT_METHODS2 = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
|
|
24534
24770
|
var AUTHORITY_OVERRIDE_HEADERS2 = new Set([
|
|
24535
24771
|
"host",
|
|
@@ -24961,7 +25197,7 @@ function deleteDomainReputation(id) {
|
|
|
24961
25197
|
}
|
|
24962
25198
|
|
|
24963
25199
|
// src/db/store.ts
|
|
24964
|
-
var
|
|
25200
|
+
var APP2 = "domains";
|
|
24965
25201
|
var DOMAINS_PAGE_SIZE = 1000;
|
|
24966
25202
|
class LocalStore {
|
|
24967
25203
|
transport = "local";
|
|
@@ -25574,7 +25810,7 @@ function assertNoStoreConflict(env) {
|
|
|
25574
25810
|
throw new Error(`Refusing to resolve the hosted domains store while ${pathVar} is set: that variable ` + `names a local sqlite file, so the configuration asks for BOTH stores at once and ` + `nothing here can tell which you meant. Writing to the wrong one is silent \u2014 a plain ` + `\`bun run\` script that set ${pathVar} put 230 rows into the production portfolio on ` + `2026-08-07 while reporting success. Pick one: unset HASNA_DOMAINS_API_URL and ` + `HASNA_DOMAINS_API_KEY to use ${pathVar}; unset ${pathVar} to use the hosted store; or set ` + `${ALLOW_CLOUD_WITH_LOCAL_PATH}=1 if you really intend the hosted store with that variable present.`);
|
|
25575
25811
|
}
|
|
25576
25812
|
function requireHostedClient(env, flip) {
|
|
25577
|
-
const resolved = resolveStorageClient(
|
|
25813
|
+
const resolved = resolveStorageClient(APP2, withoutRetiredModeKeys(env));
|
|
25578
25814
|
if (resolved.transport !== "http") {
|
|
25579
25815
|
throw new Error(`Hosted domains client was requested (${flip.urlSource} + ${flip.keySource}) but ` + `@hasna/contracts resolved transport '${resolved.transport}'. Refusing to read the wrong dataset.`);
|
|
25580
25816
|
}
|
|
@@ -25609,7 +25845,7 @@ import { domainToASCII } from "url";
|
|
|
25609
25845
|
|
|
25610
25846
|
// src/lib/version.ts
|
|
25611
25847
|
import { readFileSync as readFileSync3 } from "fs";
|
|
25612
|
-
import { dirname as dirname2, resolve as
|
|
25848
|
+
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
25613
25849
|
import { fileURLToPath } from "url";
|
|
25614
25850
|
var cachedVersion = null;
|
|
25615
25851
|
function getPackageVersion() {
|
|
@@ -25617,7 +25853,7 @@ function getPackageVersion() {
|
|
|
25617
25853
|
return cachedVersion;
|
|
25618
25854
|
try {
|
|
25619
25855
|
const moduleDir = dirname2(fileURLToPath(import.meta.url));
|
|
25620
|
-
const packageJsonPath =
|
|
25856
|
+
const packageJsonPath = resolve3(moduleDir, "../../package.json");
|
|
25621
25857
|
const pkg = JSON.parse(readFileSync3(packageJsonPath, "utf8"));
|
|
25622
25858
|
cachedVersion = pkg.version ?? "0.0.0";
|
|
25623
25859
|
} catch {
|