@salesforce/mrt-utilities 0.1.1 → 0.1.2

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 (45) hide show
  1. package/dist/cjs/data-store/index.d.ts +56 -0
  2. package/dist/cjs/data-store/index.js +131 -0
  3. package/dist/cjs/data-store/index.js.map +1 -0
  4. package/dist/cjs/index.js +22 -4
  5. package/dist/cjs/index.js.map +1 -1
  6. package/dist/cjs/metrics/index.js +17 -1
  7. package/dist/cjs/metrics/index.js.map +1 -1
  8. package/dist/cjs/metrics/metrics-sender.js +14 -9
  9. package/dist/cjs/metrics/metrics-sender.js.map +1 -1
  10. package/dist/cjs/middleware/data-store.d.ts +3 -54
  11. package/dist/cjs/middleware/data-store.js +19 -116
  12. package/dist/cjs/middleware/data-store.js.map +1 -1
  13. package/dist/cjs/middleware/express.d.ts +2 -0
  14. package/dist/cjs/middleware/express.js +23 -0
  15. package/dist/cjs/middleware/express.js.map +1 -0
  16. package/dist/cjs/middleware/index.d.ts +2 -3
  17. package/dist/cjs/middleware/index.js +18 -2
  18. package/dist/cjs/middleware/index.js.map +1 -1
  19. package/dist/cjs/middleware/middleware.js +79 -34
  20. package/dist/cjs/middleware/middleware.js.map +1 -1
  21. package/dist/cjs/streaming/create-lambda-adapter.js +66 -76
  22. package/dist/cjs/streaming/create-lambda-adapter.js.map +1 -1
  23. package/dist/cjs/streaming/index.js +7 -1
  24. package/dist/cjs/streaming/index.js.map +1 -1
  25. package/dist/cjs/utils/configure-proxying.js +16 -10
  26. package/dist/cjs/utils/configure-proxying.js.map +1 -1
  27. package/dist/cjs/utils/ssr-proxying.js +43 -32
  28. package/dist/cjs/utils/ssr-proxying.js.map +1 -1
  29. package/dist/cjs/utils/utils.js +7 -2
  30. package/dist/cjs/utils/utils.js.map +1 -1
  31. package/dist/esm/data-store/index.d.ts +56 -0
  32. package/dist/esm/data-store/index.js +124 -0
  33. package/dist/esm/data-store/index.js.map +1 -0
  34. package/dist/esm/middleware/data-store.d.ts +3 -54
  35. package/dist/esm/middleware/data-store.js +3 -116
  36. package/dist/esm/middleware/data-store.js.map +1 -1
  37. package/dist/esm/middleware/express.d.ts +2 -0
  38. package/dist/esm/middleware/express.js +8 -0
  39. package/dist/esm/middleware/express.js.map +1 -0
  40. package/dist/esm/middleware/index.d.ts +2 -3
  41. package/dist/esm/middleware/index.js +2 -3
  42. package/dist/esm/middleware/index.js.map +1 -1
  43. package/dist/esm/streaming/create-lambda-adapter.js +39 -57
  44. package/dist/esm/streaming/create-lambda-adapter.js.map +1 -1
  45. package/package.json +23 -1
