@keetanetwork/anchor 0.0.61 → 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 (98) 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/chaining.d.ts +29 -6
  6. package/lib/chaining.d.ts.map +1 -1
  7. package/lib/chaining.js +61 -24
  8. package/lib/chaining.js.map +1 -1
  9. package/lib/error.d.ts +35 -0
  10. package/lib/error.d.ts.map +1 -1
  11. package/lib/error.generated.d.ts +3 -0
  12. package/lib/error.generated.d.ts.map +1 -0
  13. package/lib/error.generated.js +104 -0
  14. package/lib/error.generated.js.map +1 -0
  15. package/lib/error.js +66 -1
  16. package/lib/error.js.map +1 -1
  17. package/lib/http-server/common.d.ts +20 -2
  18. package/lib/http-server/common.d.ts.map +1 -1
  19. package/lib/http-server/common.js +47 -0
  20. package/lib/http-server/common.js.map +1 -1
  21. package/lib/http-server/index.d.ts +22 -0
  22. package/lib/http-server/index.d.ts.map +1 -1
  23. package/lib/http-server/index.js +23 -0
  24. package/lib/http-server/index.js.map +1 -1
  25. package/lib/metadata.types.d.ts +40 -0
  26. package/lib/metadata.types.d.ts.map +1 -1
  27. package/lib/metadata.types.js.map +1 -1
  28. package/lib/queue/drivers/queue_postgres.d.ts.map +1 -1
  29. package/lib/queue/drivers/queue_postgres.js +47 -43
  30. package/lib/queue/drivers/queue_postgres.js.map +1 -1
  31. package/lib/resolver.d.ts +19 -20
  32. package/lib/resolver.d.ts.map +1 -1
  33. package/lib/resolver.js +1420 -681
  34. package/lib/resolver.js.map +1 -1
  35. package/lib/token-metadata.d.ts.map +1 -1
  36. package/lib/token-metadata.js +1 -1
  37. package/lib/token-metadata.js.map +1 -1
  38. package/lib/utils/certificate-network.d.ts +84 -0
  39. package/lib/utils/certificate-network.d.ts.map +1 -0
  40. package/lib/utils/certificate-network.js +104 -0
  41. package/lib/utils/certificate-network.js.map +1 -0
  42. package/lib/utils/signing.d.ts +12 -0
  43. package/lib/utils/signing.d.ts.map +1 -1
  44. package/lib/utils/signing.js +145 -2
  45. package/lib/utils/signing.js.map +1 -1
  46. package/npm-shrinkwrap.json +18 -18
  47. package/package.json +2 -2
  48. package/services/asset-movement/common.d.ts.map +1 -1
  49. package/services/asset-movement/common.js +7 -53
  50. package/services/asset-movement/common.js.map +1 -1
  51. package/services/asset-movement/server.d.ts +6 -4
  52. package/services/asset-movement/server.d.ts.map +1 -1
  53. package/services/asset-movement/server.js +3 -3
  54. package/services/asset-movement/server.js.map +1 -1
  55. package/services/fx/client.d.ts +2 -1
  56. package/services/fx/client.d.ts.map +1 -1
  57. package/services/fx/client.js +5 -3
  58. package/services/fx/client.js.map +1 -1
  59. package/services/fx/common.js +7 -7
  60. package/services/fx/server.d.ts +9 -7
  61. package/services/fx/server.d.ts.map +1 -1
  62. package/services/fx/server.js +5 -5
  63. package/services/fx/server.js.map +1 -1
  64. package/services/kyc/server.d.ts +6 -4
  65. package/services/kyc/server.d.ts.map +1 -1
  66. package/services/kyc/server.js +3 -3
  67. package/services/kyc/server.js.map +1 -1
  68. package/services/notification/common.d.ts +2 -1
  69. package/services/notification/common.d.ts.map +1 -1
  70. package/services/notification/common.generated.js +20 -20
  71. package/services/notification/common.js +3 -2
  72. package/services/notification/common.js.map +1 -1
  73. package/services/notification/server.d.ts +7 -6
  74. package/services/notification/server.d.ts.map +1 -1
  75. package/services/notification/server.js +25 -62
  76. package/services/notification/server.js.map +1 -1
  77. package/services/storage/clients/contacts.d.ts +5 -11
  78. package/services/storage/clients/contacts.d.ts.map +1 -1
  79. package/services/storage/clients/contacts.js +1 -1
  80. package/services/storage/clients/contacts.js.map +1 -1
  81. package/services/storage/common.d.ts +2 -1
  82. package/services/storage/common.d.ts.map +1 -1
  83. package/services/storage/common.js +7 -2
  84. package/services/storage/common.js.map +1 -1
  85. package/services/storage/server.d.ts +7 -5
  86. package/services/storage/server.d.ts.map +1 -1
  87. package/services/storage/server.js +29 -99
  88. package/services/storage/server.js.map +1 -1
  89. package/services/username/common.d.ts +2 -1
  90. package/services/username/common.d.ts.map +1 -1
  91. package/services/username/common.generated.js +14 -48
  92. package/services/username/common.generated.js.map +1 -1
  93. package/services/username/common.js +3 -2
  94. package/services/username/common.js.map +1 -1
  95. package/services/username/server.d.ts +7 -6
  96. package/services/username/server.d.ts.map +1 -1
  97. package/services/username/server.js +38 -46
  98. package/services/username/server.js.map +1 -1
