@geekmidas/constructs 0.0.17 → 0.0.18

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 (88) hide show
  1. package/dist/{Cron-3bP5rwXs.cjs → Cron-Bi3QOge_.cjs} +1 -1
  2. package/dist/{Cron-3bP5rwXs.cjs.map → Cron-Bi3QOge_.cjs.map} +1 -1
  3. package/dist/{Cron-gISh3p1m.mjs → Cron-Dy_HW2Vv.mjs} +1 -1
  4. package/dist/{Cron-gISh3p1m.mjs.map → Cron-Dy_HW2Vv.mjs.map} +1 -1
  5. package/dist/{CronBuilder-BCYftl8v.mjs → CronBuilder-Bl3A2Zp4.mjs} +2 -2
  6. package/dist/{CronBuilder-BCYftl8v.mjs.map → CronBuilder-Bl3A2Zp4.mjs.map} +1 -1
  7. package/dist/{CronBuilder-2zUMc0WT.cjs → CronBuilder-Dv_w7Yri.cjs} +2 -2
  8. package/dist/{CronBuilder-2zUMc0WT.cjs.map → CronBuilder-Dv_w7Yri.cjs.map} +1 -1
  9. package/dist/{EndpointBuilder-bMiowRHY.cjs → EndpointBuilder-CFnjYXmL.cjs} +1 -1
  10. package/dist/{EndpointBuilder-bMiowRHY.cjs.map → EndpointBuilder-CFnjYXmL.cjs.map} +1 -1
  11. package/dist/{EndpointBuilder-DN0NQp1W.mjs → EndpointBuilder-DlDft4mJ.mjs} +1 -1
  12. package/dist/{EndpointBuilder-DN0NQp1W.mjs.map → EndpointBuilder-DlDft4mJ.mjs.map} +1 -1
  13. package/dist/{EndpointFactory-B0ldqkHz.mjs → EndpointFactory-Ctln6czP.mjs} +2 -2
  14. package/dist/{EndpointFactory-B0ldqkHz.mjs.map → EndpointFactory-Ctln6czP.mjs.map} +1 -1
  15. package/dist/{EndpointFactory-DqvIVjOy.cjs → EndpointFactory-mTfi8x1X.cjs} +2 -2
  16. package/dist/{EndpointFactory-DqvIVjOy.cjs.map → EndpointFactory-mTfi8x1X.cjs.map} +1 -1
  17. package/dist/{HonoEndpointAdaptor-Dc8XsOxw.d.cts → HonoEndpointAdaptor-DajXbh80.d.cts} +3 -3
  18. package/dist/{HonoEndpointAdaptor-Br1vuQ3A.d.mts → HonoEndpointAdaptor-DsqGuEIb.d.mts} +3 -3
  19. package/dist/{TestEndpointAdaptor-C8425RJ0.cjs → TestEndpointAdaptor-B9hyZ-mF.cjs} +10 -4
  20. package/dist/TestEndpointAdaptor-B9hyZ-mF.cjs.map +1 -0
  21. package/dist/{TestEndpointAdaptor-H5To8PH7.d.cts → TestEndpointAdaptor-B9tUIlCC.d.cts} +22 -8
  22. package/dist/{TestEndpointAdaptor-BEyZa0Yg.mjs → TestEndpointAdaptor-DbwrL-RJ.mjs} +10 -4
  23. package/dist/TestEndpointAdaptor-DbwrL-RJ.mjs.map +1 -0
  24. package/dist/{TestEndpointAdaptor-jxn68ayg.d.mts → TestEndpointAdaptor-DhRjJHyk.d.mts} +22 -8
  25. package/dist/adaptors/aws.d.cts +1 -1
  26. package/dist/adaptors/aws.d.mts +1 -1
  27. package/dist/adaptors/hono.d.cts +2 -2
  28. package/dist/adaptors/hono.d.mts +2 -2
  29. package/dist/adaptors/testing.cjs +1 -1
  30. package/dist/adaptors/testing.d.cts +2 -2
  31. package/dist/adaptors/testing.d.mts +2 -2
  32. package/dist/adaptors/testing.mjs +1 -1
  33. package/dist/crons/Cron.cjs +1 -1
  34. package/dist/crons/Cron.d.cts +1 -1
  35. package/dist/crons/Cron.d.mts +1 -1
  36. package/dist/crons/Cron.mjs +1 -1
  37. package/dist/crons/CronBuilder.cjs +2 -2
  38. package/dist/crons/CronBuilder.d.cts +1 -1
  39. package/dist/crons/CronBuilder.d.mts +1 -1
  40. package/dist/crons/CronBuilder.mjs +2 -2
  41. package/dist/crons/index.cjs +2 -2
  42. package/dist/crons/index.d.cts +5 -5
  43. package/dist/crons/index.d.mts +5 -5
  44. package/dist/crons/index.mjs +2 -2
  45. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +1 -1
  46. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +1 -1
  47. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +1 -1
  48. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +1 -1
  49. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +1 -1
  50. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +1 -1
  51. package/dist/endpoints/Endpoint.d.cts +1 -1
  52. package/dist/endpoints/Endpoint.d.mts +1 -1
  53. package/dist/endpoints/EndpointBuilder.cjs +1 -1
  54. package/dist/endpoints/EndpointBuilder.d.cts +1 -1
  55. package/dist/endpoints/EndpointBuilder.d.mts +1 -1
  56. package/dist/endpoints/EndpointBuilder.mjs +1 -1
  57. package/dist/endpoints/EndpointFactory.cjs +2 -2
  58. package/dist/endpoints/EndpointFactory.d.cts +1 -1
  59. package/dist/endpoints/EndpointFactory.d.mts +1 -1
  60. package/dist/endpoints/EndpointFactory.mjs +2 -2
  61. package/dist/endpoints/HonoEndpointAdaptor.d.cts +2 -2
  62. package/dist/endpoints/HonoEndpointAdaptor.d.mts +2 -2
  63. package/dist/endpoints/TestEndpointAdaptor.cjs +1 -1
  64. package/dist/endpoints/TestEndpointAdaptor.d.cts +2 -2
  65. package/dist/endpoints/TestEndpointAdaptor.d.mts +2 -2
  66. package/dist/endpoints/TestEndpointAdaptor.mjs +1 -1
  67. package/dist/endpoints/audit.d.cts +1 -1
  68. package/dist/endpoints/audit.d.mts +1 -1
  69. package/dist/endpoints/helpers.d.cts +1 -1
  70. package/dist/endpoints/helpers.d.mts +1 -1
  71. package/dist/endpoints/index.cjs +2 -2
  72. package/dist/endpoints/index.d.cts +3 -3
  73. package/dist/endpoints/index.d.mts +3 -3
  74. package/dist/endpoints/index.mjs +2 -2
  75. package/dist/endpoints/processAudits.d.cts +1 -1
  76. package/dist/endpoints/processAudits.d.mts +1 -1
  77. package/dist/functions/index.d.cts +1 -1
  78. package/dist/functions/index.d.mts +1 -1
  79. package/dist/index-Sxtb_Pzw.d.mts +10 -0
  80. package/dist/index-m7xBtcAW.d.cts +10 -0
  81. package/dist/subscribers/index.d.cts +2 -2
  82. package/package.json +5 -5
  83. package/src/endpoints/EndpointFactory.ts +17 -7
  84. package/src/endpoints/TestEndpointAdaptor.ts +70 -13
  85. package/dist/TestEndpointAdaptor-BEyZa0Yg.mjs.map +0 -1
  86. package/dist/TestEndpointAdaptor-C8425RJ0.cjs.map +0 -1
  87. package/dist/index-C1dy81Sw.d.cts +0 -10
  88. package/dist/index-TxufD5Xp.d.mts +0 -10