@@ -0,0 +1,56 @@
1
+ import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
2
+ export declare class DataStoreNotFoundError extends Error {
3
+ constructor(message: string);
4
+ }
5
+ export declare class DataStoreServiceError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ export declare class DataStoreUnavailableError extends Error {
9
+ constructor(message: string);
10
+ }
11
+ /**
12
+ * A class for reading entries from the data store.
13
+ *
14
+ * This class uses a singleton pattern.
15
+ * Use DataStore.getDataStore() to get the singleton instance.
16
+ */
17
+ export declare class DataStore {
18
+ private _tableName;
19
+ private _ddb;
20
+ private static _instance;
21
+ /** @internal Test hook: inject a document client for unit tests */
22
+ static _testDocumentClient: DynamoDBDocumentClient | null;
23
+ /** @internal Test hook: inject logMRTError for unit tests */
24
+ static _testLogMRTError: ((namespace: string, err: unknown, context?: Record<string, unknown>) => void) | null;
25
+ private constructor();
26
+ /**
27
+ * Get or create a DynamoDB document client (for abstraction of attribute values).
28
+ *
29
+ * @private
30
+ * @returns The DynamoDB document client
31
+ * @throws {DataStoreUnavailableError} The data store is unavailable
32
+ */
33
+ private getClient;
34
+ /**
35
+ * Get or create the singleton DataStore instance.
36
+ *
37
+ * @returns The singleton DataStore instance
38
+ */
39
+ static getDataStore(): DataStore;
40
+ /**
41
+ * Whether the data store can be used in the current environment.
42
+ *
43
+ * @returns true if the data store is available, false otherwise
44
+ */
45
+ isDataStoreAvailable(): boolean;
46
+ /**
47
+ * Fetch an entry from the data store.
48
+ *
49
+ * @param key The data store entry's key
50
+ * @returns An object containing the entry's key and value
51
+ * @throws {DataStoreUnavailableError} The data store is unavailable
52
+ * @throws {DataStoreNotFoundError} An entry with the given key cannot be found
53
+ * @throws {DataStoreServiceError} An internal error occurred
54
+ */
55
+ getEntry(key: string): Promise<Record<string, unknown> | undefined>;
56
+ }
@@ -0,0 +1,124 @@
1
+ /*
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * SPDX-License-Identifier: Apache-2
4
+ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+ import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
7
+ import { DynamoDBDocumentClient, GetCommand } from '@aws-sdk/lib-dynamodb';
8
+ import { logMRTError } from '../utils/utils.js';
9
+ export class DataStoreNotFoundError extends Error {
10
+ constructor(message) {
11
+ super(message);
12
+ this.name = 'DataStoreNotFoundError';
13
+ Object.setPrototypeOf(this, DataStoreNotFoundError.prototype);
14
+ }
15
+ }
16
+ export class DataStoreServiceError extends Error {
17
+ constructor(message) {
18
+ super(message);
19
+ this.name = 'DataStoreServiceError';
20
+ Object.setPrototypeOf(this, DataStoreServiceError.prototype);
21
+ }
22
+ }
23
+ export class DataStoreUnavailableError extends Error {
24
+ constructor(message) {
25
+ super(message);
26
+ this.name = 'DataStoreUnavailableError';
27
+ Object.setPrototypeOf(this, DataStoreUnavailableError.prototype);
28
+ }
29
+ }
30
+ /**
31
+ * A class for reading entries from the data store.
32
+ *
33
+ * This class uses a singleton pattern.
34
+ * Use DataStore.getDataStore() to get the singleton instance.
35
+ */
36
+ export class DataStore {
37
+ _tableName = '';
38
+ _ddb = null;
39
+ static _instance = null;
40
+ /** @internal Test hook: inject a document client for unit tests */
41
+ static _testDocumentClient = null;
42
+ /** @internal Test hook: inject logMRTError for unit tests */
43
+ static _testLogMRTError = null;
44
+ constructor() {
45
+ // Private constructor for singleton; use DataStore.getDataStore() instead.
46
+ }
47
+ /**
48
+ * Get or create a DynamoDB document client (for abstraction of attribute values).
49
+ *
50
+ * @private
51
+ * @returns The DynamoDB document client
52
+ * @throws {DataStoreUnavailableError} The data store is unavailable
53
+ */
54
+ getClient() {
55
+ if (!this.isDataStoreAvailable()) {
56
+ throw new DataStoreUnavailableError('The data store is unavailable.');
57
+ }
58
+ if (DataStore._testDocumentClient) {
59
+ this._tableName = `DataAccessLayer-${process.env.AWS_REGION}`;
60
+ return DataStore._testDocumentClient;
61
+ }
62
+ if (!this._ddb) {
63
+ this._tableName = `DataAccessLayer-${process.env.AWS_REGION}`;
64
+ this._ddb = DynamoDBDocumentClient.from(new DynamoDBClient({
65
+ region: process.env.AWS_REGION,
66
+ }));
67
+ }
68
+ return this._ddb;
69
+ }
70
+ /**
71
+ * Get or create the singleton DataStore instance.
72
+ *
73
+ * @returns The singleton DataStore instance
74
+ */
75
+ static getDataStore() {
76
+ if (!DataStore._instance) {
77
+ DataStore._instance = new DataStore();
78
+ }
79
+ return DataStore._instance;
80
+ }
81
+ /**
82
+ * Whether the data store can be used in the current environment.
83
+ *
84
+ * @returns true if the data store is available, false otherwise
85
+ */
86
+ isDataStoreAvailable() {
87
+ return Boolean(process.env.AWS_REGION && process.env.MOBIFY_PROPERTY_ID && process.env.DEPLOY_TARGET);
88
+ }
89
+ /**
90
+ * Fetch an entry from the data store.
91
+ *
92
+ * @param key The data store entry's key
93
+ * @returns An object containing the entry's key and value
94
+ * @throws {DataStoreUnavailableError} The data store is unavailable
95
+ * @throws {DataStoreNotFoundError} An entry with the given key cannot be found
96
+ * @throws {DataStoreServiceError} An internal error occurred
97
+ */
98
+ async getEntry(key) {
99
+ if (!this.isDataStoreAvailable()) {
100
+ throw new DataStoreUnavailableError('The data store is unavailable.');
101
+ }
102
+ const ddb = this.getClient();
103
+ let response;
104
+ try {
105
+ response = await ddb.send(new GetCommand({
106
+ TableName: this._tableName,
107
+ Key: {
108
+ projectEnvironment: `${process.env.MOBIFY_PROPERTY_ID} ${process.env.DEPLOY_TARGET}`,
109
+ key,
110
+ },
111
+ }));
112
+ }
113
+ catch (error) {
114
+ const logFn = DataStore._testLogMRTError ?? logMRTError;
115
+ logFn('data_store', error, { key, tableName: this._tableName });
116
+ throw new DataStoreServiceError('Data store request failed.');
117
+ }
118
+ if (!response.Item?.value) {
119
+ throw new DataStoreNotFoundError(`Data store entry '${key}' not found.`);
120
+ }
121
+ return { key, value: response.Item.value };
122
+ }
123
+ }
124
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/data-store/index.ts"],"names":[],"mappings":"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"}
@@ -1,56 +1,5 @@
1
- import { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';
2
- export declare class DataStoreNotFoundError extends Error {
3
- constructor(message: string);
4
- }
5
- export declare class DataStoreServiceError extends Error {
6
- constructor(message: string);
7
- }
8
- export declare class DataStoreUnavailableError extends Error {
9
- constructor(message: string);
10
- }
11
1
  /**
12
- * A class for reading entries from the data store.
13
- *
14
- * This class uses a singleton pattern.
15
- * Use DataStore.getDataStore() to get the singleton instance.
2
+ * @deprecated Import data-store symbols from `@salesforce/mrt-utilities/data-store`.
3
+ * This compatibility path is kept for backward compatibility.
16
4
  */
17
- export declare class DataStore {
18
- private _tableName;
19
- private _ddb;
20
- private static _instance;
21
- /** @internal Test hook: inject a document client for unit tests */
22
- static _testDocumentClient: DynamoDBDocumentClient | null;
23
- /** @internal Test hook: inject logMRTError for unit tests */
24
- static _testLogMRTError: ((namespace: string, err: unknown, context?: Record<string, unknown>) => void) | null;
25
- private constructor();
26
- /**
27
- * Get or create a DynamoDB document client (for abstraction of attribute values).
28
- *
29
- * @private
30
- * @returns The DynamoDB document client
31
- * @throws {DataStoreUnavailableError} The data store is unavailable
32
- */
33
- private getClient;
34
- /**
35
- * Get or create the singleton DataStore instance.
36
- *
37
- * @returns The singleton DataStore instance
38
- */
39
- static getDataStore(): DataStore;
40
- /**
41
- * Whether the data store can be used in the current environment.
42
- *
43
- * @returns true if the data store is available, false otherwise
44
- */
45
- isDataStoreAvailable(): boolean;
46
- /**
47
- * Fetch an entry from the data store.
48
- *
49
- * @param key The data store entry's key
50
- * @returns An object containing the entry's key and value
51
- * @throws {DataStoreUnavailableError} The data store is unavailable
52
- * @throws {DataStoreNotFoundError} An entry with the given key cannot be found
53
- * @throws {DataStoreServiceError} An internal error occurred
54
- */
55
- getEntry(key: string): Promise<Record<string, unknown> | undefined>;
56
- }
5
+ export * from '../data-store/index.js';
@@ -3,122 +3,9 @@
3
3
  * SPDX-License-Identifier: Apache-2
4
4
  * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
5
  */
6
- import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
7
- import { DynamoDBDocumentClient, GetCommand } from '@aws-sdk/lib-dynamodb';
8
- import { logMRTError } from '../utils/utils.js';
9
- export class DataStoreNotFoundError extends Error {
10
- constructor(message) {
11
- super(message);
12
- this.name = 'DataStoreNotFoundError';
13
- Object.setPrototypeOf(this, DataStoreNotFoundError.prototype);
14
- }
15
- }
16
- export class DataStoreServiceError extends Error {
17
- constructor(message) {
18
- super(message);
19
- this.name = 'DataStoreServiceError';
20
- Object.setPrototypeOf(this, DataStoreServiceError.prototype);
21
- }
22
- }
23
- export class DataStoreUnavailableError extends Error {
24
- constructor(message) {
25
- super(message);
26
- this.name = 'DataStoreUnavailableError';
27
- Object.setPrototypeOf(this, DataStoreUnavailableError.prototype);
28
- }
29
- }
30
6
  /**
31
- * A class for reading entries from the data store.
32
- *
33
- * This class uses a singleton pattern.
34
- * Use DataStore.getDataStore() to get the singleton instance.
7
+ * @deprecated Import data-store symbols from `@salesforce/mrt-utilities/data-store`.
8
+ * This compatibility path is kept for backward compatibility.
35
9
  */
36
- export class DataStore {
37
- _tableName = '';
38
- _ddb = null;
39
- static _instance = null;
40
- /** @internal Test hook: inject a document client for unit tests */
41
- static _testDocumentClient = null;
42
- /** @internal Test hook: inject logMRTError for unit tests */
43
- static _testLogMRTError = null;
44
- constructor() {
45
- // Private constructor for singleton; use DataStore.getDataStore() instead.
46
- }
47
- /**
48
- * Get or create a DynamoDB document client (for abstraction of attribute values).
49
- *
50
- * @private
51
- * @returns The DynamoDB document client
52
- * @throws {DataStoreUnavailableError} The data store is unavailable
53
- */
54
- getClient() {
55
- if (!this.isDataStoreAvailable()) {
56
- throw new DataStoreUnavailableError('The data store is unavailable.');
57
- }
58
- if (DataStore._testDocumentClient) {
59
- this._tableName = `DataAccessLayer-${process.env.AWS_REGION}`;
60
- return DataStore._testDocumentClient;
61
- }
62
- if (!this._ddb) {
63
- this._tableName = `DataAccessLayer-${process.env.AWS_REGION}`;
64
- this._ddb = DynamoDBDocumentClient.from(new DynamoDBClient({
65
- region: process.env.AWS_REGION,
66
- }));
67
- }
68
- return this._ddb;
69
- }
70
- /**
71
- * Get or create the singleton DataStore instance.
72
- *
73
- * @returns The singleton DataStore instance
74
- */
75
- static getDataStore() {
76
- if (!DataStore._instance) {
77
- DataStore._instance = new DataStore();
78
- }
79
- return DataStore._instance;
80
- }
81
- /**
82
- * Whether the data store can be used in the current environment.
83
- *
84
- * @returns true if the data store is available, false otherwise
85
- */
86
- isDataStoreAvailable() {
87
- return Boolean(process.env.AWS_REGION && process.env.MOBIFY_PROPERTY_ID && process.env.DEPLOY_TARGET);
88
- }
89
- /**
90
- * Fetch an entry from the data store.
91
- *
92
- * @param key The data store entry's key
93
- * @returns An object containing the entry's key and value
94
- * @throws {DataStoreUnavailableError} The data store is unavailable
95
- * @throws {DataStoreNotFoundError} An entry with the given key cannot be found
96
- * @throws {DataStoreServiceError} An internal error occurred
97
- */
98
- async getEntry(key) {
99
- if (!this.isDataStoreAvailable()) {
100
- throw new DataStoreUnavailableError('The data store is unavailable.');
101
- }
102
- const ddb = this.getClient();
103
- let response;
104
- try {
105
- response = await ddb.send(new GetCommand({
106
- TableName: this._tableName,
107
- Key: {
108
- projectEnvironment: `${process.env.MOBIFY_PROPERTY_ID} ${process.env.DEPLOY_TARGET}`,
109
- key,
110
- },
111
- }));
112
- }
113
- catch (error) {
114
- const logFn = DataStore._testLogMRTError ?? logMRTError;
115
- logFn('data_store', error, { key, tableName: this._tableName });
116
- throw new DataStoreServiceError('Data store request failed.');
117
- }
118
- if (!response.Item?.value) {
119
- throw new DataStoreNotFoundError(`Data store entry '${key}' not found.`);
120
- }
121
- return { key, value: response.Item.value };
122
- }
123
- }
10
+ export * from '../data-store/index.js';
124
11
  //# sourceMappingURL=data-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"data-store.js","sourceRoot":"","sources":["../../../src/middleware/data-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-store.js","sourceRoot":"","sources":["../../../src/middleware/data-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,cAAc,wBAAwB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './middleware.js';
2
+ export { type ProxyConfig } from '../utils/configure-proxying.js';
@@ -0,0 +1,8 @@
1
+ /*
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * SPDX-License-Identifier: Apache-2
4
+ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+ export * from './middleware.js';
7
+ export {} from '../utils/configure-proxying.js';
8
+ //# sourceMappingURL=express.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"express.js","sourceRoot":"","sources":["../../../src/middleware/express.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAkB,MAAM,gCAAgC,CAAC"}
@@ -1,3 +1,2 @@
1
- export * from './data-store.js';
2
- export * from './middleware.js';
3
- export { type ProxyConfig } from '../utils/configure-proxying.js';
1
+ export * from '../data-store/index.js';
2
+ export * from './express.js';
@@ -3,7 +3,6 @@
3
3
  * SPDX-License-Identifier: Apache-2
4
4
  * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
5
  */
6
- export * from './data-store.js';
7
- export * from './middleware.js';
8
- export {} from '../utils/configure-proxying.js';
6
+ export * from '../data-store/index.js';
7
+ export * from './express.js';
9
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAkB,MAAM,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/middleware/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC"}
@@ -44,7 +44,7 @@ export function createStreamingLambdaAdapter(app, responseStream, compressionCon
44
44
  const isStreamOpen = responseStream && responseStream.writable && !responseStream.destroyed && !responseStream.writableEnded;
45
45
  if (isStreamOpen && typeof responseStream.write === 'function') {
46
46
  const errorMessage = error instanceof Error ? error.message : String(error);
47
- responseStream.write(`HTTP/1.1 500 Internal Server Error\r\n\r\nInternal Server Error: ${errorMessage}`);
47
+ responseStream.write(`Internal Server Error: ${errorMessage}`);
48
48
  }
49
49
  else {
50
50
  console.error('[error handler] Cannot write error - stream is closed');
@@ -81,34 +81,17 @@ async function streamResponse(event, responseStream, context, app, compressionCo
81
81
  reject(err);
82
82
  }
83
83
  };
84
+ // See events defined for hhtp.serverResponse interface here:
85
+ // https://nodejs.org/docs/latest-v24.x/api/http.html#class-httpserverresponse
84
86
  // Handle response finish
85
- expressResponse.once('finish', () => {
86
- resolveOnce();
87
- });
87
+ expressResponse.once('finish', resolveOnce);
88
+ // handle response close, either after a 'finish' or if underlying
89
+ // connection is closed early
90
+ expressResponse.once('close', resolveOnce);
88
91
  // Handle response errors
89
- expressResponse.once('error', (err) => {
90
- rejectOnce(err);
91
- });
92
+ expressResponse.once('error', rejectOnce);
92
93
  try {
93
- app(expressRequest, expressResponse, (err) => {
94
- if (err) {
95
- console.error('Express app error:', err);
96
- rejectOnce(err);
97
- }
98
- else {
99
- // If response has finished, resolveOnce will be called by the finish event
100
- // Otherwise, resolve after a short delay to allow async operations
101
- if (expressResponse.finished) {
102
- resolveOnce();
103
- }
104
- else {
105
- // Wait a bit for the response to finish
106
- setTimeout(() => {
107
- resolveOnce();
108
- }, 10);
109
- }
110
- }
111
- });
94
+ app(expressRequest, expressResponse);
112
95
  }
113
96
  catch (error) {
114
97
  console.error('Error in streamResponse:', error);
@@ -410,6 +393,7 @@ export function createExpressResponse(responseStream, event, context, request, c
410
393
  }
411
394
  if (!isStreamOpen()) {
412
395
  console.error('Cannot initialize response - stream is closed');
396
+ emitCloseOnce(response);
413
397
  return;
414
398
  }
415
399
  // Collect all current headers from the response
@@ -432,7 +416,7 @@ export function createExpressResponse(responseStream, event, context, request, c
432
416
  // Create HttpResponseStream with metadata
433
417
  // This writes the HTTP status and headers to the stream
434
418
  const metadata = {
435
- statusCode,
419
+ statusCode: response.statusCode || statusCode,
436
420
  headers,
437
421
  };
438
422
  const cookies = metadata.headers['set-cookie'];
@@ -442,6 +426,14 @@ export function createExpressResponse(responseStream, event, context, request, c
442
426
  }
443
427
  metadata.headers = convertHeaders(metadata.headers);
444
428
  httpResponseStream = awslambda.HttpResponseStream.from(responseStream, metadata);
429
+ // Bind 'finish' and 'close' handlers to emit the same events on the response object
430
+ httpResponseStream.on('finish', () => {
431
+ response.finished = true;
432
+ response.emit('finish');
433
+ });
434
+ httpResponseStream.on('close', () => {
435
+ response.emit('close');
436
+ });
445
437
  // Set up compression stream if compression is enabled
446
438
  // The compression stream pipes to httpResponseStream, which pipes to responseStream
447
439
  // 'identity' means no encoding, so we should not initialize compression for it
@@ -529,7 +521,7 @@ export function createExpressResponse(responseStream, event, context, request, c
529
521
  headerObj = reasonPhrase;
530
522
  reasonPhrase = undefined;
531
523
  }
532
- statusCode = code || statusCode;
524
+ statusCode = code || this.statusCode || statusCode;
533
525
  this.statusCode = statusCode;
534
526
  // Set statusMessage if provided
535
527
  if (reasonPhrase) {
@@ -552,6 +544,7 @@ export function createExpressResponse(responseStream, event, context, request, c
552
544
  res.write = function (chunk) {
553
545
  if (!isStreamOpen()) {
554
546
  console.error(`Cannot write - stream is closed`);
547
+ emitCloseOnce(this);
555
548
  return false;
556
549
  }
557
550
  initializeResponse(this);
@@ -575,6 +568,14 @@ export function createExpressResponse(responseStream, event, context, request, c
575
568
  httpResponseStream.flush();
576
569
  }
577
570
  };
571
+ let emittedClose = false;
572
+ const emitCloseOnce = (response) => {
573
+ if (emittedClose) {
574
+ return;
575
+ }
576
+ response.emit('close');
577
+ emittedClose = true;
578
+ };
578
579
  /**
579
580
  * Ends the appropriate stream(s) and emits the finish event
580
581
  * If compression is enabled, ends the compression stream which will automatically
@@ -583,50 +584,30 @@ export function createExpressResponse(responseStream, event, context, request, c
583
584
  * @param response - The Express response object to emit finish event on
584
585
  */
585
586
  const endStream = (response) => {
586
- if (shouldCompress && compressionStream) {
587
- try {
588
- // Flush compression stream to ensure all buffered data is written
589
- _flush();
590
- // End compression stream - this will automatically end httpResponseStream
591
- // due to the pipe with { end: true } option
592
- compressionStream.end(() => {
593
- response.finished = true;
594
- response.emit('finish');
595
- });
596
- }
597
- catch (error) {
598
- console.error(`Error ending compression stream:`, error);
599
- // Still emit finish even if there was an error
600
- response.finished = true;
601
- response.emit('finish');
602
- }
603
- }
604
- else if (httpResponseStream && httpResponseStream.writable) {
605
- // No compression, end httpResponseStream directly
587
+ const stream = (shouldCompress && compressionStream) || (httpResponseStream?.writable && httpResponseStream);
588
+ if (stream) {
606
589
  try {
607
590
  _flush();
608
- httpResponseStream.end(() => {
609
- response.finished = true;
610
- response.emit('finish');
611
- });
591
+ stream.end();
612
592
  }
613
593
  catch (error) {
614
- console.error(`Error ending httpResponseStream:`, error);
594
+ console.error(`Error ending stream:`, error);
615
595
  response.finished = true;
616
- response.emit('finish');
596
+ emitCloseOnce(response);
617
597
  }
618
598
  }
619
599
  else {
620
600
  console.error(`Cannot call end() - stream is closed`);
621
601
  // Still emit finish to prevent hanging
622
602
  response.finished = true;
623
- response.emit('finish');
603
+ emitCloseOnce(response);
624
604
  }
625
605
  };
626
606
  // @ts-expect-error - Type signature doesn't match ServerResponse.end exactly, but our implementation is compatible
627
607
  res.end = function (chunk) {
628
608
  if (!isStreamOpen()) {
629
609
  console.error(`Cannot end - stream is already closed`);
610
+ emitCloseOnce(this);
630
611
  return this;
631
612
  }
632
613
  initializeResponse(this);
@@ -654,9 +635,8 @@ export function createExpressResponse(responseStream, event, context, request, c
654
635
  // Add Express-specific methods that aren't in ServerResponse
655
636
  res.status = function (code, message) {
656
637
  this.statusCode = code;
657
- statusCode = code;
658
638
  if (message !== undefined) {
659
- statusMessage = message;
639
+ this.statusMessage = message;
660
640
  }
661
641
  return this;
662
642
  };
@@ -700,6 +680,7 @@ export function createExpressResponse(responseStream, event, context, request, c
700
680
  if (!responseStarted) {
701
681
  if (!isStreamOpen()) {
702
682
  console.error('[res.flushHeaders] Cannot flush headers - stream is closed');
683
+ emitCloseOnce(this);
703
684
  return this;
704
685
  }
705
686
  // Collect all current headers and send them
@@ -739,6 +720,7 @@ export function createExpressResponse(responseStream, event, context, request, c
739
720
  res.flush = function () {
740
721
  if (!isStreamOpen()) {
741
722
  console.error(`Cannot flush - stream is closed`);
723
+ emitCloseOnce(this);
742
724
  return this;
743
725
  }
744
726
  initializeResponse(this);