@agentuity/server
Advanced tools
+1
-1
@@ -0,4 +1,4 @@ | ||
| export { createServerFetchAdapter, buildClientHeaders, type BuildClientHeadersOptions, type ServiceAdapterConfig, redact, } from '@agentuity/adapter'; | ||
| export * from '@agentuity/core'; | ||
| export { type ColorScheme, ConsoleLogger, createLogger } from './logger.ts'; | ||
| export { createServerFetchAdapter, buildClientHeaders, type BuildClientHeadersOptions, } from './server.ts'; | ||
| export { toJSONSchema } from './schema.ts'; | ||
@@ -5,0 +5,0 @@ export { getContentType, mimeTypes } from './util/mime.ts'; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACN,wBAAwB,EACxB,kBAAkB,EAClB,KAAK,yBAAyB,GAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"} | ||
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,wBAAwB,EACxB,kBAAkB,EAClB,KAAK,yBAAyB,EAC9B,KAAK,oBAAoB,EACzB,MAAM,GACN,MAAM,oBAAoB,CAAC;AAK5B,cAAc,iBAAiB,CAAC;AAGhC,OAAO,EAAE,KAAK,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,eAAe,EACpB,KAAK,kBAAkB,GACvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"} |
+5
-2
@@ -1,6 +0,9 @@ | ||
| // Re-export ALL API modules from core (moved there for browser compatibility) | ||
| // Re-export adapter functions (backward compatibility - prefer @agentuity/adapter) | ||
| export { createServerFetchAdapter, buildClientHeaders, redact, } from '@agentuity/adapter'; | ||
| // Re-export commonly used types from core | ||
| // Note: Full re-export maintained for backward compatibility with CLI and other packages | ||
| // TODO: Phase 2 - Migrate CLI imports to @agentuity/core directly, then remove this re-export | ||
| export * from '@agentuity/core'; | ||
| // Server-specific exports (these remain in @agentuity/server only) | ||
| export { ConsoleLogger, createLogger } from "./logger.js"; | ||
| export { createServerFetchAdapter, buildClientHeaders, } from "./server.js"; | ||
| export { toJSONSchema } from "./schema.js"; | ||
@@ -7,0 +10,0 @@ export { getContentType, mimeTypes } from "./util/mime.js"; |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,cAAc,iBAAiB,CAAC;AAEhC,mEAAmE;AACnE,OAAO,EAAoB,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EACN,wBAAwB,EACxB,kBAAkB,GAElB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAIjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAgC,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"} | ||
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,OAAO,EACN,wBAAwB,EACxB,kBAAkB,EAGlB,MAAM,GACN,MAAM,oBAAoB,CAAC;AAE5B,0CAA0C;AAC1C,yFAAyF;AACzF,8FAA8F;AAC9F,cAAc,iBAAiB,CAAC;AAEhC,mEAAmE;AACnE,OAAO,EAAoB,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC5E,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACN,eAAe,EACf,kBAAkB,EAClB,iBAAiB,GAIjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAgC,MAAM,wBAAwB,CAAC;AAC3F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"} |
@@ -29,3 +29,3 @@ /** | ||
| * | ||
| * Call this BEFORE createApp() in your app.ts: | ||
| * Call this early in your app entry point: | ||
| * | ||
@@ -35,9 +35,5 @@ * @example | ||
| * import { bootstrapRuntimeEnv } from '@agentuity/server'; | ||
| * import { createApp } from '@agentuity/runtime'; | ||
| * | ||
| * // Set up service URLs | ||
| * // Set up service URLs before initializing your app | ||
| * bootstrapRuntimeEnv(); | ||
| * | ||
| * // Now createApp() will use the correct env vars | ||
| * const app = await createApp(); | ||
| * ``` | ||
@@ -44,0 +40,0 @@ */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"runtime-bootstrap.d.ts","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,uBAAuB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,uBAA4B,GAAG,IAAI,CA6C/E"} | ||
| {"version":3,"file":"runtime-bootstrap.d.ts","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,WAAW,uBAAuB;IACvC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,uBAA4B,GAAG,IAAI,CA6C/E"} |
@@ -19,3 +19,3 @@ /** | ||
| * | ||
| * Call this BEFORE createApp() in your app.ts: | ||
| * Call this early in your app entry point: | ||
| * | ||
@@ -25,9 +25,5 @@ * @example | ||
| * import { bootstrapRuntimeEnv } from '@agentuity/server'; | ||
| * import { createApp } from '@agentuity/runtime'; | ||
| * | ||
| * // Set up service URLs | ||
| * // Set up service URLs before initializing your app | ||
| * bootstrapRuntimeEnv(); | ||
| * | ||
| * // Now createApp() will use the correct env vars | ||
| * const app = await createApp(); | ||
| * ``` | ||
@@ -34,0 +30,0 @@ */ |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"file":"runtime-bootstrap.js","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAe7C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAmC,EAAE;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC;IAE5E,6DAA6D;IAC7D,IACC,CAAC,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;QAC/D,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAC5B,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC;IACxC,CAAC;IAED,kDAAkD;IAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC;IACzC,CAAC;IAED,mCAAmC;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,2EAA2E;IAC3E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,WAAW,CAAC,OAAO,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,WAAW,CAAC,IAAI,CAAC;IACnD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,WAAW,CAAC,KAAK,CAAC;IACrD,CAAC;AACF,CAAC"} | ||
| {"version":3,"file":"runtime-bootstrap.js","sourceRoot":"","sources":["../src/runtime-bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAe7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,mBAAmB,CAAC,UAAmC,EAAE;IACxE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC;IAE5E,6DAA6D;IAC7D,IACC,CAAC,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,CAAC;QAC/D,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAC5B,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,OAAO,CAAC;IACxC,CAAC;IAED,kDAAkD;IAClD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,OAAO,CAAC;IACzC,CAAC;IAED,mCAAmC;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;IAC5C,MAAM,WAAW,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;IAE3C,2EAA2E;IAC3E,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,uBAAuB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC5D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,qBAAqB,GAAG,WAAW,CAAC,OAAO,CAAC;IACzD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,sBAAsB,GAAG,WAAW,CAAC,QAAQ,CAAC;IAC3D,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,WAAW,CAAC,IAAI,CAAC;IACnD,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,mBAAmB,GAAG,WAAW,CAAC,KAAK,CAAC;IACrD,CAAC;AACF,CAAC"} |
+14
-8
| { | ||
| "name": "@agentuity/server", | ||
| "version": "2.0.11", | ||
| "version": "3.0.0-alpha.0", | ||
| "license": "Apache-2.0", | ||
@@ -23,17 +23,18 @@ "author": "Agentuity employees and contributors", | ||
| "clean": "rm -rf dist tsconfig.tsbuildinfo", | ||
| "build": "bunx tsc --build --force", | ||
| "typecheck": "bunx tsc --noEmit", | ||
| "build": "tsgo --build --force", | ||
| "typecheck": "tsgo --noEmit", | ||
| "prepublishOnly": "bun run clean && bun run build" | ||
| }, | ||
| "dependencies": { | ||
| "@agentuity/core": "2.0.11", | ||
| "@agentuity/schema": "2.0.11", | ||
| "@agentuity/adapter": "3.0.0-alpha.0", | ||
| "@agentuity/core": "3.0.0-alpha.0", | ||
| "@agentuity/schema": "3.0.0-alpha.0", | ||
| "zod": "^4.3.5" | ||
| }, | ||
| "devDependencies": { | ||
| "@agentuity/test-utils": "2.0.11", | ||
| "@agentuity/test-utils": "3.0.0-alpha.0", | ||
| "@types/bun": "latest", | ||
| "@types/node": "^22.0.0", | ||
| "bun-types": "latest", | ||
| "typescript": "^5.9.0" | ||
| "typescript": "^6.0.2" | ||
| }, | ||
@@ -43,3 +44,8 @@ "publishConfig": { | ||
| }, | ||
| "sideEffects": false | ||
| "sideEffects": false, | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/agentuity/sdk.git", | ||
| "directory": "packages/server" | ||
| } | ||
| } |
+12
-6
@@ -1,2 +0,13 @@ | ||
| // Re-export ALL API modules from core (moved there for browser compatibility) | ||
| // Re-export adapter functions (backward compatibility - prefer @agentuity/adapter) | ||
| export { | ||
| createServerFetchAdapter, | ||
| buildClientHeaders, | ||
| type BuildClientHeadersOptions, | ||
| type ServiceAdapterConfig, | ||
| redact, | ||
| } from '@agentuity/adapter'; | ||
| // Re-export commonly used types from core | ||
| // Note: Full re-export maintained for backward compatibility with CLI and other packages | ||
| // TODO: Phase 2 - Migrate CLI imports to @agentuity/core directly, then remove this re-export | ||
| export * from '@agentuity/core'; | ||
@@ -6,7 +17,2 @@ | ||
| export { type ColorScheme, ConsoleLogger, createLogger } from './logger.ts'; | ||
| export { | ||
| createServerFetchAdapter, | ||
| buildClientHeaders, | ||
| type BuildClientHeadersOptions, | ||
| } from './server.ts'; | ||
| export { toJSONSchema } from './schema.ts'; | ||
@@ -13,0 +19,0 @@ export { getContentType, mimeTypes } from './util/mime.ts'; |
@@ -34,3 +34,3 @@ /** | ||
| * | ||
| * Call this BEFORE createApp() in your app.ts: | ||
| * Call this early in your app entry point: | ||
| * | ||
@@ -40,9 +40,5 @@ * @example | ||
| * import { bootstrapRuntimeEnv } from '@agentuity/server'; | ||
| * import { createApp } from '@agentuity/runtime'; | ||
| * | ||
| * // Set up service URLs | ||
| * // Set up service URLs before initializing your app | ||
| * bootstrapRuntimeEnv(); | ||
| * | ||
| * // Now createApp() will use the correct env vars | ||
| * const app = await createApp(); | ||
| * ``` | ||
@@ -49,0 +45,0 @@ */ |
| import type { FetchRequest, FetchResponse, FetchAdapter, Logger } from '@agentuity/core'; | ||
| import { ServiceException } from '@agentuity/core'; | ||
| interface ServiceAdapterConfig { | ||
| headers: Record<string, string>; | ||
| queryParams?: Record<string, string>; | ||
| onBefore?: (url: string, options: FetchRequest, invoke: () => Promise<void>) => Promise<void>; | ||
| onAfter?: <T>(url: string, options: FetchRequest, response: FetchResponse<T>, err?: InstanceType<typeof ServiceException>) => Promise<void>; | ||
| } | ||
| /** | ||
| * Options for building client request headers. | ||
| */ | ||
| export interface BuildClientHeadersOptions { | ||
| /** API key for authentication (Bearer token) */ | ||
| apiKey?: string; | ||
| /** Organization ID for multi-tenant requests */ | ||
| orgId?: string; | ||
| } | ||
| /** | ||
| * Builds standard headers for Agentuity service clients. | ||
| * | ||
| * This helper creates the header object needed by `createServerFetchAdapter`, | ||
| * handling authentication and multi-tenant scoping consistently across all clients. | ||
| * | ||
| * @param options - Options containing apiKey and/or orgId | ||
| * @returns Headers object ready to pass to createServerFetchAdapter | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * import { buildClientHeaders, createServerFetchAdapter } from '@agentuity/server'; | ||
| * | ||
| * const headers = buildClientHeaders({ apiKey: 'sk_xxx', orgId: 'org_xxx' }); | ||
| * const adapter = createServerFetchAdapter({ headers }, logger); | ||
| * ``` | ||
| */ | ||
| export declare function buildClientHeaders(options: BuildClientHeadersOptions): Record<string, string>; | ||
| /** | ||
| * Redacts the middle of a string while keeping a prefix and suffix visible. | ||
| * Ensures that if the string is too short, everything is redacted. | ||
| * | ||
| * @param input The string to redact | ||
| * @param prefix Number of chars to keep at the start | ||
| * @param suffix Number of chars to keep at the end | ||
| * @param mask Character used for redaction | ||
| */ | ||
| export declare function redact(input: string, prefix?: number, suffix?: number, mask?: string): string; | ||
| declare class ServerFetchAdapter implements FetchAdapter { | ||
| #private; | ||
| constructor(config: ServiceAdapterConfig, logger: Logger); | ||
| private _invoke; | ||
| invoke<T>(url: string, options?: FetchRequest): Promise<FetchResponse<T>>; | ||
| } | ||
| /** | ||
| * Create a Server Side Fetch Adapter to allow the server to add headers and track outgoing requests | ||
| * | ||
| * @param config the service config | ||
| * @returns | ||
| */ | ||
| export declare function createServerFetchAdapter(config: ServiceAdapterConfig, logger: Logger): ServerFetchAdapter; | ||
| export {}; | ||
| //# sourceMappingURL=server.d.ts.map |
| {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,YAAY,EAEZ,aAAa,EACb,YAAY,EACZ,MAAM,EAEN,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,gBAAgB,EAAoC,MAAM,iBAAiB,CAAC;AAGrF,UAAU,oBAAoB;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,OAAO,CAAC,EAAE,CAAC,CAAC,EACX,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,YAAY,EACrB,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,EAC1B,GAAG,CAAC,EAAE,YAAY,CAAC,OAAO,gBAAgB,CAAC,KACvC,OAAO,CAAC,IAAI,CAAC,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACzC,gDAAgD;IAChD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAa7F;AAqKD;;;;;;;;GAQG;AACH,wBAAgB,MAAM,CACrB,KAAK,EAAE,MAAM,EACb,MAAM,GAAE,MAAU,EAClB,MAAM,GAAE,MAAU,EAClB,IAAI,GAAE,MAAY,GAChB,MAAM,CAaR;AAmBD,cAAM,kBAAmB,YAAW,YAAY;;gBAInC,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM;YAoB1C,OAAO;IA0Ef,MAAM,CAAC,CAAC,EACb,GAAG,EAAE,MAAM,EACX,OAAO,GAAE,YAAiC,GACxC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;CAsC5B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,EAAE,MAAM,EAAE,MAAM,sBAEpF"} |
-360
| import { ServiceException, toServiceException, fromResponse } from '@agentuity/core'; | ||
| import { appendFileSync } from 'node:fs'; | ||
| /** | ||
| * Builds standard headers for Agentuity service clients. | ||
| * | ||
| * This helper creates the header object needed by `createServerFetchAdapter`, | ||
| * handling authentication and multi-tenant scoping consistently across all clients. | ||
| * | ||
| * @param options - Options containing apiKey and/or orgId | ||
| * @returns Headers object ready to pass to createServerFetchAdapter | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * import { buildClientHeaders, createServerFetchAdapter } from '@agentuity/server'; | ||
| * | ||
| * const headers = buildClientHeaders({ apiKey: 'sk_xxx', orgId: 'org_xxx' }); | ||
| * const adapter = createServerFetchAdapter({ headers }, logger); | ||
| * ``` | ||
| */ | ||
| export function buildClientHeaders(options) { | ||
| const headers = options.apiKey | ||
| ? { | ||
| Authorization: `Bearer ${options.apiKey}`, | ||
| 'Content-Type': 'application/json', | ||
| } | ||
| : { 'Content-Type': 'application/json' }; | ||
| if (options.orgId) { | ||
| headers['x-agentuity-orgid'] = options.orgId; | ||
| } | ||
| return headers; | ||
| } | ||
| /** | ||
| * Headers that contain sensitive information and should be redacted in debug logs. | ||
| * Includes authentication tokens, API keys, cookies, and proxy credentials. | ||
| */ | ||
| const sensitiveHeaders = new Set([ | ||
| 'authorization', | ||
| 'x-api-key', | ||
| 'cookie', | ||
| 'set-cookie', | ||
| 'proxy-authorization', | ||
| ]); | ||
| /** | ||
| * Check if API debug logging is enabled and return the output destination. | ||
| * Returns: | ||
| * - 'console' if CI=1/true or AGENTUITY_API_DEBUG=1/true | ||
| * - file path string if AGENTUITY_API_DEBUG is set to a path | ||
| * - null if debug logging is disabled (including AGENTUITY_API_DEBUG=0/false) | ||
| */ | ||
| function getDebugOutput() { | ||
| const apiDebug = process.env.AGENTUITY_API_DEBUG?.trim(); | ||
| if (apiDebug) { | ||
| const normalized = apiDebug.toLowerCase(); | ||
| // Check if explicitly disabled | ||
| if (normalized === '0' || normalized === 'false') { | ||
| return null; | ||
| } | ||
| // Check if it's a truthy value (console output) | ||
| if (normalized === '1' || normalized === 'true') { | ||
| return 'console'; | ||
| } | ||
| // Treat any other non-empty value as a file path | ||
| return apiDebug; | ||
| } | ||
| // Fall back to CI environment check | ||
| if (process.env.CI === '1' || process.env.CI === 'true') { | ||
| return 'console'; | ||
| } | ||
| return null; | ||
| } | ||
| /** | ||
| * Format request body for CI debug logging | ||
| */ | ||
| function formatRequestBody(body) { | ||
| if (body === undefined || body === null) { | ||
| return '[no body]'; | ||
| } | ||
| if (typeof body === 'string') { | ||
| return body; | ||
| } | ||
| if (body instanceof Uint8Array) { | ||
| return `[binary data: ${body.length} bytes]`; | ||
| } | ||
| if (body instanceof ArrayBuffer) { | ||
| return `[binary data: ${body.byteLength} bytes]`; | ||
| } | ||
| if (body instanceof ReadableStream) { | ||
| return '[stream]'; | ||
| } | ||
| return String(body); | ||
| } | ||
| /** | ||
| * Format a sensitive header value, preserving Bearer prefix if present. | ||
| */ | ||
| function redactSensitiveHeader(key, value) { | ||
| const _k = key.toLowerCase(); | ||
| // Handle Bearer tokens in authorization and proxy-authorization headers | ||
| if ((_k === 'authorization' || _k === 'proxy-authorization') && value.startsWith('Bearer ')) { | ||
| return `Bearer ${redact(value.substring(7))}`; | ||
| } | ||
| return redact(value); | ||
| } | ||
| /** | ||
| * Format headers as a readable string for debug logging. | ||
| * Sensitive headers (auth tokens, cookies, API keys) are redacted. | ||
| */ | ||
| function formatHeaders(headers) { | ||
| const entries = []; | ||
| if (headers instanceof Headers) { | ||
| headers.forEach((value, key) => { | ||
| const _k = key.toLowerCase(); | ||
| if (sensitiveHeaders.has(_k)) { | ||
| entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`); | ||
| } | ||
| else { | ||
| entries.push(` ${key}: ${value}`); | ||
| } | ||
| }); | ||
| } | ||
| else { | ||
| for (const [key, value] of Object.entries(headers)) { | ||
| const _k = key.toLowerCase(); | ||
| if (sensitiveHeaders.has(_k)) { | ||
| entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`); | ||
| } | ||
| else { | ||
| entries.push(` ${key}: ${value}`); | ||
| } | ||
| } | ||
| } | ||
| return entries.join('\n'); | ||
| } | ||
| /** | ||
| * Log detailed debug information when API requests fail. | ||
| * Output destination is determined by AGENTUITY_API_DEBUG or CI environment variables. | ||
| */ | ||
| function logAPIDebug(url, method, requestHeaders, requestBody, response, responseBody) { | ||
| const output = getDebugOutput(); | ||
| if (!output) { | ||
| return; | ||
| } | ||
| const separator = '='.repeat(60); | ||
| const timestamp = new Date().toISOString(); | ||
| const lines = [ | ||
| '', | ||
| separator, | ||
| `API DEBUG: Request Failed [${timestamp}]`, | ||
| separator, | ||
| '', | ||
| '>>> REQUEST', | ||
| `URL: ${url}`, | ||
| `Method: ${method}`, | ||
| 'Headers:', | ||
| formatHeaders(requestHeaders), | ||
| 'Body:', | ||
| ` ${formatRequestBody(requestBody)}`, | ||
| '', | ||
| '<<< RESPONSE', | ||
| `Status: ${response.status} ${response.statusText}`, | ||
| 'Headers:', | ||
| formatHeaders(response.headers), | ||
| 'Body:', | ||
| ` ${responseBody || '[empty]'}`, | ||
| '', | ||
| separator, | ||
| '', | ||
| ]; | ||
| const content = lines.join('\n'); | ||
| if (output === 'console') { | ||
| console.error(content); | ||
| } | ||
| else { | ||
| // Append to file | ||
| try { | ||
| appendFileSync(output, content + '\n'); | ||
| } | ||
| catch { | ||
| // If file write fails, fall back to console.error | ||
| console.error(`[API DEBUG] Failed to write to ${output}, falling back to console`); | ||
| console.error(content); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Redacts the middle of a string while keeping a prefix and suffix visible. | ||
| * Ensures that if the string is too short, everything is redacted. | ||
| * | ||
| * @param input The string to redact | ||
| * @param prefix Number of chars to keep at the start | ||
| * @param suffix Number of chars to keep at the end | ||
| * @param mask Character used for redaction | ||
| */ | ||
| export function redact(input, prefix = 4, suffix = 4, mask = '*') { | ||
| if (!input) | ||
| return ''; | ||
| // If revealing prefix+suffix would leak too much, fully mask | ||
| if (input.length <= prefix + suffix) { | ||
| return mask.repeat(input.length); | ||
| } | ||
| const start = input.slice(0, prefix); | ||
| const end = input.slice(-suffix); | ||
| const hiddenLength = input.length - prefix - suffix; | ||
| return start + mask.repeat(hiddenLength) + end; | ||
| } | ||
| const redactHeaders = (kv) => { | ||
| const values = []; | ||
| for (const k of Object.keys(kv)) { | ||
| const _k = k.toLowerCase(); | ||
| const v = kv[k]; | ||
| if (v === undefined) { | ||
| continue; | ||
| } | ||
| if (sensitiveHeaders.has(_k)) { | ||
| values.push(`${_k}=${redactSensitiveHeader(k, v)}`); | ||
| } | ||
| else { | ||
| values.push(`${_k}=${v}`); | ||
| } | ||
| } | ||
| return '[' + values.join(',') + ']'; | ||
| }; | ||
| class ServerFetchAdapter { | ||
| #config; | ||
| #logger; | ||
| constructor(config, logger) { | ||
| this.#config = config; | ||
| this.#logger = logger; | ||
| } | ||
| /** | ||
| * Build the final URL with query params appended. | ||
| * This is extracted so both invoke() and _invoke() use the same URL. | ||
| */ | ||
| #buildUrl(url) { | ||
| if (this.#config.queryParams && Object.keys(this.#config.queryParams).length > 0) { | ||
| const urlObj = new URL(url); | ||
| for (const [key, value] of Object.entries(this.#config.queryParams)) { | ||
| urlObj.searchParams.set(key, value); | ||
| } | ||
| return urlObj.toString(); | ||
| } | ||
| return url; | ||
| } | ||
| async _invoke(url, options) { | ||
| // URL already has query params appended by invoke() or direct caller | ||
| const headers = { | ||
| ...options.headers, | ||
| ...this.#config.headers, | ||
| }; | ||
| if (options.contentType) { | ||
| headers['Content-Type'] = options.contentType; | ||
| } | ||
| else if (typeof options.body === 'string' || | ||
| options.body instanceof Uint8Array || | ||
| options.body instanceof ArrayBuffer) { | ||
| headers['Content-Type'] = 'application/octet-stream'; | ||
| } | ||
| // Ensure we request JSON responses for proper error handling | ||
| if (!headers['Accept'] && !headers['accept']) { | ||
| headers['Accept'] = 'application/json'; | ||
| } | ||
| const method = options.method ?? 'POST'; | ||
| this.#logger.trace('sending %s to %s with headers: %s', method, url, redactHeaders(headers)); | ||
| const res = await fetch(url, { | ||
| method, | ||
| body: options.body, | ||
| headers, | ||
| signal: options.signal, | ||
| ...(options.duplex ? { duplex: options.duplex } : {}), | ||
| }); | ||
| if (res.ok) { | ||
| switch (res.status) { | ||
| case 100: | ||
| case 101: | ||
| case 102: | ||
| case 204: | ||
| case 304: | ||
| return { | ||
| ok: true, | ||
| data: undefined, | ||
| response: res, | ||
| }; | ||
| default: | ||
| break; | ||
| } | ||
| if (options?.binary) { | ||
| return { | ||
| ok: true, | ||
| data: undefined, | ||
| response: res, | ||
| }; | ||
| } | ||
| const data = await fromResponse(res); | ||
| return { | ||
| ok: true, | ||
| data, | ||
| response: res, | ||
| }; | ||
| } | ||
| if (res.status === 404) { | ||
| // Log debug info for 404 errors if debugging is enabled | ||
| if (getDebugOutput()) { | ||
| const responseBody = await res.clone().text(); | ||
| logAPIDebug(url, method, headers, options.body, res, responseBody); | ||
| } | ||
| return { | ||
| ok: false, | ||
| response: res, | ||
| }; | ||
| } | ||
| // Clone response to read body for debug logging before toServiceException consumes it | ||
| const responseBody = getDebugOutput() ? await res.clone().text() : ''; | ||
| logAPIDebug(url, method, headers, options.body, res, responseBody); | ||
| const err = await toServiceException(method, url, res); | ||
| throw err; | ||
| } | ||
| async invoke(url, options = { method: 'POST' }) { | ||
| // Build final URL with query params BEFORE hooks, so hooks receive the actual URL | ||
| const finalUrl = this.#buildUrl(url); | ||
| if (this.#config.onBefore) { | ||
| let result = undefined; | ||
| let err = undefined; | ||
| await this.#config.onBefore(finalUrl, options, async () => { | ||
| try { | ||
| result = await this._invoke(finalUrl, options); | ||
| if (this.#config.onAfter) { | ||
| await this.#config.onAfter(finalUrl, options, result); | ||
| } | ||
| } | ||
| catch (ex) { | ||
| err = ex; | ||
| if (this.#config.onAfter && err instanceof ServiceException) { | ||
| await this.#config.onAfter(finalUrl, options, { | ||
| ok: false, | ||
| response: new Response(err.message, { | ||
| status: err.statusCode, | ||
| }), | ||
| }, err); | ||
| } | ||
| } | ||
| }); | ||
| if (err) { | ||
| throw err; | ||
| } | ||
| return result; | ||
| } | ||
| else { | ||
| return await this._invoke(finalUrl, options); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Create a Server Side Fetch Adapter to allow the server to add headers and track outgoing requests | ||
| * | ||
| * @param config the service config | ||
| * @returns | ||
| */ | ||
| export function createServerFetchAdapter(config, logger) { | ||
| return new ServerFetchAdapter(config, logger); | ||
| } | ||
| //# sourceMappingURL=server.js.map |
| {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"} |
-424
| import type { | ||
| FetchRequest, | ||
| FetchErrorResponse, | ||
| FetchResponse, | ||
| FetchAdapter, | ||
| Logger, | ||
| HttpMethod, | ||
| } from '@agentuity/core'; | ||
| import { ServiceException, toServiceException, fromResponse } from '@agentuity/core'; | ||
| import { appendFileSync } from 'node:fs'; | ||
| interface ServiceAdapterConfig { | ||
| headers: Record<string, string>; | ||
| queryParams?: Record<string, string>; | ||
| onBefore?: (url: string, options: FetchRequest, invoke: () => Promise<void>) => Promise<void>; | ||
| onAfter?: <T>( | ||
| url: string, | ||
| options: FetchRequest, | ||
| response: FetchResponse<T>, | ||
| err?: InstanceType<typeof ServiceException> | ||
| ) => Promise<void>; | ||
| } | ||
| /** | ||
| * Options for building client request headers. | ||
| */ | ||
| export interface BuildClientHeadersOptions { | ||
| /** API key for authentication (Bearer token) */ | ||
| apiKey?: string; | ||
| /** Organization ID for multi-tenant requests */ | ||
| orgId?: string; | ||
| } | ||
| /** | ||
| * Builds standard headers for Agentuity service clients. | ||
| * | ||
| * This helper creates the header object needed by `createServerFetchAdapter`, | ||
| * handling authentication and multi-tenant scoping consistently across all clients. | ||
| * | ||
| * @param options - Options containing apiKey and/or orgId | ||
| * @returns Headers object ready to pass to createServerFetchAdapter | ||
| * | ||
| * @example | ||
| * ```typescript | ||
| * import { buildClientHeaders, createServerFetchAdapter } from '@agentuity/server'; | ||
| * | ||
| * const headers = buildClientHeaders({ apiKey: 'sk_xxx', orgId: 'org_xxx' }); | ||
| * const adapter = createServerFetchAdapter({ headers }, logger); | ||
| * ``` | ||
| */ | ||
| export function buildClientHeaders(options: BuildClientHeadersOptions): Record<string, string> { | ||
| const headers: Record<string, string> = options.apiKey | ||
| ? { | ||
| Authorization: `Bearer ${options.apiKey}`, | ||
| 'Content-Type': 'application/json', | ||
| } | ||
| : { 'Content-Type': 'application/json' }; | ||
| if (options.orgId) { | ||
| headers['x-agentuity-orgid'] = options.orgId; | ||
| } | ||
| return headers; | ||
| } | ||
| /** | ||
| * Headers that contain sensitive information and should be redacted in debug logs. | ||
| * Includes authentication tokens, API keys, cookies, and proxy credentials. | ||
| */ | ||
| const sensitiveHeaders = new Set([ | ||
| 'authorization', | ||
| 'x-api-key', | ||
| 'cookie', | ||
| 'set-cookie', | ||
| 'proxy-authorization', | ||
| ]); | ||
| /** | ||
| * Check if API debug logging is enabled and return the output destination. | ||
| * Returns: | ||
| * - 'console' if CI=1/true or AGENTUITY_API_DEBUG=1/true | ||
| * - file path string if AGENTUITY_API_DEBUG is set to a path | ||
| * - null if debug logging is disabled (including AGENTUITY_API_DEBUG=0/false) | ||
| */ | ||
| function getDebugOutput(): 'console' | string | null { | ||
| const apiDebug = process.env.AGENTUITY_API_DEBUG?.trim(); | ||
| if (apiDebug) { | ||
| const normalized = apiDebug.toLowerCase(); | ||
| // Check if explicitly disabled | ||
| if (normalized === '0' || normalized === 'false') { | ||
| return null; | ||
| } | ||
| // Check if it's a truthy value (console output) | ||
| if (normalized === '1' || normalized === 'true') { | ||
| return 'console'; | ||
| } | ||
| // Treat any other non-empty value as a file path | ||
| return apiDebug; | ||
| } | ||
| // Fall back to CI environment check | ||
| if (process.env.CI === '1' || process.env.CI === 'true') { | ||
| return 'console'; | ||
| } | ||
| return null; | ||
| } | ||
| /** | ||
| * Format request body for CI debug logging | ||
| */ | ||
| function formatRequestBody(body: unknown): string { | ||
| if (body === undefined || body === null) { | ||
| return '[no body]'; | ||
| } | ||
| if (typeof body === 'string') { | ||
| return body; | ||
| } | ||
| if (body instanceof Uint8Array) { | ||
| return `[binary data: ${body.length} bytes]`; | ||
| } | ||
| if (body instanceof ArrayBuffer) { | ||
| return `[binary data: ${body.byteLength} bytes]`; | ||
| } | ||
| if (body instanceof ReadableStream) { | ||
| return '[stream]'; | ||
| } | ||
| return String(body); | ||
| } | ||
| /** | ||
| * Format a sensitive header value, preserving Bearer prefix if present. | ||
| */ | ||
| function redactSensitiveHeader(key: string, value: string): string { | ||
| const _k = key.toLowerCase(); | ||
| // Handle Bearer tokens in authorization and proxy-authorization headers | ||
| if ((_k === 'authorization' || _k === 'proxy-authorization') && value.startsWith('Bearer ')) { | ||
| return `Bearer ${redact(value.substring(7))}`; | ||
| } | ||
| return redact(value); | ||
| } | ||
| /** | ||
| * Format headers as a readable string for debug logging. | ||
| * Sensitive headers (auth tokens, cookies, API keys) are redacted. | ||
| */ | ||
| function formatHeaders(headers: Headers | Record<string, string>): string { | ||
| const entries: string[] = []; | ||
| if (headers instanceof Headers) { | ||
| headers.forEach((value, key) => { | ||
| const _k = key.toLowerCase(); | ||
| if (sensitiveHeaders.has(_k)) { | ||
| entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`); | ||
| } else { | ||
| entries.push(` ${key}: ${value}`); | ||
| } | ||
| }); | ||
| } else { | ||
| for (const [key, value] of Object.entries(headers)) { | ||
| const _k = key.toLowerCase(); | ||
| if (sensitiveHeaders.has(_k)) { | ||
| entries.push(` ${key}: ${redactSensitiveHeader(key, value)}`); | ||
| } else { | ||
| entries.push(` ${key}: ${value}`); | ||
| } | ||
| } | ||
| } | ||
| return entries.join('\n'); | ||
| } | ||
| /** | ||
| * Log detailed debug information when API requests fail. | ||
| * Output destination is determined by AGENTUITY_API_DEBUG or CI environment variables. | ||
| */ | ||
| function logAPIDebug( | ||
| url: string, | ||
| method: string, | ||
| requestHeaders: Record<string, string>, | ||
| requestBody: unknown, | ||
| response: Response, | ||
| responseBody: string | ||
| ): void { | ||
| const output = getDebugOutput(); | ||
| if (!output) { | ||
| return; | ||
| } | ||
| const separator = '='.repeat(60); | ||
| const timestamp = new Date().toISOString(); | ||
| const lines = [ | ||
| '', | ||
| separator, | ||
| `API DEBUG: Request Failed [${timestamp}]`, | ||
| separator, | ||
| '', | ||
| '>>> REQUEST', | ||
| `URL: ${url}`, | ||
| `Method: ${method}`, | ||
| 'Headers:', | ||
| formatHeaders(requestHeaders), | ||
| 'Body:', | ||
| ` ${formatRequestBody(requestBody)}`, | ||
| '', | ||
| '<<< RESPONSE', | ||
| `Status: ${response.status} ${response.statusText}`, | ||
| 'Headers:', | ||
| formatHeaders(response.headers), | ||
| 'Body:', | ||
| ` ${responseBody || '[empty]'}`, | ||
| '', | ||
| separator, | ||
| '', | ||
| ]; | ||
| const content = lines.join('\n'); | ||
| if (output === 'console') { | ||
| console.error(content); | ||
| } else { | ||
| // Append to file | ||
| try { | ||
| appendFileSync(output, content + '\n'); | ||
| } catch { | ||
| // If file write fails, fall back to console.error | ||
| console.error(`[API DEBUG] Failed to write to ${output}, falling back to console`); | ||
| console.error(content); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Redacts the middle of a string while keeping a prefix and suffix visible. | ||
| * Ensures that if the string is too short, everything is redacted. | ||
| * | ||
| * @param input The string to redact | ||
| * @param prefix Number of chars to keep at the start | ||
| * @param suffix Number of chars to keep at the end | ||
| * @param mask Character used for redaction | ||
| */ | ||
| export function redact( | ||
| input: string, | ||
| prefix: number = 4, | ||
| suffix: number = 4, | ||
| mask: string = '*' | ||
| ): string { | ||
| if (!input) return ''; | ||
| // If revealing prefix+suffix would leak too much, fully mask | ||
| if (input.length <= prefix + suffix) { | ||
| return mask.repeat(input.length); | ||
| } | ||
| const start = input.slice(0, prefix); | ||
| const end = input.slice(-suffix); | ||
| const hiddenLength = input.length - prefix - suffix; | ||
| return start + mask.repeat(hiddenLength) + end; | ||
| } | ||
| const redactHeaders = (kv: Record<string, string>): string => { | ||
| const values: string[] = []; | ||
| for (const k of Object.keys(kv)) { | ||
| const _k = k.toLowerCase(); | ||
| const v = kv[k]; | ||
| if (v === undefined) { | ||
| continue; | ||
| } | ||
| if (sensitiveHeaders.has(_k)) { | ||
| values.push(`${_k}=${redactSensitiveHeader(k, v)}`); | ||
| } else { | ||
| values.push(`${_k}=${v}`); | ||
| } | ||
| } | ||
| return '[' + values.join(',') + ']'; | ||
| }; | ||
| class ServerFetchAdapter implements FetchAdapter { | ||
| #config: ServiceAdapterConfig; | ||
| #logger: Logger; | ||
| constructor(config: ServiceAdapterConfig, logger: Logger) { | ||
| this.#config = config; | ||
| this.#logger = logger; | ||
| } | ||
| /** | ||
| * Build the final URL with query params appended. | ||
| * This is extracted so both invoke() and _invoke() use the same URL. | ||
| */ | ||
| #buildUrl(url: string): string { | ||
| if (this.#config.queryParams && Object.keys(this.#config.queryParams).length > 0) { | ||
| const urlObj = new URL(url); | ||
| for (const [key, value] of Object.entries(this.#config.queryParams)) { | ||
| urlObj.searchParams.set(key, value); | ||
| } | ||
| return urlObj.toString(); | ||
| } | ||
| return url; | ||
| } | ||
| private async _invoke<T>(url: string, options: FetchRequest): Promise<FetchResponse<T>> { | ||
| // URL already has query params appended by invoke() or direct caller | ||
| const headers: Record<string, string> = { | ||
| ...options.headers, | ||
| ...this.#config.headers, | ||
| }; | ||
| if (options.contentType) { | ||
| headers['Content-Type'] = options.contentType; | ||
| } else if ( | ||
| typeof options.body === 'string' || | ||
| options.body instanceof Uint8Array || | ||
| options.body instanceof ArrayBuffer | ||
| ) { | ||
| headers['Content-Type'] = 'application/octet-stream'; | ||
| } | ||
| // Ensure we request JSON responses for proper error handling | ||
| if (!headers['Accept'] && !headers['accept']) { | ||
| headers['Accept'] = 'application/json'; | ||
| } | ||
| const method: HttpMethod = options.method ?? 'POST'; | ||
| this.#logger.trace('sending %s to %s with headers: %s', method, url, redactHeaders(headers)); | ||
| const res = await fetch(url, { | ||
| method, | ||
| body: options.body, | ||
| headers, | ||
| signal: options.signal, | ||
| ...(options.duplex ? { duplex: options.duplex } : {}), | ||
| }); | ||
| if (res.ok) { | ||
| switch (res.status) { | ||
| case 100: | ||
| case 101: | ||
| case 102: | ||
| case 204: | ||
| case 304: | ||
| return { | ||
| ok: true, | ||
| data: undefined as T, | ||
| response: res, | ||
| }; | ||
| default: | ||
| break; | ||
| } | ||
| if (options?.binary) { | ||
| return { | ||
| ok: true, | ||
| data: undefined as T, | ||
| response: res, | ||
| }; | ||
| } | ||
| const data = await fromResponse<T>(res); | ||
| return { | ||
| ok: true, | ||
| data, | ||
| response: res, | ||
| }; | ||
| } | ||
| if (res.status === 404) { | ||
| // Log debug info for 404 errors if debugging is enabled | ||
| if (getDebugOutput()) { | ||
| const responseBody = await res.clone().text(); | ||
| logAPIDebug(url, method, headers, options.body, res, responseBody); | ||
| } | ||
| return { | ||
| ok: false, | ||
| response: res, | ||
| } as FetchErrorResponse; | ||
| } | ||
| // Clone response to read body for debug logging before toServiceException consumes it | ||
| const responseBody = getDebugOutput() ? await res.clone().text() : ''; | ||
| logAPIDebug(url, method, headers, options.body, res, responseBody); | ||
| const err = await toServiceException(method, url, res); | ||
| throw err; | ||
| } | ||
| async invoke<T>( | ||
| url: string, | ||
| options: FetchRequest = { method: 'POST' } | ||
| ): Promise<FetchResponse<T>> { | ||
| // Build final URL with query params BEFORE hooks, so hooks receive the actual URL | ||
| const finalUrl = this.#buildUrl(url); | ||
| if (this.#config.onBefore) { | ||
| let result: FetchResponse<T> | undefined = undefined; | ||
| let err: Error | undefined = undefined; | ||
| await this.#config.onBefore(finalUrl, options, async () => { | ||
| try { | ||
| result = await this._invoke(finalUrl, options); | ||
| if (this.#config.onAfter) { | ||
| await this.#config.onAfter(finalUrl, options, result); | ||
| } | ||
| } catch (ex) { | ||
| err = ex as Error; | ||
| if (this.#config.onAfter && err instanceof ServiceException) { | ||
| await this.#config.onAfter( | ||
| finalUrl, | ||
| options, | ||
| { | ||
| ok: false, | ||
| response: new Response(err.message, { | ||
| status: err.statusCode, | ||
| }), | ||
| } as FetchErrorResponse, | ||
| err | ||
| ); | ||
| } | ||
| } | ||
| }); | ||
| if (err) { | ||
| throw err; | ||
| } | ||
| return result as unknown as FetchResponse<T>; | ||
| } else { | ||
| return await this._invoke(finalUrl, options); | ||
| } | ||
| } | ||
| } | ||
| /** | ||
| * Create a Server Side Fetch Adapter to allow the server to add headers and track outgoing requests | ||
| * | ||
| * @param config the service config | ||
| * @returns | ||
| */ | ||
| export function createServerFetchAdapter(config: ServiceAdapterConfig, logger: Logger) { | ||
| return new ServerFetchAdapter(config, logger); | ||
| } |
Unstable ownership
Supply chain riskA new collaborator has begun publishing package versions. Package stability and security risk may be elevated.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 14 instances in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 16 instances in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
Found 1 instance in 1 package
71
-12.35%1
-50%89862
-28.66%4
33.33%108
-4.42%1648
-33.25%2
100%1
Infinity%+ Added
+ Added
+ Added
- Removed
- Removed