@@ -85,6 +85,8 @@ export class TestEndpointAdaptor<
85
85
  string,
86
86
  unknown
87
87
  >,
88
+ TDatabase = undefined,
89
+ TDatabaseServiceName extends string = string,
88
90
  > {
89
91
  static getDefaultServiceDiscover<
90
92
  TRoute extends string,
@@ -102,6 +104,8 @@ export class TestEndpointAdaptor<
102
104
  string,
103
105
  unknown
104
106
  >,
107
+ TDatabase = undefined,
108
+ TDatabaseServiceName extends string = string,
105
109
  >(
106
110
  endpoint: Endpoint<
107
111
  TRoute,
@@ -115,7 +119,9 @@ export class TestEndpointAdaptor<
115
119
  TEventPublisherServiceName,
116
120
  TAuditStorage,
117
121
  TAuditStorageServiceName,
118
- TAuditAction
122
+ TAuditAction,
123
+ TDatabase,
124
+ TDatabaseServiceName
119
125
  >,
120
126
  ) {
121
127
  return ServiceDiscovery.getInstance(
@@ -136,7 +142,9 @@ export class TestEndpointAdaptor<
136
142
  TEventPublisherServiceName,
137
143
  TAuditStorage,
138
144
  TAuditStorageServiceName,
139
- TAuditAction
145
+ TAuditAction,
146
+ TDatabase,
147
+ TDatabaseServiceName
140
148
  >,
141
149
  private serviceDiscovery: ServiceDiscovery<
142
150
  any,
@@ -149,7 +157,11 @@ export class TestEndpointAdaptor<
149
157
  TInput,
150
158
  TServices,
151
159
  TEventPublisher,
152
- TEventPublisherServiceName
160
+ TEventPublisherServiceName,
161
+ TAuditStorage,
162
+ TAuditStorageServiceName,
163
+ TDatabase,
164
+ TDatabaseServiceName
153
165
  >,
154
166
  ): Promise<TestHttpResponse<InferStandardSchema<TOutSchema>>> {
155
167
  const body = await this.endpoint.parseInput((ctx as any).body, 'body');
@@ -174,8 +186,16 @@ export class TestEndpointAdaptor<
174
186
  });
175
187
 
176
188
  // Create audit context if audit storage is configured
189
+ // The auditorStorage is required when endpoint uses .auditor()
190
+ const auditorStorageService = (ctx as any).auditorStorage as
191
+ | Service<TAuditStorageServiceName, TAuditStorage>
192
+ | undefined;
193
+ const endpointWithAuditor = auditorStorageService
194
+ ? { ...this.endpoint, auditorStorageService }
195
+ : this.endpoint;
196
+
177
197
  const auditContext = await createAuditContext(
178
- this.endpoint,
198
+ endpointWithAuditor as typeof this.endpoint,
179
199
  this.serviceDiscovery,
180
200
  logger,
181
201
  {
@@ -196,13 +216,14 @@ export class TestEndpointAdaptor<
196
216
  }
197
217
 
198
218
  // Resolve database service if configured
199
- const rawDb = this.endpoint.databaseService
219
+ // The database is required when endpoint uses .database()
220
+ const databaseService = (ctx as any).database as
221
+ | Service<TDatabaseServiceName, TDatabase>
222
+ | undefined;
223
+ const rawDb = databaseService
200
224
  ? await this.serviceDiscovery
201
- .register([this.endpoint.databaseService])
202
- .then(
203
- (s) =>
204
- s[this.endpoint.databaseService!.serviceName as keyof typeof s],
205
- )
225
+ .register([databaseService])
226
+ .then((s) => s[databaseService.serviceName as keyof typeof s])
206
227
  : undefined;
207
228
 
208
229
  // Execute handler with automatic audit transaction support
@@ -213,7 +234,7 @@ export class TestEndpointAdaptor<
213
234
  const sameDatabase =
214
235
  auditContext?.storage?.databaseServiceName &&
215
236
  auditContext.storage.databaseServiceName ===
216
- this.endpoint.databaseService?.serviceName;
237
+ databaseService?.serviceName;
217
238
  const db = sameDatabase
218
239
  ? (auditor?.getTransaction?.() ?? rawDb)
219
240
  : rawDb;
@@ -299,7 +320,11 @@ export class TestEndpointAdaptor<
299
320
  TInput,
300
321
  TServices,
301
322
  TEventPublisher,
302
- TEventPublisherServiceName
323
+ TEventPublisherServiceName,
324
+ TAuditStorage,
325
+ TAuditStorageServiceName,
326
+ TDatabase,
327
+ TDatabaseServiceName
303
328
  >,
304
329
  ): Promise<InferStandardSchema<TOutSchema>> {
305
330
  const response = await this.fullRequest(ctx);
@@ -307,13 +332,45 @@ export class TestEndpointAdaptor<
307
332
  }
308
333
  }
