@hasna/hooks 0.9.4 → 0.9.5

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/bin/serve.js CHANGED
@@ -5358,16 +5358,21 @@ function resolveHook(name) {
5358
5358
 
5359
5359
  // src/serve.ts
5360
5360
  import { readFileSync as readFileSync5 } from "fs";
5361
- import { dirname as dirname3, join as join8 } from "path";
5362
- import { fileURLToPath as fileURLToPath2 } from "url";
5361
+ import { dirname as dirname4, join as join8 } from "path";
5362
+ import { fileURLToPath as fileURLToPath5 } from "url";
5363
5363
 
5364
- // ../../node_modules/.bun/@hasna+contracts@1.0.2+e0db24ae03127387/node_modules/@hasna/contracts/dist/client/transport.js
5364
+ // ../contracts/dist/client/transport.js
5365
5365
  import { spawnSync } from "child_process";
5366
- import { closeSync, fstatSync, openSync, readFileSync as readFileSync4 } from "fs";
5367
- import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
5368
- import { createRequire } from "module";
5366
+ import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readFileSync as readFileSync22 } from "fs";
5367
+ import { O_NOFOLLOW as O_NOFOLLOW2, O_NONBLOCK as O_NONBLOCK2, O_RDONLY as O_RDONLY2 } from "constants";
5369
5368
  import { hostname as osHostname } from "os";
5370
- import { isAbsolute as isAbsolute2, join as join7 } from "path";
5369
+ import { isAbsolute as isAbsolute2, join as join22 } from "path";
5370
+ import { createRequire } from "module";
5371
+ import { fileURLToPath as fileURLToPath2 } from "url";
5372
+ import { closeSync, fstatSync, lstatSync, openSync, readFileSync as readFileSync4, realpathSync as realpathSync2, statSync } from "fs";
5373
+ import { O_NOFOLLOW, O_NONBLOCK, O_RDONLY } from "constants";
5374
+ import { basename as basename2, dirname as dirname3, join as join7, relative, sep as sep2 } from "path";
5375
+ import { fileURLToPath as fileURLToPath3, pathToFileURL } from "url";
5371
5376
  function envToken(name) {
5372
5377
  return name.toUpperCase().replace(/-/g, "_");
5373
5378
  }
@@ -5385,6 +5390,114 @@ var CREDENTIAL_PROFILE_ENV_KEY = "HASNA_PROFILE";
5385
5390
  function credentialPointerEnvKey(name) {
5386
5391
  return `HASNA_${envToken(name)}_API_KEY_REF`;
5387
5392
  }
