@keetanetwork/anchor 0.0.62 → 0.0.63

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/lib/anchor-metadata-server.d.ts +54 -0
  2. package/lib/anchor-metadata-server.d.ts.map +1 -0
  3. package/lib/anchor-metadata-server.js +62 -0
  4. package/lib/anchor-metadata-server.js.map +1 -0
  5. package/lib/error.d.ts +35 -0
  6. package/lib/error.d.ts.map +1 -1
  7. package/lib/error.generated.d.ts +3 -0
  8. package/lib/error.generated.d.ts.map +1 -0
  9. package/lib/error.generated.js +104 -0
  10. package/lib/error.generated.js.map +1 -0
  11. package/lib/error.js +66 -1
  12. package/lib/error.js.map +1 -1
  13. package/lib/http-server/common.d.ts +20 -2
  14. package/lib/http-server/common.d.ts.map +1 -1
  15. package/lib/http-server/common.js +47 -0
  16. package/lib/http-server/common.js.map +1 -1
  17. package/lib/http-server/index.d.ts +22 -0
  18. package/lib/http-server/index.d.ts.map +1 -1
  19. package/lib/http-server/index.js +23 -0
  20. package/lib/http-server/index.js.map +1 -1
  21. package/lib/metadata.types.d.ts +40 -0
  22. package/lib/metadata.types.d.ts.map +1 -1
  23. package/lib/metadata.types.js.map +1 -1
  24. package/lib/resolver.d.ts +19 -20
  25. package/lib/resolver.d.ts.map +1 -1
  26. package/lib/resolver.js +1420 -681
  27. package/lib/resolver.js.map +1 -1
  28. package/lib/utils/certificate-network.d.ts +84 -0
  29. package/lib/utils/certificate-network.d.ts.map +1 -0
  30. package/lib/utils/certificate-network.js +104 -0
  31. package/lib/utils/certificate-network.js.map +1 -0
  32. package/lib/utils/signing.d.ts +12 -0
  33. package/lib/utils/signing.d.ts.map +1 -1
  34. package/lib/utils/signing.js +145 -2
  35. package/lib/utils/signing.js.map +1 -1
  36. package/npm-shrinkwrap.json +4 -4
  37. package/package.json +1 -1
  38. package/services/asset-movement/common.d.ts.map +1 -1
  39. package/services/asset-movement/common.js +7 -53
  40. package/services/asset-movement/common.js.map +1 -1
  41. package/services/asset-movement/server.d.ts +6 -4
  42. package/services/asset-movement/server.d.ts.map +1 -1
  43. package/services/asset-movement/server.js +3 -3
  44. package/services/asset-movement/server.js.map +1 -1
  45. package/services/fx/common.js +7 -7
  46. package/services/fx/server.d.ts +9 -7
  47. package/services/fx/server.d.ts.map +1 -1
  48. package/services/fx/server.js +5 -5
  49. package/services/fx/server.js.map +1 -1
  50. package/services/kyc/server.d.ts +6 -4
  51. package/services/kyc/server.d.ts.map +1 -1
  52. package/services/kyc/server.js +3 -3
  53. package/services/kyc/server.js.map +1 -1
  54. package/services/notification/common.d.ts +2 -1
  55. package/services/notification/common.d.ts.map +1 -1
  56. package/services/notification/common.generated.js +20 -20
  57. package/services/notification/common.js +3 -2
  58. package/services/notification/common.js.map +1 -1
  59. package/services/notification/server.d.ts +7 -6
  60. package/services/notification/server.d.ts.map +1 -1
  61. package/services/notification/server.js +25 -62
  62. package/services/notification/server.js.map +1 -1
  63. package/services/storage/common.d.ts +2 -1
  64. package/services/storage/common.d.ts.map +1 -1
  65. package/services/storage/common.js +7 -2
  66. package/services/storage/common.js.map +1 -1
  67. package/services/storage/server.d.ts +7 -5
  68. package/services/storage/server.d.ts.map +1 -1
  69. package/services/storage/server.js +29 -99
  70. package/services/storage/server.js.map +1 -1
  71. package/services/username/common.d.ts +2 -1
  72. package/services/username/common.d.ts.map +1 -1
  73. package/services/username/common.generated.js +14 -48
  74. package/services/username/common.generated.js.map +1 -1
  75. package/services/username/common.js +3 -2
  76. package/services/username/common.js.map +1 -1
  77. package/services/username/server.d.ts +7 -6
  78. package/services/username/server.d.ts.map +1 -1
  79. package/services/username/server.js +38 -46
  80. package/services/username/server.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/lib/http-server/common.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Account } from \"@keetanetwork/keetanet-client/lib/account.js\";\nimport { KeetaAnchorUserError } from \"../error.js\";\nimport { KeetaNet } from \"../../client/index.js\";\nimport { createAssertEquals } from \"typia\";\n\nexport type ExtractOk<T> = Omit<Extract<T, { ok: true }>, 'ok'>;\n\nexport interface HTTPSignedField {\n\tnonce: string;\n\t/* Date and time of the request in ISO 8601 format */\n\ttimestamp: string;\n\t/* Signature of the account public key and the nonce as an ASN.1 Sequence, Base64 DER */\n\tsignature: string;\n}\n\nexport const assertHTTPSignedField: (input: unknown) => HTTPSignedField = createAssertEquals<HTTPSignedField>();\n\nexport interface HTTPSignedFieldURLParameters {\n\tsignedField: HTTPSignedField;\n\taccount: Account;\n}\n\nexport function addSignatureToURL(input: URL | string, data: HTTPSignedFieldURLParameters): URL {\n\tlet url: URL;\n\n\tif (typeof input === 'string') {\n\t\turl = new URL(input);\n\t} else {\n\t\turl = new URL(input.toString());\n\t}\n\n\tfor (const key of [ 'nonce', 'timestamp', 'signature' ] as const) {\n\t\tconst searchKey = `signed.${key}`;\n\n\t\tif (url.searchParams.has(searchKey)) {\n\t\t\tthrow(new KeetaAnchorUserError(`URL already has signed field parameter: ${searchKey}`));\n\t\t}\n\n\t\turl.searchParams.set(`signed.${key}`, data.signedField[key]);\n\t}\n\n\turl.searchParams.set('account', data.account.publicKeyString.get());\n\n\treturn(url);\n}\n\nexport function parseSignatureFromURL(input: URL | string): Partial<HTTPSignedFieldURLParameters> {\n\tlet url: URL;\n\n\tif (typeof input === 'string') {\n\t\turl = new URL(input);\n\t} else {\n\t\turl = new URL(input.toString());\n\t}\n\n\tconst retVal: Partial<HTTPSignedFieldURLParameters> = {};\n\n\tconst signedField = ((): HTTPSignedField | undefined => {\n\t\tconst nonce = url.searchParams.get('signed.nonce');\n\t\tconst timestamp = url.searchParams.get('signed.timestamp');\n\t\tconst signature = url.searchParams.get('signed.signature');\n\n\t\tif (!nonce && !timestamp && !signature) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\tif (!nonce || !timestamp || !signature) {\n\t\t\tthrow(new KeetaAnchorUserError('Incomplete signature fields in URL'));\n\t\t}\n\n\t\treturn({ nonce, timestamp, signature });\n\t})();\n\n\tif (signedField) {\n\t\tretVal.signedField = signedField;\n\t}\n\n\tconst account = ((): Account | undefined => {\n\t\tconst accountParam = url.searchParams.get('account');\n\t\tif (!accountParam) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\treturn(KeetaNet.lib.Account.fromPublicKeyString(accountParam).assertAccount());\n\t})();\n\n\tif (account) {\n\t\tretVal.account = account;\n\t}\n\n\treturn(retVal);\n}\n"]}