@@ -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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"queue_postgres.d.ts","sourceRoot":"","sources":["../../../../src/lib/queue/drivers/queue_postgres.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,6BAA6B,EAC7B,wCAAwC,EACxC,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,kCAAkC,EAClC,sBAAsB,EACtB,sBAAsB,EAEtB,MAAM,aAAa,CAAC;AAWrB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,KAAK,EAAE,MAAM,IAAI,CAAC;AAkB9B,KAAK,4CAA4C,GAAG;IACnD;;OAEG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAE7B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,qCAAqC,CAAC,YAAY,SAAS,gBAAgB,GAAG,gBAAgB,EAAE,WAAW,SAAS,gBAAgB,GAAG,gBAAgB,CAAE,YAAW,6BAA6B,CAAC,YAAY,EAAE,WAAW,CAAC;IAChP,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,uBAAuB,CAAiC;IAChE,OAAO,CAAC,uBAAuB,CAAK;IACpC,OAAO,CAAC,mBAAmB,CAAS;IAEpC,QAAQ,CAAC,IAAI,2CAA2C;IACxD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAM;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,WAAW,CAAgD;gBAEvD,OAAO,EAAE,WAAW,CAAC,qBAAqB,CAAC,wCAAwC,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,4CAA4C;YAgBhK,sBAAsB;IAgJpC,OAAO,CAAC,YAAY;YASN,YAAY;YA8CZ,eAAe;YAiBf,aAAa;IA0CrB,GAAG,CAAC,OAAO,EAAE,uBAAuB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA6D1H,SAAS,CAAC,EAAE,EAAE,yBAAyB,EAAE,MAAM,EAAE,sBAAsB,EAAE,SAAS,CAAC,EAAE,kCAAkC,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDpJ,GAAG,CAAC,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAAC,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IA8CpG,KAAK,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,CAAC;IA2EnG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAI,OAAO,CAAC,6BAA6B,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAkB3F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAwC5C"}
1
+ {"version":3,"file":"queue_postgres.d.ts","sourceRoot":"","sources":["../../../../src/lib/queue/drivers/queue_postgres.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACX,6BAA6B,EAC7B,wCAAwC,EACxC,uBAAuB,EACvB,yBAAyB,EACzB,qBAAqB,EACrB,0BAA0B,EAC1B,kCAAkC,EAClC,sBAAsB,EACtB,sBAAsB,EAEtB,MAAM,aAAa,CAAC;AAWrB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,OAAO,KAAK,KAAK,EAAE,MAAM,IAAI,CAAC;AAkB9B,KAAK,4CAA4C,GAAG;IACnD;;OAEG;IACH,IAAI,EAAE,MAAM,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IAE7B;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,qCAAqC,CAAC,YAAY,SAAS,gBAAgB,GAAG,gBAAgB,EAAE,WAAW,SAAS,gBAAgB,GAAG,gBAAgB,CAAE,YAAW,6BAA6B,CAAC,YAAY,EAAE,WAAW,CAAC;IAChP,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;IAC5C,OAAO,CAAC,YAAY,CAAyC;IAC7D,OAAO,CAAC,WAAW,CAAqB;IACxC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,uBAAuB,CAAS;IACxC,OAAO,CAAC,uBAAuB,CAAiC;IAChE,OAAO,CAAC,uBAAuB,CAAK;IACpC,OAAO,CAAC,mBAAmB,CAAS;IAEpC,QAAQ,CAAC,IAAI,2CAA2C;IACxD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAM;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,WAAW,CAAgD;gBAEvD,OAAO,EAAE,WAAW,CAAC,qBAAqB,CAAC,wCAAwC,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,4CAA4C;YAgBhK,sBAAsB;IAiJpC,OAAO,CAAC,YAAY;YASN,YAAY;YAkDZ,eAAe;YAiBf,aAAa;IA0CrB,GAAG,CAAC,OAAO,EAAE,uBAAuB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,EAAE,0BAA0B,GAAG,OAAO,CAAC,yBAAyB,CAAC;IA2D1H,SAAS,CAAC,EAAE,EAAE,yBAAyB,EAAE,MAAM,EAAE,sBAAsB,EAAE,SAAS,CAAC,EAAE,kCAAkC,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAyDpJ,GAAG,CAAC,EAAE,EAAE,yBAAyB,GAAG,OAAO,CAAC,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC,GAAG,IAAI,CAAC;IA8CpG,KAAK,CAAC,MAAM,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,qBAAqB,CAAC,YAAY,EAAE,WAAW,CAAC,EAAE,CAAC;IA2EnG,SAAS,CAAC,IAAI,EAAE,MAAM,GAAI,OAAO,CAAC,6BAA6B,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAkB3F,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAMxB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;CAwC5C"}
@@ -67,7 +67,7 @@ export default class KeetaAnchorQueueStorageDriverPostgres {
67
67
  // Version 1: Initial schema
68
68
  if (currentVersion < 1) {
69
69
  logger?.debug('Applying schema version 1: Initial tables and indexes');
70
- await client.query('BEGIN');
70
+ await client.query('BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED');
71
71
  try {
72
72
  await client.query(`
73
73
  CREATE TABLE IF NOT EXISTS ${this.tableNameEntries} (
@@ -108,15 +108,15 @@ export default class KeetaAnchorQueueStorageDriverPostgres {
108
108
  // Version 2: Partition-aware composite indexes
109
109
  if (currentVersion < 2) {
110
110
  logger?.debug('Applying schema version 2: Partition-aware composite indexes');
111
- // Create new partition-aware indexes (CONCURRENTLY must be outside transaction)
112
- logger?.debug('Creating partition-aware indexes...');
113
- await client.query(`CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_${this.tableNameEntries}_path_status ON ${this.tableNameEntries}(path, status)`);
114
- await client.query(`CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_${this.tableNameEntries}_path_updated ON ${this.tableNameEntries}(path, updated)`);
115
- await client.query(`CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_${this.tableNameEntries}_path_status_updated ON ${this.tableNameEntries}(path, status, updated)`);
116
- await client.query(`CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_${this.tableNameIdempotentKeys}_path_idempotent_id ON ${this.tableNameIdempotentKeys}(path, idempotent_id)`);
117
111
  // Now drop old indexes and record version
118
- await client.query('BEGIN');
112
+ await client.query('BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED');
119
113
  try {
114
+ // Create new partition-aware indexes
115
+ logger?.debug('Creating partition-aware indexes...');
116
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_${this.tableNameEntries}_path_status ON ${this.tableNameEntries}(path, status)`);
117
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_${this.tableNameEntries}_path_updated ON ${this.tableNameEntries}(path, updated)`);
118
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_${this.tableNameEntries}_path_status_updated ON ${this.tableNameEntries}(path, status, updated)`);
119
+ await client.query(`CREATE INDEX IF NOT EXISTS idx_${this.tableNameIdempotentKeys}_path_idempotent_id ON ${this.tableNameIdempotentKeys}(path, idempotent_id)`);
120
120
  // Drop old indexes that are now redundant (these will fail gracefully if indexes don't exist)
121
121
  logger?.debug('Dropping old single-column indexes...');
122
122
  await client.query(`DROP INDEX IF EXISTS idx_${this.tableNameEntries}_status`);
@@ -181,21 +181,25 @@ export default class KeetaAnchorQueueStorageDriverPostgres {
181
181
  }
182
182
  catch (error) {
183
183
  lastError = error;
184
+ let detectedRetryableError = false;
184
185
  if (error instanceof Error) {
185
186
  const errorCode = 'code' in error ? error.code : null;
186
187
  if (errorCode === '40001' || errorCode === '40P01') {
187
- logger?.debug('Serialization failure or deadlock detected');
188
188
  // Track serialization retries for instrumentation
189
189
  this.serializationRetryCount++;
190
- const minBackoff = 100;
191
- const maxBackoff = 30_000;
192
- const backoffIntervalSize = Math.min(maxBackoff - minBackoff, (retry + 50) ** 2);
193
- const backoff = Math.round((Math.random() * backoffIntervalSize)) + minBackoff;
194
- this.methodLogger('runWithRetry')?.debug(`Retrying DB operation in ${backoff}ms (retry #${retry}) from`, new Error().stack);
195
- await asleep(backoff);
196
- continue;
190
+ detectedRetryableError = true;
191
+ logger?.debug('Detected retryable error with code', errorCode);
197
192
  }
198
193
  }
194
+ if (detectedRetryableError) {
195
+ const minBackoff = 100;
196
+ const maxBackoff = 30_000;
197
+ const backoffIntervalSize = Math.min(maxBackoff - minBackoff, (retry + 50) ** 2);
198
+ const backoff = Math.round((Math.random() * backoffIntervalSize)) + minBackoff;
199
+ this.methodLogger('runWithRetry')?.debug(`Retrying DB operation in ${backoff}ms (retry #${retry}) from`, new Error().stack);
200
+ await asleep(backoff);
201
+ continue;
202
+ }
199
203
  throw (error);
200
204
  }
201
205
  }
@@ -222,7 +226,7 @@ export default class KeetaAnchorQueueStorageDriverPostgres {
222
226
  const client = await pool.connect();
223
227
  try {
224
228
  logger?.debug('Starting DB transaction');
225
- await client.query('BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE');
229
+ await client.query('BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED');
226
230
  logger?.debug('DB transaction started');
227
231
  if (debugForceIndexScan) {
228
232
  await client.query('SET LOCAL enable_seqscan TO off');
@@ -253,28 +257,6 @@ export default class KeetaAnchorQueueStorageDriverPostgres {
253
257
  async add(request, info) {
254
258
  return (await this.dbTransaction('add', async (client, logger) => {
255
259
  let entryID = ConvertStringToRequestID(info?.id);
256
- if (entryID) {
257
- const existingEntry = await client.query(`SELECT id FROM ${this.tableNameEntries} WHERE id = $1 AND path = $2`, [entryID, this.pathStr]);
258
- if (existingEntry.rows.length > 0) {
259
- logger?.debug(`Request with id ${String(entryID)} already exists, ignoring`);
260
- return (entryID);
261
- }
262
- await this.toctouDelay?.();
263
- }
264
- const idempotentIDs = info?.idempotentKeys;
265
- if (idempotentIDs) {
266
- const matchingIdempotentEntries = new Set();
267
- for (const idempotentID of idempotentIDs) {
268
- const idempotentEntryExists = await client.query(`SELECT idempotent_id FROM ${this.tableNameIdempotentKeys} WHERE idempotent_id = $1 AND path = $2`, [idempotentID, this.pathStr]);
269
- if (idempotentEntryExists.rows.length > 0) {
270
- matchingIdempotentEntries.add(idempotentID);
271
- }
272
- }
273
- if (matchingIdempotentEntries.size !== 0) {
274
- throw (new Errors.IdempotentExistsError('One or more idempotent entries already exist in the queue', matchingIdempotentEntries));
275
- }
276
- await this.toctouDelay?.();
277
- }
278
260
  entryID ??= ConvertStringToRequestID(crypto.randomUUID());
279
261
  logger?.debug(`Enqueuing request with id ${String(entryID)}`);
280
262
  const currentTime = Date.now();
@@ -283,12 +265,34 @@ export default class KeetaAnchorQueueStorageDriverPostgres {
283
265
  * The status to use for the new entry
284
266
  */
285
267
  const status = info?.status ?? 'pending';
286
- await client.query(`INSERT INTO ${this.tableNameEntries} (id, path, request, output, last_error, status, created, updated, worker, failures)
287
- VALUES ($1, $2, $3, NULL, NULL, $4, $5, $6, NULL, 0)`, [entryID, this.pathStr, requestJSON, status, currentTime, currentTime]);
268
+ const insertedEntry = await client.query(`
269
+ INSERT INTO ${this.tableNameEntries} (
270
+ id, path, request, output, last_error, status,
271
+ created, updated, worker, failures
272
+ ) VALUES ($1, $2, $3, NULL, NULL, $4, $5, $6, NULL, 0)
273
+ ON CONFLICT (id, path) DO NOTHING
274
+ RETURNING id`, [entryID, this.pathStr, requestJSON, status, currentTime, currentTime]);
275
+ if (insertedEntry.rows.length === 0) {
276
+ logger?.debug(`Request with id ${String(entryID)} already exists, ignoring`);
277
+ return (entryID);
278
+ }
279
+ await this.toctouDelay?.();
280
+ const idempotentIDs = info?.idempotentKeys;
288
281
  if (idempotentIDs && idempotentIDs.size > 0) {
289
- for (const idempotentID of idempotentIDs) {
290
- await client.query(`INSERT INTO ${this.tableNameIdempotentKeys} (entry_id, path, idempotent_id) VALUES ($1, $2, $3)`, [entryID, this.pathStr, idempotentID]);
282
+ const keys = Array.from(idempotentIDs);
283
+ const insertedKeys = await client.query(`
284
+ INSERT INTO ${this.tableNameIdempotentKeys}(entry_id, path, idempotent_id)
285
+ SELECT $1, $2, unnest($3::text[])
286
+ ON CONFLICT (idempotent_id, path) DO NOTHING
287
+ RETURNING idempotent_id`, [entryID, this.pathStr, keys]);
288
+ const foundKeySet = new Set(keys);
289
+ for (const row of insertedKeys.rows) {
290
+ foundKeySet.delete(ConvertStringToRequestID(row.idempotent_id));
291
+ }
292
+ if (insertedKeys.rows.length !== keys.length) {
293
+ throw (new Errors.IdempotentExistsError('One or more idempotent entries already exist in the queue', foundKeySet));
291
294
  }
295
+ await this.toctouDelay?.();
292
296
  }
293
297
  return (entryID);
294
298
  }));