309
334
 
335
+ /**
336
+ * Conditional audit storage requirement - required when TAuditStorage is configured
337
+ */
338
+ type AuditStorageRequirement<
339
+ TAuditStorage extends AuditStorage | undefined = undefined,
340
+ TAuditStorageServiceName extends string = string,
341
+ > = TAuditStorage extends undefined
342
+ ? {}
343
+ : {
344
+ /** Audit storage service - required when endpoint uses .auditor() */
345
+ auditorStorage: Service<TAuditStorageServiceName, TAuditStorage>;
346
+ };
347
+
348
+ /**
349
+ * Conditional database requirement - required when TDatabase is configured
350
+ */
351
+ type DatabaseRequirement<
352
+ TDatabase = undefined,
353
+ TDatabaseServiceName extends string = string,
354
+ > = TDatabase extends undefined
355
+ ? {}
356
+ : {
357
+ /** Database service - required when endpoint uses .database() */
358
+ database: Service<TDatabaseServiceName, TDatabase>;
359
+ };
360
+
310
361
  export type TestRequestAdaptor<
311
362
  TInput extends EndpointSchemas = {},
312
363
  TServices extends Service[] = [],
313
364
  TEventPublisher extends EventPublisher<any> | undefined = undefined,
314
365
  TEventPublisherServiceName extends string = string,