5393
+ function e(e2, n, r) {
5394
+ throw new Error(r ? `No known conditions for "${n}" specifier in "${e2}" package` : `Missing "${n}" specifier in "${e2}" package`);
5395
+ }
5396
+ function n(n2, i, o, f) {
5397
+ let s, u, l = r(n2, o), c = function(e2) {
5398
+ let n3 = new Set(["default", ...e2.conditions || []]);
5399
+ return e2.unsafe || n3.add(e2.require ? "require" : "import"), e2.unsafe || n3.add(e2.browser ? "browser" : "node"), n3;
5400
+ }(f || {}), a = i[l];
5401
+ if (a === undefined) {
5402
+ let e2, n3, r, t;
5403
+ for (t in i)
5404
+ n3 && t.length < n3.length || (t[t.length - 1] === "/" && l.startsWith(t) ? (u = l.substring(t.length), n3 = t) : t.length > 1 && (r = t.indexOf("*", 1), ~r && (e2 = RegExp("^" + t.substring(0, r) + "(.*)" + t.substring(1 + r) + "$").exec(l), e2 && e2[1] && (u = e2[1], n3 = t))));
5405
+ a = i[n3];
5406
+ }
5407
+ return a || e(n2, l), s = t(a, c), s || e(n2, l, 1), u && function(e2, n3) {
5408
+ let r, t = 0, i2 = e2.length, o2 = /[*]/g, f2 = /[/]$/;
5409
+ for (;t < i2; t++)
5410
+ e2[t] = o2.test(r = e2[t]) ? r.replace(o2, n3) : f2.test(r) ? r + n3 : r;
5411
+ }(s, u), s;
5412
+ }
5413
+ function r(e2, n2, r2) {
5414
+ if (e2 === n2 || n2 === ".")
5415
+ return ".";
5416
+ let t = e2 + "/", i = t.length, o = n2.slice(0, i) === t, f = o ? n2.slice(i) : n2;
5417
+ return f[0] === "#" ? f : o || !r2 ? f.slice(0, 2) === "./" ? f : "./" + f : f;
5418
+ }
5419
+ function t(e2, n2, r2) {
5420
+ if (e2) {
5421
+ if (typeof e2 == "string")
5422
+ return r2 && r2.add(e2), [e2];
5423
+ let i, o;
5424
+ if (Array.isArray(e2)) {
5425
+ for (o = r2 || new Set, i = 0;i < e2.length; i++)
5426
+ t(e2[i], n2, o);
5427
+ if (!r2 && o.size)
5428
+ return [...o];
5429
+ } else
5430
+ for (i in e2)
5431
+ if (n2.has(i))
5432
+ return t(e2[i], n2, r2);
5433
+ }
5434
+ }
5435
+ function o(e2, r2, t2) {
5436
+ let i, o2 = e2.exports;
5437
+ if (o2) {
5438
+ if (typeof o2 == "string")
5439
+ o2 = { ".": o2 };
5440
+ else
5441
+ for (i in o2) {
5442
+ i[0] !== "." && (o2 = { ".": o2 });
5443
+ break;
5444
+ }
5445
+ return n(e2.name, o2, r2 || ".", t2);
5446
+ }
5447
+ }
5448
+ var PACKAGE = "@hasna/secrets";
5449
+ var MAX_PACKAGE_BYTES = 1024 * 1024;
5450
+ function entryPoint(directory) {
5451
+ const root = realpathSync2(directory);
5452
+ const fd = openSync(join7(root, "package.json"), O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
5453
+ let pkg;
5454
+ try {
5455
+ const stat = fstatSync(fd);
5456
+ if (!stat.isFile() || stat.size > MAX_PACKAGE_BYTES)
5457
+ throw new Error("Invalid Secrets package metadata");
5458
+ pkg = JSON.parse(readFileSync4(fd, "utf8"));
5459
+ } finally {
5460
+ closeSync(fd);
5461
+ }
5462
+ if (!pkg || typeof pkg !== "object" || !("name" in pkg) || pkg.name !== PACKAGE) {
5463
+ throw new Error("Invalid Secrets package identity");
5464
+ }
5465
+ const target = o(pkg, ".")?.[0];
5466
+ if (typeof target !== "string" || !target.startsWith("./"))
5467
+ throw new Error("Missing Secrets import export");
5468
+ const parts = target.slice(2).split("/");
5469
+ if (/[\\%?#\0]/.test(target) || parts.some((part) => !part || part === "." || part === ".." || part === "node_modules")) {
5470
+ throw new Error("Invalid Secrets import export");
5471
+ }
5472
+ const file = realpathSync2(join7(root, ...parts));
5473
+ const within = relative(root, file);
5474
+ if (!within || within === ".." || within.startsWith(`..${sep2}`) || !statSync(file).isFile()) {
5475
+ throw new Error("Secrets import export escapes its package or is not a file");
5476
+ }
5477
+ return pathToFileURL(file).href;
5478
+ }
5479
+ function resolveInstalledSecrets(parentUrl) {
5480
+ let directory = dirname3(fileURLToPath3(parentUrl));
5481
+ for (;; ) {
5482
+ if (basename2(directory) !== "node_modules") {
5483
+ const candidate = join7(directory, "node_modules", PACKAGE);
5484
+ let absent = false;
5485
+ try {
5486
+ lstatSync(candidate);
5487
+ } catch (error) {
5488
+ if (error.code !== "ENOENT")
5489
+ throw error;
5490
+ absent = true;
5491
+ }
5492
+ if (!absent)
5493
+ return entryPoint(candidate);
5494
+ }
5495
+ const parent = dirname3(directory);
5496
+ if (parent === directory)
5497
+ throw new Error("Secrets SDK is not installed for this consumer");
5498
+ directory = parent;
5499
+ }
5500
+ }
5388
5501
 
5389
5502
  class CredentialResolutionError extends Error {
5390
5503
  appName;
@@ -5433,14 +5546,14 @@ function hasnaHomeDir(env) {
5433
5546
  if (override)
5434
5547
  return override;
5435
5548
  const home = homeDir(env);
5436
- return home ? join7(home, HASNA_HOME_DIR) : null;
5549
+ return home ? join22(home, HASNA_HOME_DIR) : null;
5437
5550
  }
5438
5551
  function appConfigDir(name, env) {
5439
5552
  const configRoot = absoluteOverride(env, HASNA_CONFIG_HOME_ENV_KEY);
5440
5553
  if (configRoot)
5441
- return join7(configRoot, name);
5554
+ return join22(configRoot, name);
5442
5555
  const root = hasnaHomeDir(env);
5443
- return root ? join7(root, name, CONFIG_SUBDIR) : null;
5556
+ return root ? join22(root, name, CONFIG_SUBDIR) : null;
5444
5557
  }
5445
5558
  function credentialDiskSourceList(name, env, profile = null) {
5446
5559
  if (!SAFE_APP_SLUG.test(name))
@@ -5449,7 +5562,7 @@ function credentialDiskSourceList(name, env, profile = null) {
5449
5562
  if (!directory)
5450
5563
  return [];
5451
5564
  const file = profile ? `${CREDENTIALS_FILE}-${profile}` : CREDENTIALS_FILE;
5452
- return [{ path: join7(directory, file), tier: "disk" }];
5565
+ return [{ path: join22(directory, file), tier: "disk" }];
5453
5566
  }
5454
5567
  function credentialDiskSources(name, env) {
5455
5568
  return credentialDiskSourceList(name, env, null).map((s) => s.path);
@@ -5503,7 +5616,7 @@ function readAppConfigFile(path) {
5503
5616
  };
5504
5617
  let fd = -1;
5505
5618
  try {
5506
- fd = openSync(path, O_RDONLY | O_NOFOLLOW | O_NONBLOCK);
5619
+ fd = openSync2(path, O_RDONLY2 | O_NOFOLLOW2 | O_NONBLOCK2);
5507
5620
  } catch (error) {
5508
5621
  const code = error.code;
5509
5622
  if (code === "ENOENT" || code === "ENOTDIR")
@@ -5513,7 +5626,7 @@ function readAppConfigFile(path) {
5513
5626
  unsafe(`the path could not be opened (${code ?? "unknown error"})`);
5514
5627
  }
5515
5628
  try {
5516
- const before = fstatSync(fd);
5629
+ const before = fstatSync2(fd);
5517
5630
  if (!before.isFile())
5518
5631
  unsafe("the path is not a regular file");
5519
5632
  if (!configFileModeAllowed(before.mode)) {
@@ -5524,31 +5637,39 @@ function readAppConfigFile(path) {
5524
5637
  unsafe("the file is not owned by the current user");
5525
5638
  if (before.size > MAX_CREDENTIAL_FILE_BYTES)
5526
5639
  unsafe("the file exceeds the size limit");
5527
- const bytes = readFileSync4(fd);
5528
- const after = fstatSync(fd);
5640
+ const bytes = readFileSync22(fd);
5641
+ const after = fstatSync2(fd);
5529
5642
  if (!configFileReadsCoherent(before, after)) {
5530
5643
  unsafe("the file changed while being read");
5531
5644
  }
5532
5645
  return parseEnvFile(bytes.toString("utf8"));
5533
5646
  } finally {
5534
5647
  if (fd !== -1)
5535
- closeSync(fd);
5648
+ closeSync2(fd);
5536
5649
  }
5537
5650
  }
5538
- function readCredentialFile(path, apiKeyKeys) {
5651
+ function readCredentialFile(path, apiKeyKeys, pointerKey) {
5539
5652
  const parsed = readAppConfigFile(path);
5540
5653
  if (!parsed)
5541
5654
  return null;
5542
- for (const key of apiKeyKeys) {
5655
+ for (const key of [...apiKeyKeys, pointerKey]) {
5543
5656
  if (parsed.unusable.has(key)) {
5544
5657
  throw new CredentialFileUnsafeError(path, `${key} is declared but blank or malformed`);
5545
5658
  }
5546
5659
  }
5547
5660
  const values = apiKeyKeys.map((key) => parsed.values.get(key)?.trim()).filter((value) => Boolean(value));
5661
+ const pointer = parsed.values.get(pointerKey)?.trim();
5662
+ if (pointer !== undefined) {
5663
+ if (!VAULT_POINTER_SHAPE.test(pointer))
5664
+ throw new CredentialFileUnsafeError(path, `${pointerKey} must name a vault item`);
5665
+ if (values.length)
5666
+ throw new CredentialFileUnsafeError(path, "a credential file cannot select both a literal key and a vault reference");
5667
+ return { apiKey: "", pointerVaultKey: pointer };
5668
+ }
5548
5669
  if (new Set(values).size > 1) {
5549
5670
  throw new CredentialFileUnsafeError(path, "credential aliases disagree");
5550
5671
  }
5551
- return values[0] ?? null;
5672
+ return values[0] === undefined ? null : { apiKey: values[0] };
5552
5673
  }
5553
5674
  function assertUsableCredential(appName, source, value) {
5554
5675
  if (VAULT_POINTER_SHAPE.test(value)) {
@@ -5781,12 +5902,13 @@ function resolveCredential(name, env, options = {}) {
5781
5902
  }
5782
5903
  const paths = profileDiskSources(name, env, profile);
5783
5904
  for (const path of paths) {
5784
- const value = readCredentialFile(path, apiKeyKeys);
5905
+ const value = readCredentialFile(path, apiKeyKeys, pointerKeyName);
5785
5906
  if (value) {
5786
- assertUsableCredential(name, path, value);
5907
+ if (!value.pointerVaultKey)
5908
+ assertUsableCredential(name, path, value.apiKey);
5787
5909
  return sealCredential({
5788
- apiKey: value,
5789
- tier: "profile",
5910
+ ...value,
5911
+ tier: value.pointerVaultKey ? "pointer" : "profile",
5790
5912
  source: path,
5791
5913
  deliberate: true,
5792
5914
  diskCandidates: paths,
@@ -5794,7 +5916,7 @@ function resolveCredential(name, env, options = {}) {
5794
5916
  });
5795
5917
  }
5796
5918
  }
5797
- 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);
5919
+ throw new CredentialResolutionError(name, `Profile '${profile}' (from ${profileSource}) has no ${apiKeyKeys[0]} or ${pointerKeyName} 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);
5798
5920
  }
5799
5921
  const definedEnvEntries = apiKeyKeys.filter((key) => Object.prototype.hasOwnProperty.call(env, key) && env[key] !== undefined).map((key) => ({ key, value: String(env[key]).trim() }));
5800
5922
  const blankEnv = definedEnvEntries.find((entry) => entry.value.length === 0);
@@ -5819,17 +5941,27 @@ function resolveCredential(name, env, options = {}) {
5819
5941
  });
5820
5942
  }
5821
5943
  const diskSourceList = credentialDiskSourceList(name, env, null);
5822
- const diskHits = diskSourceList.map((src) => ({ src, value: readCredentialFile(src.path, apiKeyKeys) })).filter((hit) => hit.value !== null);
5944
+ const diskHits = diskSourceList.map((src) => ({ src, value: readCredentialFile(src.path, apiKeyKeys, pointerKeyName) })).filter((hit) => hit.value !== null);
5823
5945
  if (diskHits.length > 0) {
5824
5946
  const winner = diskHits[0];
5825
- assertUsableCredential(name, winner.src.path, winner.value);
5947
+ if (winner.value.pointerVaultKey) {
5948
+ return sealCredential({
5949
+ ...winner.value,
5950
+ tier: "pointer",
5951
+ source: winner.src.path,
5952
+ deliberate: false,
5953
+ diskCandidates: diskPaths,
5954
+ warning: null
5955
+ });
5956
+ }
5957
+ assertUsableCredential(name, winner.src.path, winner.value.apiKey);
5826
5958
  const divergentSources = [
5827
- ...diskHits.slice(1).filter((hit) => hit.value !== winner.value).map((hit) => hit.src.path),
5828
- ...envHit && envHit.value !== winner.value ? [envHit.key] : []
5959
+ ...diskHits.slice(1).filter((hit) => hit.value.apiKey !== winner.value.apiKey || hit.value.pointerVaultKey !== winner.value.pointerVaultKey).map((hit) => hit.src.path),
5960
+ ...envHit && envHit.value !== winner.value.apiKey ? [envHit.key] : []
5829
5961
  ];
5830
5962
  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;
5831
5963
  return sealCredential({
5832
- apiKey: winner.value,
5964
+ apiKey: winner.value.apiKey,
5833
5965
  tier: winner.src.tier,
5834
5966
  source: winner.src.path,
5835
5967
  deliberate: false,
@@ -5850,8 +5982,54 @@ function resolveCredential(name, env, options = {}) {
5850
5982
  }
5851
5983
  return null;
5852
5984
  }
5853
- var SECRETS_PACKAGE_SPECIFIER = "@hasna/" + "secrets";
5854
5985
  var requireSecretsSdk = createRequire(import.meta.url);
5986
+ async function completePointerCredential(name, pointerResolution, env = process.env) {
5987
+ const secretsEnv = snapshotClientEnvironment("secrets", env);
5988
+ const vaultKey = pointerResolution.pointerVaultKey;
5989
+ const pointerEnvKey = pointerResolution.source;
5990
+ if (!vaultKey) {
5991
+ throw new CredentialResolutionError(name, `Pointer resolution from ${pointerEnvKey} carries no vault item key; this is a defect in the resolver.`, [pointerEnvKey]);
5992
+ }
5993
+ if (name === "secrets") {
5994
+ throw new CredentialResolutionError(name, "The Secrets bootstrap credential cannot reference the same hosted vault; configure an independent bootstrap provider.", [pointerEnvKey]);
5995
+ }
5996
+ let secretsSdk;
5997
+ try {
5998
+ const sdkUrl = resolveInstalledSecrets(import.meta.url);
5999
+ secretsSdk = requireSecretsSdk(fileURLToPath2(sdkUrl));
6000
+ } catch {
6001
+ 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]);
6002
+ }
6003
+ let client;
6004
+ try {
6005
+ const bootstrap = resolveCredential("secrets", secretsEnv);
6006
+ if (!bootstrap || bootstrap.tier === "pointer") {
6007
+ throw new CredentialResolutionError("secrets", "The Secrets vault requires an independent, non-reference bootstrap credential.", bootstrap ? [bootstrap.source] : []);
6008
+ }
6009
+ client = secretsSdk.createSecretsClientFromEnv(secretsEnv);
6010
+ } catch {
6011
+ 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]);
6012
+ }
6013
+ let secret;
6014
+ try {
6015
+ secret = await client.getSecret({ key: vaultKey });
6016
+ } catch {
6017
+ 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]);
6018
+ }
6019
+ const value = secret.value;
6020
+ if (!value) {
6021
+ throw new CredentialResolutionError(name, `${pointerEnvKey} resolved vault item '${vaultKey}', but it holds no value. A vault pointer is TERMINAL.`, [pointerEnvKey]);
6022
+ }
6023
+ assertUsableCredential(name, `${pointerEnvKey} -> vault:${vaultKey}`, value);
6024
+ return sealCredential({
6025
+ apiKey: value,
6026
+ tier: "pointer",
6027
+ source: `${pointerEnvKey} -> vault:${vaultKey}`,
6028
+ deliberate: pointerResolution.deliberate,
6029
+ diskCandidates: pointerResolution.diskCandidates,
6030
+ warning: null
6031
+ });
6032
+ }
5855
6033
  var IDEMPOTENT_METHODS = new Set(["GET", "HEAD", "PUT", "DELETE", "OPTIONS"]);
5856
6034
  var AUTHORITY_OVERRIDE_HEADERS = new Set([
5857
6035
  "host",
@@ -5899,11 +6077,25 @@ function hooksResolverInputs(env, credentials = {}) {
5899
6077
  }
5900
6078
 
5901
6079
  // src/lib/transport.ts
5902
- function resolveHooksServePublishKey(env = process.env, options = {}) {
6080
+ var authorityBindings = new WeakMap;
6081
+ function sameCredential(left, right) {
6082
+ return left === null || right === null ? left === right : left.apiKey === right.apiKey && left.pointerVaultKey === right.pointerVaultKey && left.source === right.source && left.tier === right.tier;
6083
+ }
6084
+ function changedBinding() {
6085
+ throw new Error("REMOTE_API_CREDENTIAL_INVALID: The configured Hooks authority or credential changed while preparing a request; no request was sent.");
6086
+ }
6087
+ async function resolveHooksServePublishKeyAsync(env = process.env, options = {}) {
5903
6088
  const { env: resolverEnv, credentials } = hooksResolverInputs(env, options.credentials);
5904
- const tier1 = options.credentials?.apiKey;
5905
- const credentialOptions = tier1 !== undefined ? { ...credentials, apiKey: tier1 } : credentials;
5906
- return resolveCredential("hooks", resolverEnv, credentialOptions)?.apiKey;
6089
+ const read = () => resolveCredential("hooks", resolverEnv, credentials);
6090
+ const selected = read();
6091
+ if (!selected || selected.tier !== "pointer")
6092
+ return selected?.apiKey;
6093
+ if (!sameCredential(selected, read()))
6094
+ changedBinding();
6095
+ const completed = await completePointerCredential("hooks", selected, env);
6096
+ if (!sameCredential(selected, read()))
6097
+ changedBinding();
6098
+ return completed.apiKey;
5907
6099
  }
5908
6100
 
5909
6101
  // src/lib/secure-compare.ts
@@ -5912,8 +6104,8 @@ function secureEqual(a, b) {
5912
6104
  const ab = enc.encode(a);
5913
6105
  const bb = enc.encode(b);
5914
6106
  let diff = ab.length ^ bb.length;
5915
- const n = Math.max(ab.length, bb.length);
5916
- for (let i = 0;i < n; i++) {
6107
+ const n2 = Math.max(ab.length, bb.length);
6108
+ for (let i = 0;i < n2; i++) {
5917
6109
  diff |= (ab[i] ?? 0) ^ (bb[i] ?? 0);
5918
6110
  }
5919
6111
  return diff === 0;
@@ -6076,7 +6268,7 @@ var SERVE_HOST = "127.0.0.1";
6076
6268
  var SERVE_SERVICE_NAME = "hooks-registry";
6077
6269
  function packageVersion() {
6078
6270
  try {
6079
- const pkgPath = join8(dirname3(fileURLToPath2(import.meta.url)), "..", "package.json");
6271
+ const pkgPath = join8(dirname4(fileURLToPath5(import.meta.url)), "..", "package.json");
6080
6272
  return JSON.parse(readFileSync5(pkgPath, "utf-8")).version || "0.0.0";
6081
6273
  } catch {
6082
6274
  return "0.0.0";
@@ -6238,7 +6430,7 @@ function startServeServer(options) {
6238
6430
  hostname: host,
6239
6431
  port,
6240
6432
  async fetch(req) {
6241
- return handleServeRequest(req, resolveHooksServePublishKey());
6433
+ return handleServeRequest(req, await resolveHooksServePublishKeyAsync());
6242
6434
  }
6243
6435
  });
6244
6436
  console.error(`hooks registry listening on http://${host}:${server.port} (publish requires an API key)`);
package/dist/index.d.ts CHANGED
@@ -75,7 +75,7 @@ export { createProfile, getProfile, listProfiles, updateProfile, deleteProfile,
75
75
  export { HOOKS_STORAGE_ENV, HOOKS_STORAGE_FALLBACK_ENV, HOOKS_STORAGE_BACKEND_ENV, HOOKS_STORAGE_BACKEND_FALLBACK_ENV, HOOKS_STORAGE_TABLES, RETIRED_STORAGE_MODE_ENV, STORAGE_BACKENDS, STORAGE_BACKEND_ENV, STORAGE_DATABASE_ENV, STORAGE_TABLES, getStorageBackend, getStorageDatabaseEnv, getStorageDatabaseEnvName, getStorageDatabaseUrl, getStoragePg, getStorageStatus, getSyncMetaAll, parseStorageTables, resolveTables, runStorageMigrations, storagePull, storagePush, storageSync, } from "./storage.js";
76
76
  export type { StorageBackend, StorageEnv, StorageStatus, SyncMeta, SyncResult } from "./storage.js";
77
77
  export { getHooksDataDir, getCustomHooksDir, getLockPath, } from "./config.js";
78
- export { resolveHooksTransport, resolveHooksServePublishKey, hooksRegistryOrigin, type HooksRemoteAuthority, type HooksCredentialOptions, type HooksTransportMode, type HooksTransportNotice, type HooksTransportOptions, type HooksTransportResolution, } from "./lib/transport.js";
78
+ export { resolveHooksTransport, resolveHooksRequestAuthority, resolveHooksServePublishKey, resolveHooksServePublishKeyAsync, hooksRegistryOrigin, type HooksRemoteAuthority, type HooksCredentialOptions, type HooksTransportMode, type HooksTransportNotice, type HooksTransportOptions, type HooksTransportResolution, } from "./lib/transport.js";
79
79
  export type { HooksLocalOptInEnv } from "./lib/resolver-types.js";
80
80
  export { HOOKS_LOCAL_OPT_IN_ENV_KEYS, isHooksLocalOptIn, hasHooksEnvAuthorityIntent, selectsHooksLocalStore, hooksFailClosedLine, hooksHostedRouteLocalStoreRefusal, hooksEventSinkRefusal, } from "./lib/local-opt-in.js";
81
81
  export { refuseLocalStore, allowLocalStore, isLocalStoreRefused } from "./db/index.js";