1
+ {"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/lib/http-server/common.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Account } from \"@keetanetwork/keetanet-client/lib/account.js\";\nimport type { ResolvedCertificateChainRequirement } from \"../utils/certificate-network.js\";\nimport type { Signable } from \"../utils/signing.js\";\nimport { KeetaAnchorUserError } from \"../error.js\";\nimport { KeetaNet } from \"../../client/index.js\";\nimport { assertAccountCertificateChain } from \"../utils/certificate-network.js\";\nimport { createAssertEquals } from \"typia\";\nimport { VerifySignedData } from \"../utils/signing.js\";\n\nexport type ExtractOk<T> = Omit<Extract<T, { ok: true }>, 'ok'>;\n\nexport type HTTPSignedField = {\n\tnonce: string;\n\t/* Date and time of the request in ISO 8601 format */\n\ttimestamp: string;\n\t/* Signature of the account public key and the nonce as an ASN.1 Sequence, Base64 DER */\n\tsignature: string;\n};\n\nexport const assertHTTPSignedField: (input: unknown) => HTTPSignedField = createAssertEquals<HTTPSignedField>();\n\nexport interface HTTPSignedFieldURLParameters {\n\tsignedField: HTTPSignedField;\n\taccount: Account;\n}\n\nexport function addSignatureToURL(input: URL | string, data: HTTPSignedFieldURLParameters): URL {\n\tlet url: URL;\n\n\tif (typeof input === 'string') {\n\t\turl = new URL(input);\n\t} else {\n\t\turl = new URL(input.toString());\n\t}\n\n\tfor (const key of [ 'nonce', 'timestamp', 'signature' ] as const) {\n\t\tconst searchKey = `signed.${key}`;\n\n\t\tif (url.searchParams.has(searchKey)) {\n\t\t\tthrow(new KeetaAnchorUserError(`URL already has signed field parameter: ${searchKey}`));\n\t\t}\n\n\t\turl.searchParams.set(`signed.${key}`, data.signedField[key]);\n\t}\n\n\turl.searchParams.set('account', data.account.publicKeyString.get());\n\n\treturn(url);\n}\n\nexport function parseSignatureFromURL(input: URL | string): Partial<HTTPSignedFieldURLParameters> {\n\tlet url: URL;\n\n\tif (typeof input === 'string') {\n\t\turl = new URL(input);\n\t} else {\n\t\turl = new URL(input.toString());\n\t}\n\n\tconst retVal: Partial<HTTPSignedFieldURLParameters> = {};\n\n\tconst signedField = ((): HTTPSignedField | undefined => {\n\t\tconst nonce = url.searchParams.get('signed.nonce');\n\t\tconst timestamp = url.searchParams.get('signed.timestamp');\n\t\tconst signature = url.searchParams.get('signed.signature');\n\n\t\tif (!nonce && !timestamp && !signature) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\tif (!nonce || !timestamp || !signature) {\n\t\t\tthrow(new KeetaAnchorUserError('Incomplete signature fields in URL'));\n\t\t}\n\n\t\treturn({ nonce, timestamp, signature });\n\t})();\n\n\tif (signedField) {\n\t\tretVal.signedField = signedField;\n\t}\n\n\tconst account = ((): Account | undefined => {\n\t\tconst accountParam = url.searchParams.get('account');\n\t\tif (!accountParam) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\treturn(KeetaNet.lib.Account.fromPublicKeyString(accountParam).assertAccount());\n\t})();\n\n\tif (account) {\n\t\tretVal.account = account;\n\t}\n\n\treturn(retVal);\n}\n\n/**\n * Verify a signed body, then enforce the cert-chain gate. Returns the\n * authenticated account. Throws `KeetaAnchorUserError` on missing or\n * invalid auth, and `KeetaAnchorCertificateRequiredError` when the\n * caller's on-chain cert chain doesn't satisfy `certificateChain`.\n */\nexport async function verifyBodyAuth<T extends { account?: string; signed?: unknown }>(\n\trequest: T,\n\tgetSigningData: (req: T) => Signable,\n\tcertificateChain?: ResolvedCertificateChainRequirement\n): Promise<Account> {\n\tif (!request.account || !request.signed) {\n\t\tthrow(new KeetaAnchorUserError('Authentication required'));\n\t}\n\n\tconst account = KeetaNet.lib.Account.fromPublicKeyString(request.account).assertAccount();\n\n\tconst signable = getSigningData(request);\n\tconst signed = assertHTTPSignedField(request.signed);\n\tconst valid = await VerifySignedData(account, signable, signed);\n\tif (!valid) {\n\t\tthrow(new KeetaAnchorUserError('Invalid signature'));\n\t}\n\n\tawait assertAccountCertificateChain(account, certificateChain);\n\n\treturn(account);\n}\n\n/**\n * Verify a URL-signed request, then enforce the cert-chain gate. Returns\n * the authenticated account. The signable is built by the caller from a\n * request derived from the URL-bound account public key.\n */\nexport async function verifyURLAuth(\n\turl: URL | string,\n\tgetSigningData: (account: Account) => Signable,\n\tcertificateChain?: ResolvedCertificateChainRequirement\n): Promise<Account> {\n\tlet urlString: string;\n\tif (typeof url === 'string') {\n\t\turlString = url;\n\t} else {\n\t\turlString = url.href;\n\t}\n\n\tconst parsed = parseSignatureFromURL(urlString);\n\tif (!parsed.account || !parsed.signedField) {\n\t\tthrow(new KeetaAnchorUserError('Authentication required'));\n\t}\n\n\tconst signable = getSigningData(parsed.account);\n\tconst valid = await VerifySignedData(parsed.account, signable, parsed.signedField);\n\tif (!valid) {\n\t\tthrow(new KeetaAnchorUserError('Invalid signature'));\n\t}\n\n\tawait assertAccountCertificateChain(parsed.account, certificateChain);\n\n\treturn(parsed.account);\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import * as http from 'http';
2
2
  import type { JSONSerializable } from '../utils/json.js';
3
3
  import type { Logger } from '../log/index.js';
4
+ import type { CertificateChainConfig, ResolvedCertificateChainRequirement } from '../utils/certificate-network.js';
4
5
  export declare const AssertHTTPErrorData: (input: unknown) => {
5
6
  error: string;
6
7
  statusCode?: number;
@@ -58,14 +59,35 @@ export interface KeetaAnchorHTTPServerConfig {
58
59
  port?: number;
59
60
  protocol?: string;
60
61
  };
62
+ /**
63
+ * Optional on-chain cert-chain gate. When set, authenticated callers
64
+ * MUST have a published cert chaining to one of `trustedIssuers`.
65
+ */
66
+ requireCertificateChain?: CertificateChainConfig | undefined;
61
67
  }
62
68
  export declare abstract class KeetaNetAnchorHTTPServer<ConfigType extends KeetaAnchorHTTPServerConfig = KeetaAnchorHTTPServerConfig> implements Required<KeetaAnchorHTTPServerConfig> {
63
69
  #private;
64
70
  readonly port: NonNullable<KeetaAnchorHTTPServerConfig['port']>;
65
71
  readonly logger: NonNullable<KeetaAnchorHTTPServerConfig['logger']>;
66
72
  readonly id: NonNullable<KeetaAnchorHTTPServerConfig['id']>;
73
+ /**
74
+ * Resolved cert-chain requirement, or `undefined` when disabled.
75
+ * @see {@link requireCertificateChain}.
76
+ */
77
+ protected readonly resolvedCertificateChainRequirement: ResolvedCertificateChainRequirement | undefined;
67
78
  constructor(config: ConfigType);
68
79
  protected abstract initRoutes(config: ConfigType): Promise<Routes>;
80
+ /**
81
+ * Public view of the cert-chain config, or `undefined` when disabled.
82
+ */
83
+ get requireCertificateChain(): CertificateChainConfig | undefined;
84
+ /**
85
+ * Trusted-issuer DNs metadata. Is `undefined` when the gate is not configured.
86
+ */
87
+ protected acceptedIssuerDNs(): {
88
+ name: string;
89
+ value: string;
90
+ }[][] | undefined;
69
91
  private static routeMatch;
70
92
  private static routeFind;
71
93
  private static addCORS;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/http-server/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/http-server/index.ts"],"names":[],"mappings":"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"}
@@ -4,6 +4,7 @@ import { KeetaAnchorError, KeetaAnchorUserError } from '../error.js';
4
4
  import { Log } from '../log/index.js';
5
5
  import { createAssert } from 'typia';
6
6
  import { assertNever } from '../utils/never.js';
7
+ import { resolveCertificateChainConfig } from '../utils/certificate-network.js';
7
8
  export const AssertHTTPErrorData = (() => { const _io0 = input => "string" === typeof input.error && (undefined === input.statusCode || "number" === typeof input.statusCode) && (undefined === input.contentType || "string" === typeof input.contentType); const _ao0 = (input, _path, _exceptionable = true) => ("string" === typeof input.error || __typia_transform__assertGuard._assertGuard(_exceptionable, {
8
9
  method: "createAssert",
9
10
  path: _path + ".error",
@@ -45,6 +46,11 @@ export class KeetaNetAnchorHTTPServer {
45
46
  port;
46
47
  logger;
47
48
  id;
49
+ /**
50
+ * Resolved cert-chain requirement, or `undefined` when disabled.
51
+ * @see {@link requireCertificateChain}.
52
+ */
53
+ resolvedCertificateChainRequirement;
48
54
  #serverPromise;
49
55
  #server;
50
56
  #urlParts;
@@ -55,6 +61,7 @@ export class KeetaNetAnchorHTTPServer {
55
61
  this.port = config.port ?? 0;
56
62
  this.id = config.id ?? crypto.randomUUID();
57
63
  this.logger = config.logger ?? Log.Legacy('ANCHOR');
64
+ this.resolvedCertificateChainRequirement = resolveCertificateChainConfig(config.requireCertificateChain);
58
65
  if (config.url !== undefined) {
59
66
  if (config.url instanceof URL || typeof config.url === 'string') {
60
67
  this.#url = config.url;
@@ -82,6 +89,22 @@ export class KeetaNetAnchorHTTPServer {
82
89
  }
83
90
  }
84
91
  }
92
+ /**
93
+ * Public view of the cert-chain config, or `undefined` when disabled.
94
+ */
95
+ get requireCertificateChain() {
96
+ return (this.resolvedCertificateChainRequirement);
97
+ }
98
+ /**
99
+ * Trusted-issuer DNs metadata. Is `undefined` when the gate is not configured.
100
+ */
101
+ acceptedIssuerDNs() {
102
+ const requirement = this.resolvedCertificateChainRequirement;
103
+ if (requirement === undefined) {
104
+ return (undefined);
105
+ }
106
+ return (requirement.acceptedIssuerDNs);
107
+ }
85
108
  static routeMatch(requestURL, routeURL) {
86
109
  const requestURLPaths = requestURL.pathname.split('/');
87
110
  const routeURLPaths = routeURL.pathname.split('/');
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/http-server/index.ts"],"names":[],"mappings":"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","sourcesContent":["import * as http from 'http';\nimport {\n\tKeetaAnchorError,\n\tKeetaAnchorUserError\n} from '../error.js';\nimport type { JSONSerializable } from '../utils/json.js';\nimport type { Logger, LogLevel } from '../log/index.js';\nimport { Log } from '../log/index.js';\nimport { createAssert } from 'typia';\nimport { assertNever } from '../utils/never.js';\n\nexport const AssertHTTPErrorData: (input: unknown) => { error: string; statusCode?: number; contentType?: string; } = createAssert<{ error: string; statusCode?: number; contentType?: string; }>();\n\n/**\n * The maximum size of a request (128MiB)\n */\nconst MAX_REQUEST_SIZE = 128 * (1024 ** 2);\n\ntype RouteHandlerMethod<BodyDataType = JSONSerializable | undefined> = (urlParams: Map<string, string>, postData: BodyDataType, requestHeaders: http.IncomingHttpHeaders, requestUrl: URL) => Promise<{ output: string | Buffer; statusCode?: number; contentType?: string; headers?: { [headerName: string]: string; }; }>;\ntype RouteHandlerWithConfig = {\n\tbodyType: 'raw';\n\tmaxBodySize?: number;\n\thandler: RouteHandlerMethod<Buffer>;\n} | {\n\tbodyType: 'parsed';\n\tmaxBodySize?: number;\n\thandler: RouteHandlerMethod;\n} | {\n\tbodyType: 'none';\n\thandler: RouteHandlerMethod<undefined>;\n};\ntype RouteHandler = RouteHandlerMethod | RouteHandlerWithConfig;\nexport type Routes = { [route: string]: RouteHandler };\nexport type RoutesWithConfigs = { [route: string]: RouteHandlerWithConfig };\n\nexport interface KeetaAnchorHTTPServerConfig {\n\t/**\n\t * Identifier for the server instance -- if one is not given\n\t * a random one will be generated.\n\t */\n\tid?: string;\n\n\t/**\n\t * The port for the HTTP server to listen on (default is an ephemeral port).\n\t */\n\tport?: number;\n\n\t/**\n\t * Enable debug logging\n\t */\n\tlogger?: Logger | undefined;\n\t/**\n\t * The URL for the server. By default, this will be generated based on\n\t * the port and will use \"localhost\" as the hostname, but it can be\n\t * overridden by setting this to a string, URL, or function that\n\t * generates the URL\n\t */\n\turl?: undefined | string | URL | ((object: KeetaNetAnchorHTTPServer) => string) | {\n\t\thostname?: string;\n\t\tport?: number;\n\t\tprotocol?: string;\n\t};\n};\n\nexport abstract class KeetaNetAnchorHTTPServer<ConfigType extends KeetaAnchorHTTPServerConfig = KeetaAnchorHTTPServerConfig> implements Required<KeetaAnchorHTTPServerConfig> {\n\treadonly port: NonNullable<KeetaAnchorHTTPServerConfig['port']>;\n\treadonly logger: NonNullable<KeetaAnchorHTTPServerConfig['logger']>;\n\treadonly id: NonNullable<KeetaAnchorHTTPServerConfig['id']>;\n\t#serverPromise?: Promise<void>;\n\t#server?: http.Server;\n\t#urlParts: undefined | { hostname?: string; port?: number; protocol?: string; };\n\t#url: undefined | string | URL | ((object: this) => string);\n\treadonly #config: ConfigType;\n\n\tconstructor(config: ConfigType) {\n\t\tthis.#config = { ...config };\n\t\tthis.port = config.port ?? 0;\n\t\tthis.id = config.id ?? crypto.randomUUID();\n\t\tthis.logger = config.logger ?? Log.Legacy('ANCHOR');\n\n\t\tif (config.url !== undefined) {\n\t\t\tif (config.url instanceof URL || typeof config.url === 'string') {\n\t\t\t\tthis.#url = config.url;\n\t\t\t\tthis.#urlParts = undefined;\n\t\t\t} else if (typeof config.url === 'function') {\n\t\t\t\t/**\n\t\t\t\t * The parameter for the call back is typed as\n\t\t\t\t * `this`, which means any subclass is typed\n\t\t\t\t * but the interface can't identify that --\n\t\t\t\t * instead it types it as the base class\n\t\t\t\t * (KeetaNetAnchorHTTPServer), which means it\n\t\t\t\t * can't be assigned to the type of `#url`\n\t\t\t\t * without overriding the type check. However,\n\t\t\t\t * we know that `this` will be at least\n\t\t\t\t * compatible with the base class.\n\t\t\t\t */\n\t\t\t\t// @ts-ignore\n\t\t\t\tthis.#url = config.url;\n\t\t\t\tthis.#urlParts = undefined;\n\t\t\t} else {\n\t\t\t\tthis.#url = undefined;\n\t\t\t\tthis.#urlParts = config.url;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected abstract initRoutes(config: ConfigType): Promise<Routes>;\n\n\tprivate static routeMatch(requestURL: URL, routeURL: URL): ({ match: true; params: Map<string, string>; wildcard?: { prefixLength: number }} | { match: false }) {\n\t\tconst requestURLPaths = requestURL.pathname.split('/');\n\t\tconst routeURLPaths = routeURL.pathname.split('/');\n\n\t\t// Check if route ends with wildcard /**\n\t\tconst isWildcard = routeURLPaths.length > 0 && routeURLPaths[routeURLPaths.length - 1] === '**';\n\t\tif (isWildcard) {\n\t\t\t// For wildcard routes, request must have more segments than route prefix (minus the **)\n\t\t\t// This ensures at least one segment is captured by the wildcard\n\t\t\tconst prefixLength = routeURLPaths.length - 1;\n\t\t\tif (requestURLPaths.length <= prefixLength) {\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\n\t\t\t// Check that prefix segments match\n\t\t\tconst params = new Map<string, string>();\n\t\t\tfor (let partIndex = 0; partIndex < prefixLength; partIndex++) {\n\t\t\t\tconst requestPath = requestURLPaths[partIndex];\n\n\t\t\t\tconst routePath = routeURLPaths[partIndex];\n\t\t\t\tif (routePath === undefined || requestPath === undefined) {\n\t\t\t\t\treturn({ match: false });\n\t\t\t\t}\n\n\t\t\t\tif (routePath.startsWith(':')) {\n\t\t\t\t\tparams.set(routePath.slice(1), requestPath);\n\t\t\t\t} else if (requestPath !== routePath) {\n\t\t\t\t\treturn({ match: false });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Capture the remainder as the wildcard param\n\t\t\t// Filter empty segments to handle trailing slashes correctly\n\t\t\tconst remainder = requestURLPaths.slice(prefixLength)\n\t\t\t\t.filter(function(s) {\n\t\t\t\t\treturn(s !== '');\n\t\t\t\t})\n\t\t\t\t.join('/');\n\n\t\t\tif (remainder === '') {\n\t\t\t\t// Reject if wildcard would capture nothing\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\n\t\t\tparams.set('**', remainder);\n\n\t\t\treturn({ match: true, params: params, wildcard: { prefixLength }});\n\t\t}\n\n\t\t// Non-wildcard: require exact segment count\n\t\tif (requestURLPaths.length !== routeURLPaths.length) {\n\t\t\treturn({ match: false });\n\t\t}\n\n\t\tconst params = new Map<string, string>();\n\t\tfor (let partIndex = 0; partIndex < requestURLPaths.length; partIndex++) {\n\t\t\tconst requestPath = requestURLPaths[partIndex];\n\t\t\tconst routePath = routeURLPaths[partIndex];\n\n\t\t\tif (routePath === undefined || requestPath === undefined) {\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\n\t\t\tif (routePath.startsWith(':')) {\n\t\t\t\tparams.set(routePath.slice(1), requestPath);\n\t\t\t} else if (requestPath !== routePath) {\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\t\t}\n\n\t\treturn({ match: true, params: params });\n\t}\n\n\tprivate static routeFind(method: string, requestURL: URL, routes: Routes): { route: Routes[keyof Routes]; params: Map<string, string> } | null {\n\t\tlet wildcardMatch: { route: Routes[keyof Routes]; params: Map<string, string> } | null = null;\n\t\tlet wildcardPrefixLength = -1;\n\n\t\tfor (const routeKey in routes) {\n\t\t\tconst route = routes[routeKey];\n\t\t\tif (route === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst [routeMethod, ...routePathParts] = routeKey.split(' ');\n\t\t\tconst routePath = `/${routePathParts.join(' ')}`.replace(/^\\/+/, '/');\n\n\t\t\tif (method !== routeMethod) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst routeURL = new URL(routePath, 'http://localhost');\n\t\t\tconst matchResult = this.routeMatch(requestURL, routeURL);\n\t\t\tif (matchResult.match) {\n\t\t\t\t// Exact matches take priority over wildcard matches\n\t\t\t\tif (matchResult.wildcard === undefined) {\n\t\t\t\t\treturn({\n\t\t\t\t\t\troute: route,\n\t\t\t\t\t\tparams: matchResult.params\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Keep the most specific wildcard (longest prefix wins)\n\t\t\t\tif (matchResult.wildcard.prefixLength > wildcardPrefixLength) {\n\t\t\t\t\twildcardPrefixLength = matchResult.wildcard.prefixLength;\n\t\t\t\t\twildcardMatch = {\n\t\t\t\t\t\troute: route,\n\t\t\t\t\t\tparams: matchResult.params\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return most specific wildcard match if no exact match found\n\t\treturn(wildcardMatch);\n\t}\n\n\tprivate static addCORS(routes: Routes): RoutesWithConfigs {\n\t\tconst newRoutes: RoutesWithConfigs = {};\n\n\t\tconst validMethods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']);\n\n\t\tconst methodsByPath: { [key: string]: Set<string>; } = {};\n\t\tfor (const routeKey in routes) {\n\t\t\tconst methodAndPath = routeKey.split(' ');\n\t\t\tconst method = methodAndPath[0];\n\t\t\tconst path = methodAndPath.slice(1).join(' ');\n\n\t\t\tif (method === undefined || path === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!validMethods.has(method)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!(path in methodsByPath)) {\n\t\t\t\tmethodsByPath[path] = new Set<string>();\n\t\t\t}\n\n\t\t\tif (methodsByPath[path] === undefined) {\n\t\t\t\tthrow(new Error(`internal error: methodsByPath missing path for ${path}`));\n\t\t\t}\n\n\t\t\tmethodsByPath[path].add(method);\n\t\t}\n\n\t\tconst seenPaths = new Set<string>();\n\t\tfor (const routeKey in routes) {\n\t\t\tconst methodAndPath = routeKey.split(' ');\n\t\t\tconst method = methodAndPath[0];\n\t\t\tconst path = methodAndPath.slice(1).join(' ');\n\n\t\t\tconst routeHandler = routes[routeKey];\n\t\t\tif (routeHandler === undefined) {\n\t\t\t\tthrow(new Error(`internal error: routeHandler missing for routeKey ${routeKey}`));\n\t\t\t}\n\n\t\t\tlet newRoute: RouteHandlerWithConfig;\n\n\t\t\tif (typeof routeHandler === 'function') {\n\t\t\t\tnewRoute = {\n\t\t\t\t\tbodyType: 'parsed',\n\t\t\t\t\thandler: routeHandler\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tnewRoute = routeHandler;\n\t\t\t}\n\n\t\t\tif (method !== 'ERROR') {\n\t\t\t\tif (method === undefined || path === undefined) {\n\t\t\t\t\tnewRoutes[routeKey] = newRoute;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!validMethods.has(method)) {\n\t\t\t\t\tnewRoutes[routeKey] = newRoute;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst validMethodsForPath = methodsByPath[path];\n\n\t\t\tlet validMethodsForPathParts: string[] = [];\n\t\t\tif (validMethodsForPath !== undefined) {\n\t\t\t\tvalidMethodsForPath.add('OPTIONS');\n\t\t\t\tvalidMethodsForPathParts = Array.from(validMethodsForPath);\n\t\t\t} else {\n\t\t\t\tvalidMethodsForPathParts = [...Array.from(validMethods), 'OPTIONS'];\n\t\t\t}\n\n\t\t\tnewRoutes[routeKey] = {\n\t\t\t\t...newRoute,\n\t\t\t\tasync handler(...args: Parameters<RouteHandlerMethod<unknown>>) {\n\t\t\t\t\t// This is typed properly, but TS can't infer it here\n\t\t\t\t\t// @ts-ignore\n\t\t\t\t\tconst retval = await newRoute.handler(...args);\n\n\t\t\t\t\t/* Add CORS headers to the response for the original route handler */\n\t\t\t\t\tif (retval.contentType === 'application/json' || retval.contentType === undefined) {\n\t\t\t\t\t\tif (!('headers' in retval) || retval.headers === undefined) {\n\t\t\t\t\t\t\tretval.headers = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tretval.headers['Access-Control-Allow-Origin'] = '*';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn(retval);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!seenPaths.has(path) && path !== '' && path !== undefined) {\n\t\t\t\tconst corsRouteKey = `OPTIONS ${path}`;\n\n\t\t\t\tnewRoutes[corsRouteKey] = {\n\t\t\t\t\tbodyType: 'none',\n\t\t\t\t\tasync handler() {\n\t\t\t\t\t\treturn({\n\t\t\t\t\t\t\toutput: '',\n\t\t\t\t\t\t\tstatusCode: 204,\n\t\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t'Access-Control-Allow-Origin': '*',\n\t\t\t\t\t\t\t\t'Access-Control-Allow-Methods': validMethodsForPathParts.join(', '),\n\t\t\t\t\t\t\t\t'Access-Control-Allow-Headers': 'Content-Type',\n\t\t\t\t\t\t\t\t'Access-Control-Max-Age': '86400'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tseenPaths.add(path);\n\t\t\t}\n\t\t}\n\n\t\treturn(newRoutes);\n\t}\n\n\tprivate async main(onSetPort?: (port: number) => void): Promise<void> {\n\t\tthis.logger?.debug('KeetaAnchorHTTP.Server', 'Starting HTTP server...');\n\n\t\tconst port = this.port;\n\n\t\tconst routes = KeetaNetAnchorHTTPServer.addCORS({\n\t\t\tERROR: async function(_ignore_params, postData) {\n\t\t\t\tconst errorInfo = AssertHTTPErrorData(postData);\n\n\t\t\t\tconst retval = {\n\t\t\t\t\toutput: errorInfo.error,\n\t\t\t\t\tstatusCode: errorInfo.statusCode ?? 400,\n\t\t\t\t\tcontentType: errorInfo.contentType ?? 'text/plain'\n\t\t\t\t};\n\n\t\t\t\treturn(retval);\n\t\t\t},\n\t\t\t...(await this.initRoutes(this.#config))\n\t\t});\n\n\t\tconst server = new http.Server(async (request, response) => {\n\t\t\t/*\n\t\t\t * Get the Base URL from the request Host header (if\n\t\t\t * available) or default to localhost. This is used\n\t\t\t * to construct the full URL for routing.\n\t\t\t */\n\t\t\tconst inputURLBaseRaw = new URL(`http://${request.headers.host ?? 'localhost'}`);\n\t\t\tconst inputURLBase = inputURLBaseRaw.protocol + '//' + inputURLBaseRaw.host;\n\n\t\t\t/*\n\t\t\t * Normalize the input URL by stripping leading slashes and\n\t\t\t * combining it with the base URL to get the full URL for routing.\n\t\t\t */\n\t\t\tconst inputURLRaw = (request.url ?? '/').replace(/^\\/+/, '/');\n\t\t\tconst inputURLObject = new URL(inputURLRaw, 'http://localhost');\n\t\t\tconst inputURL = inputURLObject.pathname + (function() {\n\t\t\t\tif (inputURLObject.search === '') {\n\t\t\t\t\treturn('');\n\t\t\t\t}\n\n\t\t\t\treturn('?' + inputURLObject.searchParams.toString());\n\t\t\t})();\n\t\t\tconst url = new URL(inputURL, inputURLBase);\n\t\t\tconst method = request.method ?? 'GET';\n\n\t\t\t/*\n\t\t\t * Finalize the response by syncing the logger and ending\n\t\t\t * the response.\n\t\t\t */\n\t\t\tconst responseFinalize = async () => {\n\t\t\t\tif ('sync' in this.logger && typeof this.logger.sync === 'function') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.logger.sync();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* ignore errors */\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresponse.end();\n\t\t\t};\n\n\t\t\t/*\n\t\t\t * If the request is malformed, reject it immediately\n\t\t\t */\n\t\t\tif (inputURLRaw.at(0) !== '/') {\n\t\t\t\tresponse.statusCode = 400;\n\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\tresponse.write('Bad Request');\n\t\t\t\tawait responseFinalize();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Lookup the route based on the request\n\t\t\t */\n\t\t\tconst requestedRouteAndParams = KeetaNetAnchorHTTPServer.routeFind(method, url, routes);\n\t\t\tif (requestedRouteAndParams === null) {\n\t\t\t\tresponse.statusCode = 404;\n\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\tresponse.write('Not Found');\n\t\t\t\tawait responseFinalize();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Extract the route handler and the parameters from\n\t\t\t * the request\n\t\t\t */\n\t\t\tconst { route, params } = requestedRouteAndParams;\n\n\t\t\t/**\n\t\t\t * Attempt to run the route, catch any errors\n\t\t\t */\n\t\t\tlet result: Awaited<ReturnType<RouteHandlerMethod>> | undefined = undefined;\n\t\t\tlet generatedResult = false;\n\t\t\ttry {\n\t\t\t\tif (!request.method) {\n\t\t\t\t\tthrow(new Error('internal error: No request method'));\n\t\t\t\t}\n\n\t\t\t\tlet bodyData: JSONSerializable | Buffer | undefined;\n\n\t\t\t\tconst shouldCheckBody = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method);\n\n\t\t\t\tif (typeof route === 'function') {\n\t\t\t\t\tthrow(new Error('internal error: Route handler missing body type configuration, should have been added in addCORS'));\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * If POST'ing, PUT'ing, or PATCH'ing, read and parse the request body\n\t\t\t\t */\n\t\t\t\tif (shouldCheckBody && route.bodyType !== 'none') {\n\t\t\t\t\tconst bodySizeLimit = route.maxBodySize ?? MAX_REQUEST_SIZE;\n\n\t\t\t\t\t// Early rejection based on Content-Length header\n\t\t\t\t\tconst contentLength = request.headers['content-length'];\n\t\t\t\t\tif (contentLength !== undefined) {\n\t\t\t\t\t\tconst declaredSize = parseInt(contentLength, 10);\n\t\t\t\t\t\tif (!isNaN(declaredSize) && declaredSize > bodySizeLimit) {\n\t\t\t\t\t\t\trequest.resume();\n\n\t\t\t\t\t\t\tresponse.statusCode = 413;\n\t\t\t\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\t\t\t\tresponse.write('Payload Too Large');\n\n\t\t\t\t\t\t\tawait responseFinalize();\n\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = await request.map(function(chunk) {\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\t\t\t\treturn(Buffer.from(chunk));\n\t\t\t\t\t}).reduce(function(prev, curr) {\n\t\t\t\t\t\tif (prev.length > bodySizeLimit) {\n\t\t\t\t\t\t\tthrow(new Error('Request too large'));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!Buffer.isBuffer(curr)) {\n\t\t\t\t\t\t\tthrow(new Error(`internal error: Current item is not a buffer -- ${typeof curr}`));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(Buffer.concat([prev, curr]));\n\t\t\t\t\t}, Buffer.from(''));\n\n\t\t\t\t\tif (route.bodyType === 'raw') {\n\t\t\t\t\t\tbodyData = data;\n\t\t\t\t\t} else if (route.bodyType === 'parsed' && request.headers['content-type'] === 'application/json') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\t\t\tbodyData = JSON.parse(data.toString('utf-8'));\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tthrow(new Error('Invalid JSON data'));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (data.length > 0) {\n\t\t\t\t\t\tthrow(new KeetaAnchorUserError('Unsupported content type'));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Call the route handler\n\t\t\t\t */\n\t\t\t\t// @ts-ignore\n\t\t\t\tresult = await route.handler(params, bodyData, request.headers, url);\n\n\t\t\t\tgeneratedResult = true;\n\t\t\t} catch (err) {\n\t\t\t\tlet logLevel: Lowercase<LogLevel> = 'error';\n\t\t\t\tif (KeetaAnchorError.isInstance(err)) {\n\t\t\t\t\t/*\n\t\t\t\t\t * We're able to safely cast this here because the cast\n\t\t\t\t\t * duplicates the logic.\n\t\t\t\t\t */\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\t\tlogLevel = err.logLevel.toLowerCase() as Lowercase<typeof err.logLevel>;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * If an error occurs, log it and return an error page\n\t\t\t\t */\n\t\t\t\tthis.logger?.[logLevel]('KeetaAnchorHTTP.Server', err);\n\n\t\t\t\t/**\n\t\t\t\t * If it is a user error, provide a user-friendly error page\n\t\t\t\t */\n\t\t\t\tconst errorHandlerRoute = routes['ERROR'];\n\t\t\t\tif (errorHandlerRoute !== undefined) {\n\t\t\t\t\tlet errBody;\n\t\t\t\t\tif (KeetaAnchorError.isInstance(err) && err['userError']) {\n\t\t\t\t\t\terrBody = err.asErrorResponse('application/json');\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrBody = {\n\t\t\t\t\t\t\terror: JSON.stringify({ ok: false, error: 'Internal Server Error' }),\n\t\t\t\t\t\t\tstatusCode: 500,\n\t\t\t\t\t\t\tcontentType: 'application/json'\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// @ts-ignore\n\t\t\t\t\tresult = await errorHandlerRoute.handler(new Map(), errBody, request.headers, url);\n\t\t\t\t\tgeneratedResult = true;\n\t\t\t\t}\n\n\t\t\t\tif (!generatedResult) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Otherwise provide a generic error page\n\t\t\t\t\t */\n\t\t\t\t\tresponse.statusCode = 500;\n\t\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\t\tresponse.write('Internal Server Error');\n\t\t\t\t\tawait responseFinalize();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (result === undefined) {\n\t\t\t\tthrow(new Error('internal error: No result'));\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write the response to the client\n\t\t\t */\n\t\t\tresponse.statusCode = result.statusCode ?? 200;\n\n\t\t\tfor (const headerKey in result.headers ?? {}) {\n\t\t\t\tconst headerValue = result.headers?.[headerKey];\n\t\t\t\tif (headerValue !== undefined) {\n\t\t\t\t\tresponse.setHeader(headerKey, headerValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresponse.setHeader('Content-Type', result.contentType ?? 'application/json');\n\t\t\tresponse.write(result.output);\n\t\t\tawait responseFinalize();\n\t\t});\n\t\tthis.#server = server;\n\n\t\t/**\n\t\t * Create a promise to wait for the server to close\n\t\t */\n\t\tconst waiter = new Promise<void>((resolve) => {\n\t\t\tserver.on('close', () => {\n\t\t\t\tthis.logger?.debug('KeetaAnchorHTTP.Server', 'Server closed');\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\n\t\t/**\n\t\t * Start listening on the port\n\t\t */\n\t\tserver.listen(port, () => {\n\t\t\tconst address = server.address();\n\t\t\tif (address !== null && typeof address === 'object') {\n\t\t\t\t// @ts-ignore\n\t\t\t\tthis.port = address.port;\n\t\t\t\tonSetPort?.(this.port);\n\t\t\t}\n\t\t\tthis.logger?.debug('KeetaAnchorHTTP.Server', 'Listening on port:', this.port);\n\t\t});\n\n\t\t/**\n\t\t * Wait for the server to close\n\t\t */\n\t\tawait waiter;\n\t}\n\n\t/**\n\t * Start the HTTP server and wait for it to be fully initialized.\n\t */\n\tasync start(): Promise<void> {\n\t\t/*\n\t\t * Start the server and wait for it to be initialized before returning\n\t\t */\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tthis.#serverPromise = this.main(function() {\n\t\t\t\tresolve();\n\t\t\t}).catch(function(error: unknown) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n\t\t\t\treject(error);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Wait for the server to terminate. This will only resolve once the\n\t * server has been stopped.\n\t */\n\tasync wait(): Promise<void> {\n\t\tawait this.#serverPromise;\n\t}\n\n\t/**\n\t * Stop the HTTP server and wait for it to be fully terminated.\n\t */\n\tasync stop(): Promise<void> {\n\t\tthis.#server?.close();\n\t\t// @ts-ignore\n\t\tthis.#server = undefined;\n\t\tawait this.wait();\n\t}\n\n\t/**\n\t * Get the URL of the server, which can be used to make requests to\n\t * it. This will use \"localhost\" as the hostname and the port that\n\t * the server is listening on by default but can be overridden by\n\t * setting a custom URL.\n\t */\n\tget url(): string {\n\t\tif (this.port === 0 || this.#server === undefined) {\n\t\t\tthrow(new Error('Server not started'));\n\t\t}\n\n\t\tif (this.#url !== undefined) {\n\t\t\tlet newURL: string;\n\t\t\tif (typeof this.#url === 'string') {\n\t\t\t\tnewURL = this.#url;\n\t\t\t} else if (this.#url instanceof URL || ('port' in this.#url && 'hostname' in this.#url && 'toString' in this.#url)) {\n\t\t\t\tnewURL = this.#url.toString();\n\t\t\t} else if (typeof this.#url === 'function') {\n\t\t\t\tnewURL = this.#url(this);\n\t\t\t} else {\n\t\t\t\tassertNever(this.#url);\n\t\t\t}\n\n\t\t\tconst newURLObj = new URL(newURL);\n\t\t\tnewURLObj.pathname = '/';\n\t\t\tnewURLObj.search = '';\n\n\t\t\tconst retval = newURLObj.toString();\n\n\t\t\treturn(retval);\n\t\t}\n\n\t\tconst urlObj = new URL('http://localhost');\n\t\turlObj.port = String(this.#urlParts?.port ?? this.port);\n\t\turlObj.hostname = this.#urlParts?.hostname ?? 'localhost';\n\t\turlObj.protocol = this.#urlParts?.protocol ?? 'http:';\n\t\turlObj.pathname = '/';\n\t\turlObj.search = '';\n\n\t\tconst retval = urlObj.toString();\n\n\t\treturn(retval);\n\t}\n\n\tset url(value: undefined | string | URL | ((object: this) => string)) {\n\t\tthis.#urlParts = undefined;\n\t\tthis.#url = value;\n\t}\n\n\t[Symbol.asyncDispose](): Promise<void> {\n\t\treturn(this.stop());\n\t}\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/http-server/index.ts"],"names":[],"mappings":"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","sourcesContent":["import * as http from 'http';\n\nimport {\n\tKeetaAnchorError,\n\tKeetaAnchorUserError\n} from '../error.js';\nimport type { JSONSerializable } from '../utils/json.js';\nimport type { Logger, LogLevel } from '../log/index.js';\nimport type {\n\tCertificateChainConfig,\n\tResolvedCertificateChainRequirement\n} from '../utils/certificate-network.js';\nimport { Log } from '../log/index.js';\nimport { createAssert } from 'typia';\nimport { assertNever } from '../utils/never.js';\nimport { resolveCertificateChainConfig } from '../utils/certificate-network.js';\n\nexport const AssertHTTPErrorData: (input: unknown) => { error: string; statusCode?: number; contentType?: string; } = createAssert<{ error: string; statusCode?: number; contentType?: string; }>();\n\n/**\n * The maximum size of a request (128MiB)\n */\nconst MAX_REQUEST_SIZE = 128 * (1024 ** 2);\n\ntype RouteHandlerMethod<BodyDataType = JSONSerializable | undefined> = (urlParams: Map<string, string>, postData: BodyDataType, requestHeaders: http.IncomingHttpHeaders, requestUrl: URL) => Promise<{ output: string | Buffer; statusCode?: number; contentType?: string; headers?: { [headerName: string]: string; }; }>;\ntype RouteHandlerWithConfig = {\n\tbodyType: 'raw';\n\tmaxBodySize?: number;\n\thandler: RouteHandlerMethod<Buffer>;\n} | {\n\tbodyType: 'parsed';\n\tmaxBodySize?: number;\n\thandler: RouteHandlerMethod;\n} | {\n\tbodyType: 'none';\n\thandler: RouteHandlerMethod<undefined>;\n};\ntype RouteHandler = RouteHandlerMethod | RouteHandlerWithConfig;\nexport type Routes = { [route: string]: RouteHandler };\nexport type RoutesWithConfigs = { [route: string]: RouteHandlerWithConfig };\n\nexport interface KeetaAnchorHTTPServerConfig {\n\t/**\n\t * Identifier for the server instance -- if one is not given\n\t * a random one will be generated.\n\t */\n\tid?: string;\n\n\t/**\n\t * The port for the HTTP server to listen on (default is an ephemeral port).\n\t */\n\tport?: number;\n\n\t/**\n\t * Enable debug logging\n\t */\n\tlogger?: Logger | undefined;\n\t/**\n\t * The URL for the server. By default, this will be generated based on\n\t * the port and will use \"localhost\" as the hostname, but it can be\n\t * overridden by setting this to a string, URL, or function that\n\t * generates the URL\n\t */\n\turl?: undefined | string | URL | ((object: KeetaNetAnchorHTTPServer) => string) | {\n\t\thostname?: string;\n\t\tport?: number;\n\t\tprotocol?: string;\n\t};\n\n\t/**\n\t * Optional on-chain cert-chain gate. When set, authenticated callers\n\t * MUST have a published cert chaining to one of `trustedIssuers`.\n\t */\n\trequireCertificateChain?: CertificateChainConfig | undefined;\n};\n\nexport abstract class KeetaNetAnchorHTTPServer<ConfigType extends KeetaAnchorHTTPServerConfig = KeetaAnchorHTTPServerConfig> implements Required<KeetaAnchorHTTPServerConfig> {\n\treadonly port: NonNullable<KeetaAnchorHTTPServerConfig['port']>;\n\treadonly logger: NonNullable<KeetaAnchorHTTPServerConfig['logger']>;\n\treadonly id: NonNullable<KeetaAnchorHTTPServerConfig['id']>;\n\t/**\n\t * Resolved cert-chain requirement, or `undefined` when disabled.\n\t * @see {@link requireCertificateChain}.\n\t */\n\tprotected readonly resolvedCertificateChainRequirement: ResolvedCertificateChainRequirement | undefined;\n\t#serverPromise?: Promise<void>;\n\t#server?: http.Server;\n\t#urlParts: undefined | { hostname?: string; port?: number; protocol?: string; };\n\t#url: undefined | string | URL | ((object: this) => string);\n\treadonly #config: ConfigType;\n\n\tconstructor(config: ConfigType) {\n\t\tthis.#config = { ...config };\n\t\tthis.port = config.port ?? 0;\n\t\tthis.id = config.id ?? crypto.randomUUID();\n\t\tthis.logger = config.logger ?? Log.Legacy('ANCHOR');\n\t\tthis.resolvedCertificateChainRequirement = resolveCertificateChainConfig(config.requireCertificateChain);\n\n\t\tif (config.url !== undefined) {\n\t\t\tif (config.url instanceof URL || typeof config.url === 'string') {\n\t\t\t\tthis.#url = config.url;\n\t\t\t\tthis.#urlParts = undefined;\n\t\t\t} else if (typeof config.url === 'function') {\n\t\t\t\t/**\n\t\t\t\t * The parameter for the call back is typed as\n\t\t\t\t * `this`, which means any subclass is typed\n\t\t\t\t * but the interface can't identify that --\n\t\t\t\t * instead it types it as the base class\n\t\t\t\t * (KeetaNetAnchorHTTPServer), which means it\n\t\t\t\t * can't be assigned to the type of `#url`\n\t\t\t\t * without overriding the type check. However,\n\t\t\t\t * we know that `this` will be at least\n\t\t\t\t * compatible with the base class.\n\t\t\t\t */\n\t\t\t\t// @ts-ignore\n\t\t\t\tthis.#url = config.url;\n\t\t\t\tthis.#urlParts = undefined;\n\t\t\t} else {\n\t\t\t\tthis.#url = undefined;\n\t\t\t\tthis.#urlParts = config.url;\n\t\t\t}\n\t\t}\n\t}\n\n\tprotected abstract initRoutes(config: ConfigType): Promise<Routes>;\n\n\t/**\n\t * Public view of the cert-chain config, or `undefined` when disabled.\n\t */\n\tget requireCertificateChain(): CertificateChainConfig | undefined {\n\t\treturn(this.resolvedCertificateChainRequirement);\n\t}\n\n\t/**\n\t * Trusted-issuer DNs metadata. Is `undefined` when the gate is not configured.\n\t */\n\tprotected acceptedIssuerDNs(): { name: string; value: string }[][] | undefined {\n\t\tconst requirement = this.resolvedCertificateChainRequirement;\n\t\tif (requirement === undefined) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\treturn(requirement.acceptedIssuerDNs);\n\t}\n\n\tprivate static routeMatch(requestURL: URL, routeURL: URL): ({ match: true; params: Map<string, string>; wildcard?: { prefixLength: number }} | { match: false }) {\n\t\tconst requestURLPaths = requestURL.pathname.split('/');\n\t\tconst routeURLPaths = routeURL.pathname.split('/');\n\n\t\t// Check if route ends with wildcard /**\n\t\tconst isWildcard = routeURLPaths.length > 0 && routeURLPaths[routeURLPaths.length - 1] === '**';\n\t\tif (isWildcard) {\n\t\t\t// For wildcard routes, request must have more segments than route prefix (minus the **)\n\t\t\t// This ensures at least one segment is captured by the wildcard\n\t\t\tconst prefixLength = routeURLPaths.length - 1;\n\t\t\tif (requestURLPaths.length <= prefixLength) {\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\n\t\t\t// Check that prefix segments match\n\t\t\tconst params = new Map<string, string>();\n\t\t\tfor (let partIndex = 0; partIndex < prefixLength; partIndex++) {\n\t\t\t\tconst requestPath = requestURLPaths[partIndex];\n\n\t\t\t\tconst routePath = routeURLPaths[partIndex];\n\t\t\t\tif (routePath === undefined || requestPath === undefined) {\n\t\t\t\t\treturn({ match: false });\n\t\t\t\t}\n\n\t\t\t\tif (routePath.startsWith(':')) {\n\t\t\t\t\tparams.set(routePath.slice(1), requestPath);\n\t\t\t\t} else if (requestPath !== routePath) {\n\t\t\t\t\treturn({ match: false });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Capture the remainder as the wildcard param\n\t\t\t// Filter empty segments to handle trailing slashes correctly\n\t\t\tconst remainder = requestURLPaths.slice(prefixLength)\n\t\t\t\t.filter(function(s) {\n\t\t\t\t\treturn(s !== '');\n\t\t\t\t})\n\t\t\t\t.join('/');\n\n\t\t\tif (remainder === '') {\n\t\t\t\t// Reject if wildcard would capture nothing\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\n\t\t\tparams.set('**', remainder);\n\n\t\t\treturn({ match: true, params: params, wildcard: { prefixLength }});\n\t\t}\n\n\t\t// Non-wildcard: require exact segment count\n\t\tif (requestURLPaths.length !== routeURLPaths.length) {\n\t\t\treturn({ match: false });\n\t\t}\n\n\t\tconst params = new Map<string, string>();\n\t\tfor (let partIndex = 0; partIndex < requestURLPaths.length; partIndex++) {\n\t\t\tconst requestPath = requestURLPaths[partIndex];\n\t\t\tconst routePath = routeURLPaths[partIndex];\n\n\t\t\tif (routePath === undefined || requestPath === undefined) {\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\n\t\t\tif (routePath.startsWith(':')) {\n\t\t\t\tparams.set(routePath.slice(1), requestPath);\n\t\t\t} else if (requestPath !== routePath) {\n\t\t\t\treturn({ match: false });\n\t\t\t}\n\t\t}\n\n\t\treturn({ match: true, params: params });\n\t}\n\n\tprivate static routeFind(method: string, requestURL: URL, routes: Routes): { route: Routes[keyof Routes]; params: Map<string, string> } | null {\n\t\tlet wildcardMatch: { route: Routes[keyof Routes]; params: Map<string, string> } | null = null;\n\t\tlet wildcardPrefixLength = -1;\n\n\t\tfor (const routeKey in routes) {\n\t\t\tconst route = routes[routeKey];\n\t\t\tif (route === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst [routeMethod, ...routePathParts] = routeKey.split(' ');\n\t\t\tconst routePath = `/${routePathParts.join(' ')}`.replace(/^\\/+/, '/');\n\n\t\t\tif (method !== routeMethod) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst routeURL = new URL(routePath, 'http://localhost');\n\t\t\tconst matchResult = this.routeMatch(requestURL, routeURL);\n\t\t\tif (matchResult.match) {\n\t\t\t\t// Exact matches take priority over wildcard matches\n\t\t\t\tif (matchResult.wildcard === undefined) {\n\t\t\t\t\treturn({\n\t\t\t\t\t\troute: route,\n\t\t\t\t\t\tparams: matchResult.params\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\t// Keep the most specific wildcard (longest prefix wins)\n\t\t\t\tif (matchResult.wildcard.prefixLength > wildcardPrefixLength) {\n\t\t\t\t\twildcardPrefixLength = matchResult.wildcard.prefixLength;\n\t\t\t\t\twildcardMatch = {\n\t\t\t\t\t\troute: route,\n\t\t\t\t\t\tparams: matchResult.params\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Return most specific wildcard match if no exact match found\n\t\treturn(wildcardMatch);\n\t}\n\n\tprivate static addCORS(routes: Routes): RoutesWithConfigs {\n\t\tconst newRoutes: RoutesWithConfigs = {};\n\n\t\tconst validMethods = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']);\n\n\t\tconst methodsByPath: { [key: string]: Set<string>; } = {};\n\t\tfor (const routeKey in routes) {\n\t\t\tconst methodAndPath = routeKey.split(' ');\n\t\t\tconst method = methodAndPath[0];\n\t\t\tconst path = methodAndPath.slice(1).join(' ');\n\n\t\t\tif (method === undefined || path === undefined) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!validMethods.has(method)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!(path in methodsByPath)) {\n\t\t\t\tmethodsByPath[path] = new Set<string>();\n\t\t\t}\n\n\t\t\tif (methodsByPath[path] === undefined) {\n\t\t\t\tthrow(new Error(`internal error: methodsByPath missing path for ${path}`));\n\t\t\t}\n\n\t\t\tmethodsByPath[path].add(method);\n\t\t}\n\n\t\tconst seenPaths = new Set<string>();\n\t\tfor (const routeKey in routes) {\n\t\t\tconst methodAndPath = routeKey.split(' ');\n\t\t\tconst method = methodAndPath[0];\n\t\t\tconst path = methodAndPath.slice(1).join(' ');\n\n\t\t\tconst routeHandler = routes[routeKey];\n\t\t\tif (routeHandler === undefined) {\n\t\t\t\tthrow(new Error(`internal error: routeHandler missing for routeKey ${routeKey}`));\n\t\t\t}\n\n\t\t\tlet newRoute: RouteHandlerWithConfig;\n\n\t\t\tif (typeof routeHandler === 'function') {\n\t\t\t\tnewRoute = {\n\t\t\t\t\tbodyType: 'parsed',\n\t\t\t\t\thandler: routeHandler\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tnewRoute = routeHandler;\n\t\t\t}\n\n\t\t\tif (method !== 'ERROR') {\n\t\t\t\tif (method === undefined || path === undefined) {\n\t\t\t\t\tnewRoutes[routeKey] = newRoute;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (!validMethods.has(method)) {\n\t\t\t\t\tnewRoutes[routeKey] = newRoute;\n\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst validMethodsForPath = methodsByPath[path];\n\n\t\t\tlet validMethodsForPathParts: string[] = [];\n\t\t\tif (validMethodsForPath !== undefined) {\n\t\t\t\tvalidMethodsForPath.add('OPTIONS');\n\t\t\t\tvalidMethodsForPathParts = Array.from(validMethodsForPath);\n\t\t\t} else {\n\t\t\t\tvalidMethodsForPathParts = [...Array.from(validMethods), 'OPTIONS'];\n\t\t\t}\n\n\t\t\tnewRoutes[routeKey] = {\n\t\t\t\t...newRoute,\n\t\t\t\tasync handler(...args: Parameters<RouteHandlerMethod<unknown>>) {\n\t\t\t\t\t// This is typed properly, but TS can't infer it here\n\t\t\t\t\t// @ts-ignore\n\t\t\t\t\tconst retval = await newRoute.handler(...args);\n\n\t\t\t\t\t/* Add CORS headers to the response for the original route handler */\n\t\t\t\t\tif (retval.contentType === 'application/json' || retval.contentType === undefined) {\n\t\t\t\t\t\tif (!('headers' in retval) || retval.headers === undefined) {\n\t\t\t\t\t\t\tretval.headers = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tretval.headers['Access-Control-Allow-Origin'] = '*';\n\t\t\t\t\t}\n\n\t\t\t\t\treturn(retval);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (!seenPaths.has(path) && path !== '' && path !== undefined) {\n\t\t\t\tconst corsRouteKey = `OPTIONS ${path}`;\n\n\t\t\t\tnewRoutes[corsRouteKey] = {\n\t\t\t\t\tbodyType: 'none',\n\t\t\t\t\tasync handler() {\n\t\t\t\t\t\treturn({\n\t\t\t\t\t\t\toutput: '',\n\t\t\t\t\t\t\tstatusCode: 204,\n\t\t\t\t\t\t\tcontentType: 'text/plain',\n\t\t\t\t\t\t\theaders: {\n\t\t\t\t\t\t\t\t'Access-Control-Allow-Origin': '*',\n\t\t\t\t\t\t\t\t'Access-Control-Allow-Methods': validMethodsForPathParts.join(', '),\n\t\t\t\t\t\t\t\t'Access-Control-Allow-Headers': 'Content-Type',\n\t\t\t\t\t\t\t\t'Access-Control-Max-Age': '86400'\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t\tseenPaths.add(path);\n\t\t\t}\n\t\t}\n\n\t\treturn(newRoutes);\n\t}\n\n\tprivate async main(onSetPort?: (port: number) => void): Promise<void> {\n\t\tthis.logger?.debug('KeetaAnchorHTTP.Server', 'Starting HTTP server...');\n\n\t\tconst port = this.port;\n\n\t\tconst routes = KeetaNetAnchorHTTPServer.addCORS({\n\t\t\tERROR: async function(_ignore_params, postData) {\n\t\t\t\tconst errorInfo = AssertHTTPErrorData(postData);\n\n\t\t\t\tconst retval = {\n\t\t\t\t\toutput: errorInfo.error,\n\t\t\t\t\tstatusCode: errorInfo.statusCode ?? 400,\n\t\t\t\t\tcontentType: errorInfo.contentType ?? 'text/plain'\n\t\t\t\t};\n\n\t\t\t\treturn(retval);\n\t\t\t},\n\t\t\t...(await this.initRoutes(this.#config))\n\t\t});\n\n\t\tconst server = new http.Server(async (request, response) => {\n\t\t\t/*\n\t\t\t * Get the Base URL from the request Host header (if\n\t\t\t * available) or default to localhost. This is used\n\t\t\t * to construct the full URL for routing.\n\t\t\t */\n\t\t\tconst inputURLBaseRaw = new URL(`http://${request.headers.host ?? 'localhost'}`);\n\t\t\tconst inputURLBase = inputURLBaseRaw.protocol + '//' + inputURLBaseRaw.host;\n\n\t\t\t/*\n\t\t\t * Normalize the input URL by stripping leading slashes and\n\t\t\t * combining it with the base URL to get the full URL for routing.\n\t\t\t */\n\t\t\tconst inputURLRaw = (request.url ?? '/').replace(/^\\/+/, '/');\n\t\t\tconst inputURLObject = new URL(inputURLRaw, 'http://localhost');\n\t\t\tconst inputURL = inputURLObject.pathname + (function() {\n\t\t\t\tif (inputURLObject.search === '') {\n\t\t\t\t\treturn('');\n\t\t\t\t}\n\n\t\t\t\treturn('?' + inputURLObject.searchParams.toString());\n\t\t\t})();\n\t\t\tconst url = new URL(inputURL, inputURLBase);\n\t\t\tconst method = request.method ?? 'GET';\n\n\t\t\t/*\n\t\t\t * Finalize the response by syncing the logger and ending\n\t\t\t * the response.\n\t\t\t */\n\t\t\tconst responseFinalize = async () => {\n\t\t\t\tif ('sync' in this.logger && typeof this.logger.sync === 'function') {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait this.logger.sync();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* ignore errors */\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tresponse.end();\n\t\t\t};\n\n\t\t\t/*\n\t\t\t * If the request is malformed, reject it immediately\n\t\t\t */\n\t\t\tif (inputURLRaw.at(0) !== '/') {\n\t\t\t\tresponse.statusCode = 400;\n\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\tresponse.write('Bad Request');\n\t\t\t\tawait responseFinalize();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Lookup the route based on the request\n\t\t\t */\n\t\t\tconst requestedRouteAndParams = KeetaNetAnchorHTTPServer.routeFind(method, url, routes);\n\t\t\tif (requestedRouteAndParams === null) {\n\t\t\t\tresponse.statusCode = 404;\n\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\tresponse.write('Not Found');\n\t\t\t\tawait responseFinalize();\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Extract the route handler and the parameters from\n\t\t\t * the request\n\t\t\t */\n\t\t\tconst { route, params } = requestedRouteAndParams;\n\n\t\t\t/**\n\t\t\t * Attempt to run the route, catch any errors\n\t\t\t */\n\t\t\tlet result: Awaited<ReturnType<RouteHandlerMethod>> | undefined = undefined;\n\t\t\tlet generatedResult = false;\n\t\t\ttry {\n\t\t\t\tif (!request.method) {\n\t\t\t\t\tthrow(new Error('internal error: No request method'));\n\t\t\t\t}\n\n\t\t\t\tlet bodyData: JSONSerializable | Buffer | undefined;\n\n\t\t\t\tconst shouldCheckBody = ['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method);\n\n\t\t\t\tif (typeof route === 'function') {\n\t\t\t\t\tthrow(new Error('internal error: Route handler missing body type configuration, should have been added in addCORS'));\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * If POST'ing, PUT'ing, or PATCH'ing, read and parse the request body\n\t\t\t\t */\n\t\t\t\tif (shouldCheckBody && route.bodyType !== 'none') {\n\t\t\t\t\tconst bodySizeLimit = route.maxBodySize ?? MAX_REQUEST_SIZE;\n\n\t\t\t\t\t// Early rejection based on Content-Length header\n\t\t\t\t\tconst contentLength = request.headers['content-length'];\n\t\t\t\t\tif (contentLength !== undefined) {\n\t\t\t\t\t\tconst declaredSize = parseInt(contentLength, 10);\n\t\t\t\t\t\tif (!isNaN(declaredSize) && declaredSize > bodySizeLimit) {\n\t\t\t\t\t\t\trequest.resume();\n\n\t\t\t\t\t\t\tresponse.statusCode = 413;\n\t\t\t\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\t\t\t\tresponse.write('Payload Too Large');\n\n\t\t\t\t\t\t\tawait responseFinalize();\n\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tconst data = await request.map(function(chunk) {\n\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-argument\n\t\t\t\t\t\treturn(Buffer.from(chunk));\n\t\t\t\t\t}).reduce(function(prev, curr) {\n\t\t\t\t\t\tif (prev.length > bodySizeLimit) {\n\t\t\t\t\t\t\tthrow(new Error('Request too large'));\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!Buffer.isBuffer(curr)) {\n\t\t\t\t\t\t\tthrow(new Error(`internal error: Current item is not a buffer -- ${typeof curr}`));\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn(Buffer.concat([prev, curr]));\n\t\t\t\t\t}, Buffer.from(''));\n\n\t\t\t\t\tif (route.bodyType === 'raw') {\n\t\t\t\t\t\tbodyData = data;\n\t\t\t\t\t} else if (route.bodyType === 'parsed' && request.headers['content-type'] === 'application/json') {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n\t\t\t\t\t\t\tbodyData = JSON.parse(data.toString('utf-8'));\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tthrow(new Error('Invalid JSON data'));\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (data.length > 0) {\n\t\t\t\t\t\tthrow(new KeetaAnchorUserError('Unsupported content type'));\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * Call the route handler\n\t\t\t\t */\n\t\t\t\t// @ts-ignore\n\t\t\t\tresult = await route.handler(params, bodyData, request.headers, url);\n\n\t\t\t\tgeneratedResult = true;\n\t\t\t} catch (err) {\n\t\t\t\tlet logLevel: Lowercase<LogLevel> = 'error';\n\t\t\t\tif (KeetaAnchorError.isInstance(err)) {\n\t\t\t\t\t/*\n\t\t\t\t\t * We're able to safely cast this here because the cast\n\t\t\t\t\t * duplicates the logic.\n\t\t\t\t\t */\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/consistent-type-assertions\n\t\t\t\t\tlogLevel = err.logLevel.toLowerCase() as Lowercase<typeof err.logLevel>;\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * If an error occurs, log it and return an error page\n\t\t\t\t */\n\t\t\t\tthis.logger?.[logLevel]('KeetaAnchorHTTP.Server', err);\n\n\t\t\t\t/**\n\t\t\t\t * If it is a user error, provide a user-friendly error page\n\t\t\t\t */\n\t\t\t\tconst errorHandlerRoute = routes['ERROR'];\n\t\t\t\tif (errorHandlerRoute !== undefined) {\n\t\t\t\t\tlet errBody;\n\t\t\t\t\tif (KeetaAnchorError.isInstance(err) && err['userError']) {\n\t\t\t\t\t\terrBody = err.asErrorResponse('application/json');\n\t\t\t\t\t} else {\n\t\t\t\t\t\terrBody = {\n\t\t\t\t\t\t\terror: JSON.stringify({ ok: false, error: 'Internal Server Error' }),\n\t\t\t\t\t\t\tstatusCode: 500,\n\t\t\t\t\t\t\tcontentType: 'application/json'\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\t// @ts-ignore\n\t\t\t\t\tresult = await errorHandlerRoute.handler(new Map(), errBody, request.headers, url);\n\t\t\t\t\tgeneratedResult = true;\n\t\t\t\t}\n\n\t\t\t\tif (!generatedResult) {\n\t\t\t\t\t/**\n\t\t\t\t\t * Otherwise provide a generic error page\n\t\t\t\t\t */\n\t\t\t\t\tresponse.statusCode = 500;\n\t\t\t\t\tresponse.setHeader('Content-Type', 'text/plain');\n\t\t\t\t\tresponse.write('Internal Server Error');\n\t\t\t\t\tawait responseFinalize();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (result === undefined) {\n\t\t\t\tthrow(new Error('internal error: No result'));\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * Write the response to the client\n\t\t\t */\n\t\t\tresponse.statusCode = result.statusCode ?? 200;\n\n\t\t\tfor (const headerKey in result.headers ?? {}) {\n\t\t\t\tconst headerValue = result.headers?.[headerKey];\n\t\t\t\tif (headerValue !== undefined) {\n\t\t\t\t\tresponse.setHeader(headerKey, headerValue);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tresponse.setHeader('Content-Type', result.contentType ?? 'application/json');\n\t\t\tresponse.write(result.output);\n\t\t\tawait responseFinalize();\n\t\t});\n\t\tthis.#server = server;\n\n\t\t/**\n\t\t * Create a promise to wait for the server to close\n\t\t */\n\t\tconst waiter = new Promise<void>((resolve) => {\n\t\t\tserver.on('close', () => {\n\t\t\t\tthis.logger?.debug('KeetaAnchorHTTP.Server', 'Server closed');\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\n\t\t/**\n\t\t * Start listening on the port\n\t\t */\n\t\tserver.listen(port, () => {\n\t\t\tconst address = server.address();\n\t\t\tif (address !== null && typeof address === 'object') {\n\t\t\t\t// @ts-ignore\n\t\t\t\tthis.port = address.port;\n\t\t\t\tonSetPort?.(this.port);\n\t\t\t}\n\t\t\tthis.logger?.debug('KeetaAnchorHTTP.Server', 'Listening on port:', this.port);\n\t\t});\n\n\t\t/**\n\t\t * Wait for the server to close\n\t\t */\n\t\tawait waiter;\n\t}\n\n\t/**\n\t * Start the HTTP server and wait for it to be fully initialized.\n\t */\n\tasync start(): Promise<void> {\n\t\t/*\n\t\t * Start the server and wait for it to be initialized before returning\n\t\t */\n\t\tawait new Promise<void>((resolve, reject) => {\n\t\t\tthis.#serverPromise = this.main(function() {\n\t\t\t\tresolve();\n\t\t\t}).catch(function(error: unknown) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors\n\t\t\t\treject(error);\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Wait for the server to terminate. This will only resolve once the\n\t * server has been stopped.\n\t */\n\tasync wait(): Promise<void> {\n\t\tawait this.#serverPromise;\n\t}\n\n\t/**\n\t * Stop the HTTP server and wait for it to be fully terminated.\n\t */\n\tasync stop(): Promise<void> {\n\t\tthis.#server?.close();\n\t\t// @ts-ignore\n\t\tthis.#server = undefined;\n\t\tawait this.wait();\n\t}\n\n\t/**\n\t * Get the URL of the server, which can be used to make requests to\n\t * it. This will use \"localhost\" as the hostname and the port that\n\t * the server is listening on by default but can be overridden by\n\t * setting a custom URL.\n\t */\n\tget url(): string {\n\t\tif (this.port === 0 || this.#server === undefined) {\n\t\t\tthrow(new Error('Server not started'));\n\t\t}\n\n\t\tif (this.#url !== undefined) {\n\t\t\tlet newURL: string;\n\t\t\tif (typeof this.#url === 'string') {\n\t\t\t\tnewURL = this.#url;\n\t\t\t} else if (this.#url instanceof URL || ('port' in this.#url && 'hostname' in this.#url && 'toString' in this.#url)) {\n\t\t\t\tnewURL = this.#url.toString();\n\t\t\t} else if (typeof this.#url === 'function') {\n\t\t\t\tnewURL = this.#url(this);\n\t\t\t} else {\n\t\t\t\tassertNever(this.#url);\n\t\t\t}\n\n\t\t\tconst newURLObj = new URL(newURL);\n\t\t\tnewURLObj.pathname = '/';\n\t\t\tnewURLObj.search = '';\n\n\t\t\tconst retval = newURLObj.toString();\n\n\t\t\treturn(retval);\n\t\t}\n\n\t\tconst urlObj = new URL('http://localhost');\n\t\turlObj.port = String(this.#urlParts?.port ?? this.port);\n\t\turlObj.hostname = this.#urlParts?.hostname ?? 'localhost';\n\t\turlObj.protocol = this.#urlParts?.protocol ?? 'http:';\n\t\turlObj.pathname = '/';\n\t\turlObj.search = '';\n\n\t\tconst retval = urlObj.toString();\n\n\t\treturn(retval);\n\t}\n\n\tset url(value: undefined | string | URL | ((object: this) => string)) {\n\t\tthis.#urlParts = undefined;\n\t\tthis.#url = value;\n\t}\n\n\t[Symbol.asyncDispose](): Promise<void> {\n\t\treturn(this.stop());\n\t}\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { HTTPSignedField } from "./http-server/common.js";
1
2
  import type { Logger } from "./log/index.js";
2
3
  import type { ToValuizable } from "./resolver.js";
3
4
  /**
@@ -9,6 +10,22 @@ export type ClientRenderableContent = {
9
10
  type: 'markdown' | 'plaintext';
10
11
  content: string;
11
12
  };
13
+ /**
14
+ * Authentication requirement attached to a service operation endpoint.
15
+ */
16
+ export type ServiceMetadataAuthenticationType = {
17
+ method: 'keeta-account';
18
+ type: 'required' | 'optional' | 'none';
19
+ };
20
+ /**
21
+ * Operation endpoint exposed by a service.
22
+ */
23
+ export type ServiceMetadataEndpoint = string | {
24
+ url: string;
25
+ options?: {
26
+ authentication?: ServiceMetadataAuthenticationType;
27
+ };
28
+ };
12
29
  export interface AnchorMetadataLegalField {
13
30
  disclaimers?: {
14
31
  purpose: 'general';
@@ -22,6 +39,29 @@ export interface SharedAnchorMetadataLegalExtension {
22
39
  */
23
40
  legal?: AnchorMetadataLegalField;
24
41
  }
42
+ /**
43
+ * Signature over `{ operations, legal }` for a service entry. `account` and
44
+ * `signed` are coupled at runtime: either both are absent (unsigned entry)
45
+ * or both are present (signed entry that MUST verify). The coupling cannot
46
+ * be expressed at the type level without breaking `JSONSerializable`
47
+ * compatibility, so consumers MUST treat one-sided forms as malformed.
48
+ */
49
+ export type SharedAnchorMetadataSignedExtension = {
50
+ account?: string;
51
+ signed?: HTTPSignedField;
52
+ };
53
+ export type SharedAnchorCallerCertificateRequirementMetadata = {
54
+ /**
55
+ * Issuer DNs this anchor accepts for caller authentication. Outer array
56
+ * is any-of (OR), inner array is all-of (AND) within a single DN.
57
+ * When present, callers MUST present an on-chain certificate that chains
58
+ * to an issuer whose subject DN matches one of these.
59
+ */
60
+ acceptedIssuerDNs?: {
61
+ name: string;
62
+ value: string;
63
+ }[][];
64
+ };
25
65
  export declare function resolveSharedAnchorMetadataLegalExtension(metadata: ToValuizable<AnchorMetadataLegalField> | undefined, options: {
26
66
  logger?: Logger | undefined;
27
67
  }): Promise<SharedAnchorMetadataLegalExtension>;
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.types.d.ts","sourceRoot":"","sources":["../../src/lib/metadata.types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAAE,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;CAAE,CAAC;AAG3F,MAAM,WAAW,wBAAwB;IACxC,WAAW,CAAC,EAAE;QACb,OAAO,EAAE,SAAS,CAAC;QACnB,OAAO,EAAE,uBAAuB,CAAC;KACjC,EAAE,GAAG,SAAS,CAAC;CAChB;AAED,MAAM,WAAW,kCAAkC;IAClD;;;OAGG;IACH,KAAK,CAAC,EAAE,wBAAwB,CAAC;CACjC;AAWD,wBAAsB,yCAAyC,CAAC,QAAQ,EAAE,YAAY,CAAC,wBAAwB,CAAC,GAAG,SAAS,EAAE,OAAO,EAAE;IACtI,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAkD9C"}
1
+ {"version":3,"file":"metadata.types.d.ts","sourceRoot":"","sources":["../../src/lib/metadata.types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGlD;;;;GAIG;AACH,MAAM,MAAM,uBAAuB,GAAG;IAAE,IAAI,EAAE,UAAU,GAAG,WAAW,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;CAAE,CAAC;AAG3F;;GAEG;AACH,MAAM,MAAM,iCAAiC,GAAG;IAC/C,MAAM,EAAE,eAAe,CAAC;IACxB,IAAI,EAAE,UAAU,GAAG,UAAU,GAAG,MAAM,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,iCAAiC,CAAC;KAAE,CAAA;CAAC,CAAC;AAEjI,MAAM,WAAW,wBAAwB;IACxC,WAAW,CAAC,EAAE;QACb,OAAO,EAAE,SAAS,CAAC;QACnB,OAAO,EAAE,uBAAuB,CAAC;KACjC,EAAE,GAAG,SAAS,CAAC;CAChB;AAED,MAAM,WAAW,kCAAkC;IAClD;;;OAGG;IACH,KAAK,CAAC,EAAE,wBAAwB,CAAC;CACjC;AAED;;;;;;GAMG;AACH,MAAM,MAAM,mCAAmC,GAAG;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,eAAe,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gDAAgD,GAAG;IAC9D;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,EAAE,CAAC;CACxD,CAAC;AAWF,wBAAsB,yCAAyC,CAAC,QAAQ,EAAE,YAAY,CAAC,wBAAwB,CAAC,GAAG,SAAS,EAAE,OAAO,EAAE;IACtI,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,GAAG,OAAO,CAAC,kCAAkC,CAAC,CAkD9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"metadata.types.js","sourceRoot":"","sources":["../../src/lib/metadata.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,+BAA+B,CAAC;AA4BlF,KAAK,UAAU,8BAA8B,CAAC,OAA8C;IAC3F,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEzC,OAAM,CAAC;QACN,IAAI,EAAE,iCAAiC,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtE,OAAO,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;KACzC,CAAC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yCAAyC,CAAC,QAA4D,EAAE,OAE7H;IACA,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAM,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAM,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,IAAsD,EAAE;QACvF,MAAM,mBAAmB,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1B,OAAM,CAAC,SAAS,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,WAAU,UAAU;YACnG,MAAM,kBAAkB,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YAEtD,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAE3D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAK,CAAC,IAAI,KAAK,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC;YAED,OAAM,CAAC;gBACN,OAAO,EAAE,OAAO;gBAChB,OAAO,EAAE,MAAM,8BAA8B,CAAC,kBAAkB,CAAC,OAAO,CAAC;aACzE,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;YACxC,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,2CAA2C,EAAE,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1H,CAAC;QACF,CAAC;QAED,OAAM,CAAC,QAAQ,CAAC,CAAC;IAClB,CAAC,CAAC,EAAE,CAAC;IAEL,OAAM,CAAC;QACN,KAAK,EAAE;YACN,WAAW;SACX;KACD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { assertClientRenderableContentType } from \"./metadata.types.generated.js\";\nimport type { Logger } from \"./log/index.js\";\nimport type { ToValuizable } from \"./resolver.js\";\n\n\n/**\n * This is the type of content that can be rendered directly in a client application.\n *\n * There is no guarantee on if/how this content will be displayed, so it should not be used for critical information, rather as a way to provide the user additional context about a transfer.\n */\nexport type ClientRenderableContent = { type: 'markdown' | 'plaintext'; content: string; };\n\n\nexport interface AnchorMetadataLegalField {\n\tdisclaimers?: {\n\t\tpurpose: 'general';\n\t\tcontent: ClientRenderableContent;\n\t}[] | undefined;\n}\n\nexport interface SharedAnchorMetadataLegalExtension {\n\t/**\n\t * Legal details that the anchor wants to share with the user.\n\t * This can include things like disclaimers, terms of service, etc.\n\t */\n\tlegal?: AnchorMetadataLegalField;\n}\n\nasync function resolveClientRenderableContent(content: ToValuizable<ClientRenderableContent>): Promise<ClientRenderableContent> {\n\tconst resolved = await content('object');\n\n\treturn({\n\t\ttype: assertClientRenderableContentType(await resolved.type('string')),\n\t\tcontent: await resolved.content('string')\n\t})\n}\n\nexport async function resolveSharedAnchorMetadataLegalExtension(metadata: ToValuizable<AnchorMetadataLegalField> | undefined, options: {\n\tlogger?: Logger | undefined;\n}): Promise<SharedAnchorMetadataLegalExtension> {\n\tif (!metadata) {\n\t\treturn({});\n\t}\n\n\tconst resolvedField = await metadata('object');\n\n\tif (!resolvedField) {\n\t\treturn({});\n\t}\n\n\tconst disclaimers = await (async (): Promise<AnchorMetadataLegalField['disclaimers']> => {\n\t\tconst resolvedDisclaimers = await resolvedField.disclaimers?.('array');\n\t\tif (!resolvedDisclaimers) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\tconst parsedDisclaimers = await Promise.allSettled(resolvedDisclaimers.map(async function(disclaimer): Promise<NonNullable<AnchorMetadataLegalField['disclaimers']>[number]> {\n\t\t\tconst resolvedDisclaimer = await disclaimer('object');\n\n\t\t\tconst purpose = await resolvedDisclaimer.purpose('string');\n\n\t\t\tif (purpose !== 'general') {\n\t\t\t\tthrow(new Error(`Unsupported disclaimer purpose: ${purpose}`));\n\t\t\t}\n\n\t\t\treturn({\n\t\t\t\tpurpose: purpose,\n\t\t\t\tcontent: await resolveClientRenderableContent(resolvedDisclaimer.content)\n\t\t\t});\n\t\t}));\n\n\t\tconst filtered = [];\n\n\t\tfor (const result of parsedDisclaimers) {\n\t\t\tif (result.status === 'fulfilled') {\n\t\t\t\tfiltered.push(result.value);\n\t\t\t} else {\n\t\t\t\toptions.logger?.warn('resolveSharedAnchorMetadataLegalExtension', 'Failed to resolve disclaimer content', result.reason);\n\t\t\t}\n\t\t}\n\n\t\treturn(filtered);\n\t})();\n\n\treturn({\n\t\tlegal: {\n\t\t\tdisclaimers\n\t\t}\n\t});\n}\n"]}
1
+ {"version":3,"file":"metadata.types.js","sourceRoot":"","sources":["../../src/lib/metadata.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iCAAiC,EAAE,MAAM,+BAA+B,CAAC;AAgElF,KAAK,UAAU,8BAA8B,CAAC,OAA8C;IAC3F,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IAEzC,OAAM,CAAC;QACN,IAAI,EAAE,iCAAiC,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtE,OAAO,EAAE,MAAM,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;KACzC,CAAC,CAAA;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yCAAyC,CAAC,QAA4D,EAAE,OAE7H;IACA,IAAI,CAAC,QAAQ,EAAE,CAAC;QACf,OAAM,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAE/C,IAAI,CAAC,aAAa,EAAE,CAAC;QACpB,OAAM,CAAC,EAAE,CAAC,CAAC;IACZ,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,IAAsD,EAAE;QACvF,MAAM,mBAAmB,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC1B,OAAM,CAAC,SAAS,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,WAAU,UAAU;YACnG,MAAM,kBAAkB,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;YAEtD,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YAE3D,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAK,CAAC,IAAI,KAAK,CAAC,mCAAmC,OAAO,EAAE,CAAC,CAAC,CAAC;YAChE,CAAC;YAED,OAAM,CAAC;gBACN,OAAO,EAAE,OAAO;gBAChB,OAAO,EAAE,MAAM,8BAA8B,CAAC,kBAAkB,CAAC,OAAO,CAAC;aACzE,CAAC,CAAC;QACJ,CAAC,CAAC,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAG,EAAE,CAAC;QAEpB,KAAK,MAAM,MAAM,IAAI,iBAAiB,EAAE,CAAC;YACxC,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBACnC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACP,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,2CAA2C,EAAE,sCAAsC,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YAC1H,CAAC;QACF,CAAC;QAED,OAAM,CAAC,QAAQ,CAAC,CAAC;IAClB,CAAC,CAAC,EAAE,CAAC;IAEL,OAAM,CAAC;QACN,KAAK,EAAE;YACN,WAAW;SACX;KACD,CAAC,CAAC;AACJ,CAAC","sourcesContent":["import { assertClientRenderableContentType } from \"./metadata.types.generated.js\";\nimport type { HTTPSignedField } from \"./http-server/common.js\";\nimport type { Logger } from \"./log/index.js\";\nimport type { ToValuizable } from \"./resolver.js\";\n\n\n/**\n * This is the type of content that can be rendered directly in a client application.\n *\n * There is no guarantee on if/how this content will be displayed, so it should not be used for critical information, rather as a way to provide the user additional context about a transfer.\n */\nexport type ClientRenderableContent = { type: 'markdown' | 'plaintext'; content: string; };\n\n\n/**\n * Authentication requirement attached to a service operation endpoint.\n */\nexport type ServiceMetadataAuthenticationType = {\n\tmethod: 'keeta-account';\n\ttype: 'required' | 'optional' | 'none';\n};\n\n/**\n * Operation endpoint exposed by a service.\n */\nexport type ServiceMetadataEndpoint = string | { url: string; options?: { authentication?: ServiceMetadataAuthenticationType; }};\n\nexport interface AnchorMetadataLegalField {\n\tdisclaimers?: {\n\t\tpurpose: 'general';\n\t\tcontent: ClientRenderableContent;\n\t}[] | undefined;\n}\n\nexport interface SharedAnchorMetadataLegalExtension {\n\t/**\n\t * Legal details that the anchor wants to share with the user.\n\t * This can include things like disclaimers, terms of service, etc.\n\t */\n\tlegal?: AnchorMetadataLegalField;\n}\n\n/**\n * Signature over `{ operations, legal }` for a service entry. `account` and\n * `signed` are coupled at runtime: either both are absent (unsigned entry)\n * or both are present (signed entry that MUST verify). The coupling cannot\n * be expressed at the type level without breaking `JSONSerializable`\n * compatibility, so consumers MUST treat one-sided forms as malformed.\n */\nexport type SharedAnchorMetadataSignedExtension = {\n\taccount?: string;\n\tsigned?: HTTPSignedField;\n};\n\nexport type SharedAnchorCallerCertificateRequirementMetadata = {\n\t/**\n\t * Issuer DNs this anchor accepts for caller authentication. Outer array\n\t * is any-of (OR), inner array is all-of (AND) within a single DN.\n\t * When present, callers MUST present an on-chain certificate that chains\n\t * to an issuer whose subject DN matches one of these.\n\t */\n\tacceptedIssuerDNs?: { name: string; value: string }[][];\n};\n\nasync function resolveClientRenderableContent(content: ToValuizable<ClientRenderableContent>): Promise<ClientRenderableContent> {\n\tconst resolved = await content('object');\n\n\treturn({\n\t\ttype: assertClientRenderableContentType(await resolved.type('string')),\n\t\tcontent: await resolved.content('string')\n\t})\n}\n\nexport async function resolveSharedAnchorMetadataLegalExtension(metadata: ToValuizable<AnchorMetadataLegalField> | undefined, options: {\n\tlogger?: Logger | undefined;\n}): Promise<SharedAnchorMetadataLegalExtension> {\n\tif (!metadata) {\n\t\treturn({});\n\t}\n\n\tconst resolvedField = await metadata('object');\n\n\tif (!resolvedField) {\n\t\treturn({});\n\t}\n\n\tconst disclaimers = await (async (): Promise<AnchorMetadataLegalField['disclaimers']> => {\n\t\tconst resolvedDisclaimers = await resolvedField.disclaimers?.('array');\n\t\tif (!resolvedDisclaimers) {\n\t\t\treturn(undefined);\n\t\t}\n\n\t\tconst parsedDisclaimers = await Promise.allSettled(resolvedDisclaimers.map(async function(disclaimer): Promise<NonNullable<AnchorMetadataLegalField['disclaimers']>[number]> {\n\t\t\tconst resolvedDisclaimer = await disclaimer('object');\n\n\t\t\tconst purpose = await resolvedDisclaimer.purpose('string');\n\n\t\t\tif (purpose !== 'general') {\n\t\t\t\tthrow(new Error(`Unsupported disclaimer purpose: ${purpose}`));\n\t\t\t}\n\n\t\t\treturn({\n\t\t\t\tpurpose: purpose,\n\t\t\t\tcontent: await resolveClientRenderableContent(resolvedDisclaimer.content)\n\t\t\t});\n\t\t}));\n\n\t\tconst filtered = [];\n\n\t\tfor (const result of parsedDisclaimers) {\n\t\t\tif (result.status === 'fulfilled') {\n\t\t\t\tfiltered.push(result.value);\n\t\t\t} else {\n\t\t\t\toptions.logger?.warn('resolveSharedAnchorMetadataLegalExtension', 'Failed to resolve disclaimer content', result.reason);\n\t\t\t}\n\t\t}\n\n\t\treturn(filtered);\n\t})();\n\n\treturn({\n\t\tlegal: {\n\t\t\tdisclaimers\n\t\t}\n\t});\n}\n"]}
package/lib/resolver.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as KeetaNetClient from '@keetanetwork/keetanet-client';
2
- import type { GenericAccount as KeetaNetGenericAccount } from '@keetanetwork/keetanet-client/lib/account.js';
2
+ import type { AccountPublicKeyString, GenericAccount as KeetaNetGenericAccount } from '@keetanetwork/keetanet-client/lib/account.js';
3
3
  import * as CurrencyInfo from '@keetanetwork/currency-info';
4
4
  import type { Logger } from './log/index.ts';
5
5
  import type { JSONSerializable } from './utils/json.ts';
@@ -7,7 +7,8 @@ import type { DeepPartial } from './utils/types.ts';
7
7
  import type { AssetLocationString, SupportedAssetsMetadata, AssetMovementRailSearchInput, AnchorCustomLocationMetadata } from '../services/asset-movement/common.js';
8
8
  import type { MovableAssetSearchInput, KeetaNetTokenPublicKeyString } from './asset.js';
9
9
  import type { NotificationChannelType, NotificationSubscriptionType, SupportedChannelConfigurationMetadata } from '../services/notification/common.js';
10
- import type { SharedAnchorMetadataLegalExtension } from './metadata.types.js';
10
+ import type { ServiceMetadataEndpoint, SharedAnchorCallerCertificateRequirementMetadata, SharedAnchorMetadataLegalExtension, SharedAnchorMetadataSignedExtension } from './metadata.types.js';
11
+ import type { VerifiableAccount } from './utils/signing.js';
11
12
  type ExternalURL = {
12
13
  external: '2b828e33-2692-46e9-817e-9b93d63f28fd';
13
14
  url: string;
@@ -28,16 +29,6 @@ type ServiceMetadataCurrencyCodeCanonical = CurrencyInfo.ISOCurrencyCode | `$${s
28
29
  type CurrencySearchInput = ServiceMetadataCurrencyCodeCanonical | CurrencyInfo.ISOCurrencyNumber | CurrencyInfo.Currency;
29
30
  type CurrencySearchCanonical = ServiceMetadataCurrencyCodeCanonical;
30
31
  type CountrySearchInput = CurrencyInfo.ISOCountryCode | CurrencyInfo.ISOCountryNumber | CurrencyInfo.Country;
31
- type ServiceMetadataAuthenticationType = {
32
- method: 'keeta-account';
33
- type: 'required' | 'optional' | 'none';
34
- };
35
- type ServiceMetadataEndpoint = string | {
36
- url: string;
37
- options?: {
38
- authentication?: ServiceMetadataAuthenticationType;
39
- };
40
- };
41
32
  /**
42
33
  * Service Metadata General Structure
43
34
  */
@@ -52,7 +43,7 @@ type ServiceMetadata = {
52
43
  };
53
44
  services: {
54
45
  banking?: {
55
- [id: string]: {
46
+ [id: string]: SharedAnchorMetadataSignedExtension & {
56
47
  operations: {
57
48
  createAccount?: string;
58
49
  };
@@ -62,7 +53,7 @@ type ServiceMetadata = {
62
53
  };
63
54
  };
64
55
  kyc?: {
65
- [id: string]: {
56
+ [id: string]: SharedAnchorMetadataSignedExtension & {
66
57
  operations: {
67
58
  /**
68
59
  * Check if the KYC provider can
@@ -112,7 +103,7 @@ type ServiceMetadata = {
112
103
  /**
113
104
  * Provider ID which identifies the FX provider
114
105
  */
115
- [id: string]: SharedAnchorMetadataLegalExtension & {
106
+ [id: string]: SharedAnchorMetadataLegalExtension & SharedAnchorMetadataSignedExtension & {
116
107
  operations: {
117
108
  /**
118
109
  * Get an estimate for a currency
@@ -175,7 +166,7 @@ type ServiceMetadata = {
175
166
  };
176
167
  };
177
168
  username?: {
178
- [id: string]: {
169
+ [id: string]: SharedAnchorCallerCertificateRequirementMetadata & SharedAnchorMetadataSignedExtension & {
179
170
  operations: {
180
171
  resolve: ServiceMetadataEndpoint;
181
172
  claim?: ServiceMetadataEndpoint;
@@ -190,7 +181,7 @@ type ServiceMetadata = {
190
181
  };
191
182
  };
192
183
  assetMovement?: {
193
- [id: string]: SharedAnchorMetadataLegalExtension & {
184
+ [id: string]: SharedAnchorMetadataLegalExtension & SharedAnchorMetadataSignedExtension & {
194
185
  operations: {
195
186
  [Operation in ('initiateTransfer' | 'simulateTransfer' | 'executeTransfer' | 'getTransferStatus' | 'initiatePersistentForwardingTemplate' | 'createPersistentForwardingTemplate' | 'listPersistentForwardingTemplate' | 'createPersistentForwarding' | 'listPersistentForwarding' | 'listTransactions' | 'shareKYC')]?: ServiceMetadataEndpoint;
196
187
  };
@@ -204,7 +195,7 @@ type ServiceMetadata = {
204
195
  };
205
196
  };
206
197
  storage?: {
207
- [id: string]: {
198
+ [id: string]: SharedAnchorCallerCertificateRequirementMetadata & SharedAnchorMetadataSignedExtension & {
208
199
  operations: {
209
200
  put?: ServiceMetadataEndpoint;
210
201
  get?: ServiceMetadataEndpoint;
@@ -240,7 +231,7 @@ type ServiceMetadata = {
240
231
  };
241
232
  };
242
233
  notification?: {
243
- [id: string]: {
234
+ [id: string]: SharedAnchorCallerCertificateRequirementMetadata & SharedAnchorMetadataSignedExtension & {
244
235
  supportedChannels?: Partial<SupportedChannelConfigurationMetadata>;
245
236
  supportedSubscriptions?: NotificationSubscriptionType[];
246
237
  operations: {
@@ -554,6 +545,13 @@ type ResolverStats = {
554
545
  };
555
546
  type SharedLookupCriteria = {
556
547
  providerIDs?: string[];
548
+ /**
549
+ * Restrict to entries signed by one of the listed accounts. Each entry
550
+ * may be a {@link KeetaNetGenericAccount} or its public-key string
551
+ * form. Entries without a matching `account` are filtered out
552
+ * (including unsigned entries).
553
+ */
554
+ accounts?: (AccountPublicKeyString | VerifiableAccount)[];
557
555
  };
558
556
  declare class Resolver {
559
557
  #private;
@@ -585,5 +583,6 @@ declare class Resolver {
585
583
  clearCache(): void;
586
584
  }
587
585
  export default Resolver;
588
- export type { ServiceMetadata, ServiceMetadataExternalizable, ServiceSearchCriteria, ServiceMetadataEndpoint, ServiceMetadataAuthenticationType, Services, SharedLookupCriteria };
586
+ export type { ServiceMetadata, ServiceMetadataExternalizable, ServiceSearchCriteria, Services, SharedLookupCriteria };
587
+ export type { ServiceMetadataEndpoint, ServiceMetadataAuthenticationType } from './metadata.types.js';
589
588
  //# sourceMappingURL=resolver.d.ts.map