366
+ TAuditStorage extends AuditStorage | undefined = undefined,
367
+ TAuditStorageServiceName extends string = string,
368
+ TDatabase = undefined,
369
+ TDatabaseServiceName extends string = string,
315
370
  > = {
316
371
  services: ServiceRecord<TServices>;
317
372
  headers: Record<string, string>;
318
373
  publisher?: Service<TEventPublisherServiceName, TEventPublisher>;
319
- } & InferComposableStandardSchema<TInput>;
374
+ } & InferComposableStandardSchema<TInput> &
375
+ AuditStorageRequirement<TAuditStorage, TAuditStorageServiceName> &
376
+ DatabaseRequirement<TDatabase, TDatabaseServiceName>;
@@ -1 +0,0 @@
1
- {"version":3,"file":"TestEndpointAdaptor-BEyZa0Yg.mjs","names":["name: string","value: string","options?: CookieOptions","endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >","serviceDiscovery: ServiceDiscovery<\n any,\n any\n >","ctx: TestRequestAdaptor<\n TInput,\n TServices,\n TEventPublisher,\n TEventPublisherServiceName\n >","metadata","output","result","headers: Record<string, string | string[]>","setCookieValues: string[]","cookie"],"sources":["../src/endpoints/TestEndpointAdaptor.ts"],"sourcesContent":["import type { AuditStorage, AuditableAction } from '@geekmidas/audit';\nimport { EnvironmentParser } from '@geekmidas/envkit';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type {\n InferComposableStandardSchema,\n InferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n type Service,\n ServiceDiscovery,\n type ServiceRecord,\n} from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { publishConstructEvents } from '../publisher';\nimport type { HttpMethod } from '../types';\nimport {\n type CookieOptions,\n Endpoint,\n type EndpointSchemas,\n ResponseBuilder,\n} from './Endpoint';\nimport type { MappedAudit } from './audit';\nimport {\n createAuditContext,\n executeWithAuditTransaction,\n} from './processAudits';\n\nexport type TestHttpResponse<TBody = any> = {\n body: TBody;\n status: number;\n headers: Record<string, string | string[]>;\n};\n\n/**\n * Serializes a cookie into a Set-Cookie header string\n */\nfunction serializeCookie(\n name: string,\n value: string,\n options?: CookieOptions,\n): string {\n let cookieString = `${name}=${value}`;\n\n if (options) {\n if (options.maxAge !== undefined) {\n cookieString += `; Max-Age=${options.maxAge}`;\n }\n if (options.expires) {\n cookieString += `; Expires=${options.expires.toUTCString()}`;\n }\n if (options.domain) {\n cookieString += `; Domain=${options.domain}`;\n }\n if (options.path) {\n cookieString += `; Path=${options.path}`;\n }\n if (options.httpOnly) {\n cookieString += '; HttpOnly';\n }\n if (options.secure) {\n cookieString += '; Secure';\n }\n if (options.sameSite) {\n cookieString += `; SameSite=${options.sameSite}`;\n }\n }\n\n return cookieString;\n}\n\nexport class TestEndpointAdaptor<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n> {\n static getDefaultServiceDiscover<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n >(\n endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >,\n ) {\n return ServiceDiscovery.getInstance(\n endpoint.logger,\n new EnvironmentParser({}),\n );\n }\n constructor(\n private readonly endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >,\n private serviceDiscovery: ServiceDiscovery<\n any,\n any\n > = TestEndpointAdaptor.getDefaultServiceDiscover(endpoint),\n ) {}\n\n async fullRequest(\n ctx: TestRequestAdaptor<\n TInput,\n TServices,\n TEventPublisher,\n TEventPublisherServiceName\n >,\n ): Promise<TestHttpResponse<InferStandardSchema<TOutSchema>>> {\n const body = await this.endpoint.parseInput((ctx as any).body, 'body');\n const query = await this.endpoint.parseInput((ctx as any).query, 'query');\n const params = await this.endpoint.parseInput(\n (ctx as any).params,\n 'params',\n );\n\n const header = Endpoint.createHeaders(ctx.headers);\n const cookie = Endpoint.createCookies(ctx.headers.cookie);\n const logger = this.endpoint.logger.child({\n route: this.endpoint.route,\n host: ctx.headers.host,\n method: this.endpoint.method,\n }) as TLogger;\n const session = await this.endpoint.getSession({\n logger,\n services: ctx.services,\n header,\n cookie,\n });\n\n // Create audit context if audit storage is configured\n const auditContext = await createAuditContext(\n this.endpoint,\n this.serviceDiscovery,\n logger,\n {\n session,\n header,\n cookie,\n services: ctx.services as Record<string, unknown>,\n },\n );\n\n // Warn if declarative audits are configured but no audit storage\n const audits = this.endpoint.audits as MappedAudit<\n TAuditAction,\n TOutSchema\n >[];\n if (!auditContext && audits?.length) {\n logger.warn('No auditor storage service available');\n }\n\n // Resolve database service if configured\n const rawDb = this.endpoint.databaseService\n ? await this.serviceDiscovery\n .register([this.endpoint.databaseService])\n .then(\n (s) =>\n s[this.endpoint.databaseService!.serviceName as keyof typeof s],\n )\n : undefined;\n\n // Execute handler with automatic audit transaction support\n const result = await executeWithAuditTransaction(\n auditContext,\n async (auditor) => {\n // Use audit transaction as db only if the storage uses the same database service\n const sameDatabase =\n auditContext?.storage?.databaseServiceName &&\n auditContext.storage.databaseServiceName ===\n this.endpoint.databaseService?.serviceName;\n const db = sameDatabase\n ? (auditor?.getTransaction?.() ?? rawDb)\n : rawDb;\n\n const responseBuilder = new ResponseBuilder();\n const response = await this.endpoint.handler(\n {\n body,\n query,\n params,\n session,\n services: ctx.services,\n logger,\n header,\n cookie,\n auditor,\n db,\n } as any,\n responseBuilder,\n );\n\n // Check if response has metadata\n let data = response;\n let metadata = responseBuilder.getMetadata();\n\n if (Endpoint.hasMetadata(response)) {\n data = response.data;\n metadata = response.metadata;\n }\n\n const output = await this.endpoint.parseOutput(data);\n\n return { output, metadata, responseBuilder };\n },\n // Process declarative audits after handler (inside transaction)\n async (result, auditor) => {\n if (!audits?.length) return;\n\n for (const audit of audits) {\n if (audit.when && !audit.when(result.output as any)) {\n continue;\n }\n const payload = audit.payload(result.output as any);\n const entityId = audit.entityId?.(result.output as any);\n auditor.audit(audit.type as any, payload as any, {\n table: audit.table,\n entityId,\n });\n }\n },\n );\n\n const { output, metadata } = result;\n\n ctx.publisher && (await this.serviceDiscovery.register([ctx.publisher]));\n await publishConstructEvents(this.endpoint, output, this.serviceDiscovery);\n\n // Convert cookies to Set-Cookie headers\n const headers: Record<string, string | string[]> = {\n ...(metadata.headers || {}),\n };\n\n if (metadata.cookies && metadata.cookies.size > 0) {\n const setCookieValues: string[] = [];\n for (const [name, cookie] of metadata.cookies.entries()) {\n setCookieValues.push(\n serializeCookie(name, cookie.value, cookie.options),\n );\n }\n headers['set-cookie'] = setCookieValues;\n }\n\n // Return HTTP response format\n return {\n body: output,\n status: metadata.status || 200,\n headers,\n };\n }\n\n async request(\n ctx: TestRequestAdaptor<\n TInput,\n TServices,\n TEventPublisher,\n TEventPublisherServiceName\n >,\n ): Promise<InferStandardSchema<TOutSchema>> {\n const response = await this.fullRequest(ctx);\n return response.body;\n }\n}\n\nexport type TestRequestAdaptor<\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n> = {\n services: ServiceRecord<TServices>;\n headers: Record<string, string>;\n publisher?: Service<TEventPublisherServiceName, TEventPublisher>;\n} & InferComposableStandardSchema<TInput>;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"TestEndpointAdaptor-C8425RJ0.cjs","names":["name: string","value: string","options?: CookieOptions","endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >","EnvironmentParser","serviceDiscovery: ServiceDiscovery<\n any,\n any\n >","ctx: TestRequestAdaptor<\n TInput,\n TServices,\n TEventPublisher,\n TEventPublisherServiceName\n >","ResponseBuilder","metadata","output","result","headers: Record<string, string | string[]>","setCookieValues: string[]","cookie"],"sources":["../src/endpoints/TestEndpointAdaptor.ts"],"sourcesContent":["import type { AuditStorage, AuditableAction } from '@geekmidas/audit';\nimport { EnvironmentParser } from '@geekmidas/envkit';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type {\n InferComposableStandardSchema,\n InferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n type Service,\n ServiceDiscovery,\n type ServiceRecord,\n} from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { publishConstructEvents } from '../publisher';\nimport type { HttpMethod } from '../types';\nimport {\n type CookieOptions,\n Endpoint,\n type EndpointSchemas,\n ResponseBuilder,\n} from './Endpoint';\nimport type { MappedAudit } from './audit';\nimport {\n createAuditContext,\n executeWithAuditTransaction,\n} from './processAudits';\n\nexport type TestHttpResponse<TBody = any> = {\n body: TBody;\n status: number;\n headers: Record<string, string | string[]>;\n};\n\n/**\n * Serializes a cookie into a Set-Cookie header string\n */\nfunction serializeCookie(\n name: string,\n value: string,\n options?: CookieOptions,\n): string {\n let cookieString = `${name}=${value}`;\n\n if (options) {\n if (options.maxAge !== undefined) {\n cookieString += `; Max-Age=${options.maxAge}`;\n }\n if (options.expires) {\n cookieString += `; Expires=${options.expires.toUTCString()}`;\n }\n if (options.domain) {\n cookieString += `; Domain=${options.domain}`;\n }\n if (options.path) {\n cookieString += `; Path=${options.path}`;\n }\n if (options.httpOnly) {\n cookieString += '; HttpOnly';\n }\n if (options.secure) {\n cookieString += '; Secure';\n }\n if (options.sameSite) {\n cookieString += `; SameSite=${options.sameSite}`;\n }\n }\n\n return cookieString;\n}\n\nexport class TestEndpointAdaptor<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n> {\n static getDefaultServiceDiscover<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n >(\n endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >,\n ) {\n return ServiceDiscovery.getInstance(\n endpoint.logger,\n new EnvironmentParser({}),\n );\n }\n constructor(\n private readonly endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >,\n private serviceDiscovery: ServiceDiscovery<\n any,\n any\n > = TestEndpointAdaptor.getDefaultServiceDiscover(endpoint),\n ) {}\n\n async fullRequest(\n ctx: TestRequestAdaptor<\n TInput,\n TServices,\n TEventPublisher,\n TEventPublisherServiceName\n >,\n ): Promise<TestHttpResponse<InferStandardSchema<TOutSchema>>> {\n const body = await this.endpoint.parseInput((ctx as any).body, 'body');\n const query = await this.endpoint.parseInput((ctx as any).query, 'query');\n const params = await this.endpoint.parseInput(\n (ctx as any).params,\n 'params',\n );\n\n const header = Endpoint.createHeaders(ctx.headers);\n const cookie = Endpoint.createCookies(ctx.headers.cookie);\n const logger = this.endpoint.logger.child({\n route: this.endpoint.route,\n host: ctx.headers.host,\n method: this.endpoint.method,\n }) as TLogger;\n const session = await this.endpoint.getSession({\n logger,\n services: ctx.services,\n header,\n cookie,\n });\n\n // Create audit context if audit storage is configured\n const auditContext = await createAuditContext(\n this.endpoint,\n this.serviceDiscovery,\n logger,\n {\n session,\n header,\n cookie,\n services: ctx.services as Record<string, unknown>,\n },\n );\n\n // Warn if declarative audits are configured but no audit storage\n const audits = this.endpoint.audits as MappedAudit<\n TAuditAction,\n TOutSchema\n >[];\n if (!auditContext && audits?.length) {\n logger.warn('No auditor storage service available');\n }\n\n // Resolve database service if configured\n const rawDb = this.endpoint.databaseService\n ? await this.serviceDiscovery\n .register([this.endpoint.databaseService])\n .then(\n (s) =>\n s[this.endpoint.databaseService!.serviceName as keyof typeof s],\n )\n : undefined;\n\n // Execute handler with automatic audit transaction support\n const result = await executeWithAuditTransaction(\n auditContext,\n async (auditor) => {\n // Use audit transaction as db only if the storage uses the same database service\n const sameDatabase =\n auditContext?.storage?.databaseServiceName &&\n auditContext.storage.databaseServiceName ===\n this.endpoint.databaseService?.serviceName;\n const db = sameDatabase\n ? (auditor?.getTransaction?.() ?? rawDb)\n : rawDb;\n\n const responseBuilder = new ResponseBuilder();\n const response = await this.endpoint.handler(\n {\n body,\n query,\n params,\n session,\n services: ctx.services,\n logger,\n header,\n cookie,\n auditor,\n db,\n } as any,\n responseBuilder,\n );\n\n // Check if response has metadata\n let data = response;\n let metadata = responseBuilder.getMetadata();\n\n if (Endpoint.hasMetadata(response)) {\n data = response.data;\n metadata = response.metadata;\n }\n\n const output = await this.endpoint.parseOutput(data);\n\n return { output, metadata, responseBuilder };\n },\n // Process declarative audits after handler (inside transaction)\n async (result, auditor) => {\n if (!audits?.length) return;\n\n for (const audit of audits) {\n if (audit.when && !audit.when(result.output as any)) {\n continue;\n }\n const payload = audit.payload(result.output as any);\n const entityId = audit.entityId?.(result.output as any);\n auditor.audit(audit.type as any, payload as any, {\n table: audit.table,\n entityId,\n });\n }\n },\n );\n\n const { output, metadata } = result;\n\n ctx.publisher && (await this.serviceDiscovery.register([ctx.publisher]));\n await publishConstructEvents(this.endpoint, output, this.serviceDiscovery);\n\n // Convert cookies to Set-Cookie headers\n const headers: Record<string, string | string[]> = {\n ...(metadata.headers || {}),\n };\n\n if (metadata.cookies && metadata.cookies.size > 0) {\n const setCookieValues: string[] = [];\n for (const [name, cookie] of metadata.cookies.entries()) {\n setCookieValues.push(\n serializeCookie(name, cookie.value, cookie.options),\n );\n }\n headers['set-cookie'] = setCookieValues;\n }\n\n // Return HTTP response format\n return {\n body: output,\n status: metadata.status || 200,\n headers,\n };\n }\n\n async request(\n ctx: TestRequestAdaptor<\n TInput,\n TServices,\n TEventPublisher,\n TEventPublisherServiceName\n >,\n ): Promise<InferStandardSchema<TOutSchema>> {\n const response = await this.fullRequest(ctx);\n return response.body;\n }\n}\n\nexport type TestRequestAdaptor<\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n> = {\n services: ServiceRecord<TServices>;\n headers: Record<string, string>;\n publisher?: Service<TEventPublisherServiceName, TEventPublisher>;\n} & InferComposableStandardSchema<TInput>;\n"],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import { FunctionBuilder } from "./FunctionBuilder-CjVEFTYC.cjs";
2
- import * as _geekmidas_audit6 from "@geekmidas/audit";
3
- import * as _geekmidas_logger5 from "@geekmidas/logger";
4
- import * as _geekmidas_schema4 from "@geekmidas/schema";
5
-
6
- //#region src/functions/index.d.ts
7
- declare const f: FunctionBuilder<_geekmidas_schema4.ComposableStandardSchema, undefined, [], _geekmidas_logger5.Logger, undefined, string, undefined, string, undefined, string, _geekmidas_audit6.AuditableAction<string, unknown>>;
8
- //#endregion
9
- export { f };
10
- //# sourceMappingURL=index-C1dy81Sw.d.cts.map
@@ -1,10 +0,0 @@
1
- import { FunctionBuilder } from "./FunctionBuilder-D1ofSeMd.mjs";
2
- import * as _geekmidas_audit8 from "@geekmidas/audit";
3
- import * as _geekmidas_logger7 from "@geekmidas/logger";
4
- import * as _geekmidas_schema6 from "@geekmidas/schema";
5
-
6
- //#region src/functions/index.d.ts
7
- declare const f: FunctionBuilder<_geekmidas_schema6.ComposableStandardSchema, undefined, [], _geekmidas_logger7.Logger, undefined, string, undefined, string, undefined, string, _geekmidas_audit8.AuditableAction<string, unknown>>;
8
- //#endregion
9
- export { f };
10
- //# sourceMappingURL=index-TxufD5Xp.d.mts.map