glasswork 1.1.0 → 1.3.0
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.
- package/CHANGELOG.md +57 -1
- package/README.md +3 -0
- package/dist/auth/better-auth-provider.d.ts +11 -3
- package/dist/auth/better-auth-provider.d.ts.map +1 -1
- package/dist/auth/better-auth-provider.js +15 -6
- package/dist/auth/better-auth-provider.js.map +1 -1
- package/dist/auth/middleware.d.ts +1 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +18 -10
- package/dist/auth/middleware.js.map +1 -1
- package/dist/auth/types.d.ts +6 -2
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/core/bootstrap.d.ts.map +1 -1
- package/dist/core/bootstrap.js +16 -7
- package/dist/core/bootstrap.js.map +1 -1
- package/dist/core/module-graph.js +3 -0
- package/dist/core/module-graph.js.map +1 -1
- package/dist/core/request-scope.d.ts +12 -0
- package/dist/core/request-scope.d.ts.map +1 -0
- package/dist/core/request-scope.js +86 -0
- package/dist/core/request-scope.js.map +1 -0
- package/dist/core/route-factory.d.ts +1 -0
- package/dist/core/route-factory.d.ts.map +1 -1
- package/dist/core/types.d.ts +6 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/email/compiler/compiler.d.ts.map +1 -1
- package/dist/email/compiler/compiler.js +69 -17
- package/dist/email/compiler/compiler.js.map +1 -1
- package/dist/email/compiler/tokenizer.js +4 -2
- package/dist/email/compiler/tokenizer.js.map +1 -1
- package/dist/email/compiler/types.d.ts +2 -0
- package/dist/email/compiler/types.d.ts.map +1 -1
- package/dist/email/transports/ses-transport.d.ts +8 -0
- package/dist/email/transports/ses-transport.d.ts.map +1 -1
- package/dist/email/transports/ses-transport.js +132 -25
- package/dist/email/transports/ses-transport.js.map +1 -1
- package/dist/email/webhooks/handler-factory.d.ts +1 -0
- package/dist/email/webhooks/handler-factory.d.ts.map +1 -1
- package/dist/email/webhooks/handler-factory.js +40 -38
- package/dist/email/webhooks/handler-factory.js.map +1 -1
- package/dist/email/webhooks/notification-parser.d.ts +1 -1
- package/dist/email/webhooks/notification-parser.js +1 -1
- package/dist/email/webhooks/signature-verification.d.ts +4 -2
- package/dist/email/webhooks/signature-verification.d.ts.map +1 -1
- package/dist/email/webhooks/signature-verification.js +63 -8
- package/dist/email/webhooks/signature-verification.js.map +1 -1
- package/dist/email/webhooks/subscription-handler.d.ts +4 -2
- package/dist/email/webhooks/subscription-handler.d.ts.map +1 -1
- package/dist/email/webhooks/subscription-handler.js +42 -6
- package/dist/email/webhooks/subscription-handler.js.map +1 -1
- package/dist/email/webhooks/types.d.ts +17 -2
- package/dist/email/webhooks/types.d.ts.map +1 -1
- package/dist/jobs/define-job.d.ts +4 -4
- package/dist/jobs/define-job.d.ts.map +1 -1
- package/dist/jobs/drivers/mock-driver.d.ts.map +1 -1
- package/dist/jobs/drivers/mock-driver.js +11 -1
- package/dist/jobs/drivers/mock-driver.js.map +1 -1
- package/dist/jobs/index.d.ts +2 -2
- package/dist/jobs/index.d.ts.map +1 -1
- package/dist/jobs/index.js +1 -1
- package/dist/jobs/index.js.map +1 -1
- package/dist/jobs/job-service.d.ts +6 -6
- package/dist/jobs/job-service.d.ts.map +1 -1
- package/dist/jobs/job-service.js +8 -0
- package/dist/jobs/job-service.js.map +1 -1
- package/dist/jobs/observability/emf.d.ts +5 -15
- package/dist/jobs/observability/emf.d.ts.map +1 -1
- package/dist/jobs/observability/emf.js +87 -67
- package/dist/jobs/observability/emf.js.map +1 -1
- package/dist/jobs/observability/index.d.ts +2 -4
- package/dist/jobs/observability/index.d.ts.map +1 -1
- package/dist/jobs/observability/index.js +1 -3
- package/dist/jobs/observability/index.js.map +1 -1
- package/dist/jobs/observability/types.d.ts +16 -193
- package/dist/jobs/observability/types.d.ts.map +1 -1
- package/dist/jobs/types.d.ts +4 -4
- package/dist/jobs/types.d.ts.map +1 -1
- package/dist/jobs/worker.d.ts +5 -0
- package/dist/jobs/worker.d.ts.map +1 -1
- package/dist/jobs/worker.js +73 -12
- package/dist/jobs/worker.js.map +1 -1
- package/dist/list-query/builder.d.ts +2 -1
- package/dist/list-query/builder.d.ts.map +1 -1
- package/dist/list-query/builder.js +23 -15
- package/dist/list-query/builder.js.map +1 -1
- package/dist/middleware/rate-limit.d.ts.map +1 -1
- package/dist/middleware/rate-limit.js +60 -92
- package/dist/middleware/rate-limit.js.map +1 -1
- package/dist/openapi/openapi.d.ts +1 -4
- package/dist/openapi/openapi.d.ts.map +1 -1
- package/dist/openapi/openapi.js +15 -35
- package/dist/openapi/openapi.js.map +1 -1
- package/dist/sse/index.d.ts +6 -0
- package/dist/sse/index.d.ts.map +1 -0
- package/dist/sse/index.js +18 -0
- package/dist/sse/index.js.map +1 -0
- package/dist/sse/sse-broadcaster.d.ts +38 -0
- package/dist/sse/sse-broadcaster.d.ts.map +1 -0
- package/dist/sse/sse-broadcaster.js +118 -0
- package/dist/sse/sse-broadcaster.js.map +1 -0
- package/dist/utils/get-client-ip.d.ts.map +1 -1
- package/dist/utils/get-client-ip.js +22 -13
- package/dist/utils/get-client-ip.js.map +1 -1
- package/package.json +11 -3
- package/dist/jobs/observability/client.d.ts +0 -26
- package/dist/jobs/observability/client.d.ts.map +0 -1
- package/dist/jobs/observability/client.js +0 -286
- package/dist/jobs/observability/client.js.map +0 -1
- package/dist/jobs/observability/dashboard.d.ts +0 -19
- package/dist/jobs/observability/dashboard.d.ts.map +0 -1
- package/dist/jobs/observability/dashboard.js +0 -144
- package/dist/jobs/observability/dashboard.js.map +0 -1
- package/dist/jobs/scheduler.d.ts +0 -17
- package/dist/jobs/scheduler.d.ts.map +0 -1
- package/dist/jobs/scheduler.js +0 -83
- package/dist/jobs/scheduler.js.map +0 -1
|
@@ -15,7 +15,8 @@ export class ListQueryBuilder {
|
|
|
15
15
|
prismaParams;
|
|
16
16
|
paginationEnabled = true;
|
|
17
17
|
context;
|
|
18
|
-
|
|
18
|
+
searchWhere;
|
|
19
|
+
scopeConditions = [];
|
|
19
20
|
transformFn;
|
|
20
21
|
constructor(config, validationConfig) {
|
|
21
22
|
this.config = config;
|
|
@@ -30,18 +31,19 @@ export class ListQueryBuilder {
|
|
|
30
31
|
catch {
|
|
31
32
|
throw new ValidationException('Invalid list query.');
|
|
32
33
|
}
|
|
34
|
+
this.searchWhere = undefined;
|
|
33
35
|
// Apply global search if configured
|
|
34
36
|
if (this.config.search && this.parsedQuery?.search) {
|
|
35
37
|
const searchWhere = buildGlobalSearchWhere(this.config.search, this.parsedQuery.search);
|
|
36
38
|
if (Object.keys(searchWhere).length > 0) {
|
|
37
|
-
this.
|
|
39
|
+
this.searchWhere = searchWhere;
|
|
38
40
|
}
|
|
39
41
|
}
|
|
40
42
|
return this;
|
|
41
43
|
}
|
|
42
44
|
scope(conditions) {
|
|
43
45
|
if (conditions && Object.keys(conditions).length > 0) {
|
|
44
|
-
this.
|
|
46
|
+
this.scopeConditions.push(conditions);
|
|
45
47
|
}
|
|
46
48
|
return this;
|
|
47
49
|
}
|
|
@@ -83,14 +85,16 @@ export class ListQueryBuilder {
|
|
|
83
85
|
if (this.config.mapFilters) {
|
|
84
86
|
validatedWhere = applyFilterMappings(validatedWhere, this.config.mapFilters);
|
|
85
87
|
}
|
|
86
|
-
//
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
// Keep user-controlled filters/search separate from trusted application scopes.
|
|
89
|
+
// Facet aggregations may remove their own user filter, but never a scope.
|
|
90
|
+
const userWhere = this.mergeWhereConditions([
|
|
91
|
+
validatedWhere,
|
|
92
|
+
...(this.searchWhere ? [this.searchWhere] : []),
|
|
93
|
+
]);
|
|
94
|
+
const trustedWhereConditions = this.scopeConditions.map((condition) => this.validationConfig
|
|
95
|
+
? parseWhereFilterValues(condition, this.validationConfig.whereSchema)
|
|
96
|
+
: condition);
|
|
97
|
+
const mergedWhere = this.mergeWhereConditions([userWhere, ...trustedWhereConditions]);
|
|
94
98
|
// Deep copy for params.where to prevent any potential mutation
|
|
95
99
|
// buildAggregationParams uses mergedWhere directly since removeFieldFromWhere is immutable
|
|
96
100
|
const whereForParams = structuredClone(mergedWhere);
|
|
@@ -99,7 +103,7 @@ export class ListQueryBuilder {
|
|
|
99
103
|
orderBy: this.resolveProcessedOrderBy(validatedOrderBy),
|
|
100
104
|
skip: this.paginationEnabled ? this.prismaParams.skip : 0,
|
|
101
105
|
take: this.paginationEnabled ? this.prismaParams.take : undefined,
|
|
102
|
-
aggregations: this.buildAggregationParams(
|
|
106
|
+
aggregations: this.buildAggregationParams(userWhere, trustedWhereConditions),
|
|
103
107
|
};
|
|
104
108
|
if (this.transformFn) {
|
|
105
109
|
return this.transformFn(params);
|
|
@@ -112,7 +116,7 @@ export class ListQueryBuilder {
|
|
|
112
116
|
? applySortMappings(rawOrderBy, this.config.mapSorts)
|
|
113
117
|
: rawOrderBy);
|
|
114
118
|
}
|
|
115
|
-
buildAggregationParams(
|
|
119
|
+
buildAggregationParams(userWhere, trustedWhereConditions) {
|
|
116
120
|
if (!this.config.aggregations || !this.prismaParams) {
|
|
117
121
|
return undefined;
|
|
118
122
|
}
|
|
@@ -124,11 +128,15 @@ export class ListQueryBuilder {
|
|
|
124
128
|
throw new Error(`Invalid field path for aggregation: ${key}`);
|
|
125
129
|
}
|
|
126
130
|
// Remove filter on the aggregation field to get counts across all values
|
|
127
|
-
const
|
|
131
|
+
const userWhereWithoutAggregationField = this.removeFieldFromWhere(userWhere, fieldPath);
|
|
132
|
+
const aggregationWhere = this.mergeWhereConditions([
|
|
133
|
+
userWhereWithoutAggregationField,
|
|
134
|
+
...trustedWhereConditions,
|
|
135
|
+
]);
|
|
128
136
|
aggregationParams[key] = {
|
|
129
137
|
by: fieldPath,
|
|
130
138
|
_count: { [lastField]: true },
|
|
131
|
-
where:
|
|
139
|
+
where: structuredClone(aggregationWhere),
|
|
132
140
|
};
|
|
133
141
|
}
|
|
134
142
|
return aggregationParams;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/list-query/builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAuB,MAAM,qBAAqB,CAAC;AAC/E,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAqB,MAAM,mBAAmB,CAAC;AASzE,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAElG,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAwBpD,MAAM,OAAO,gBAAgB;
|
|
1
|
+
{"version":3,"file":"builder.js","sourceRoot":"","sources":["../../src/list-query/builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limit.d.ts","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAmFzD;;;GAGG;AACH,wBAAgB,4BAA4B,IAAI,IAAI,CAKnD;AAuFD;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,iBAAiB,CAsEtF"}
|
|
@@ -14,25 +14,17 @@ let shutdownHookRegistered = false;
|
|
|
14
14
|
class MemoryStore {
|
|
15
15
|
store = new Map();
|
|
16
16
|
cleanupTimer = null;
|
|
17
|
-
async
|
|
17
|
+
async consume(key, windowEnd, maxRequests) {
|
|
18
18
|
const item = this.store.get(key);
|
|
19
19
|
if (!item) {
|
|
20
|
-
|
|
20
|
+
this.store.set(key, { count: 1, windowEnd });
|
|
21
|
+
return { allowed: true, count: 1, windowEnd };
|
|
21
22
|
}
|
|
22
|
-
if (item.
|
|
23
|
-
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
return item;
|
|
27
|
-
}
|
|
28
|
-
async set(key, value) {
|
|
29
|
-
this.store.set(key, value);
|
|
30
|
-
}
|
|
31
|
-
async increment(key) {
|
|
32
|
-
const item = this.store.get(key);
|
|
33
|
-
if (item) {
|
|
34
|
-
item.count += 1;
|
|
23
|
+
if (item.count >= maxRequests) {
|
|
24
|
+
return { allowed: false, count: item.count, windowEnd: item.windowEnd };
|
|
35
25
|
}
|
|
26
|
+
item.count += 1;
|
|
27
|
+
return { allowed: true, count: item.count, windowEnd: item.windowEnd };
|
|
36
28
|
}
|
|
37
29
|
/**
|
|
38
30
|
* Start periodic cleanup of expired entries.
|
|
@@ -113,76 +105,64 @@ class DynamoDBStore {
|
|
|
113
105
|
async getClient() {
|
|
114
106
|
return this.clientPromise;
|
|
115
107
|
}
|
|
116
|
-
async
|
|
117
|
-
const { GetCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
118
|
-
const client = await this.getClient();
|
|
119
|
-
try {
|
|
120
|
-
// @ts-expect-error - client type is complex
|
|
121
|
-
const { Item } = await client.send(new GetCommand({
|
|
122
|
-
TableName: this.tableName,
|
|
123
|
-
Key: { bucketId: key },
|
|
124
|
-
}));
|
|
125
|
-
if (!Item || Item.windowEnd < Date.now()) {
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
return {
|
|
129
|
-
count: Item.count,
|
|
130
|
-
windowEnd: Item.windowEnd,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
// Log error but fail open to prevent DynamoDB issues from blocking traffic
|
|
135
|
-
logger.error('DynamoDB rate limit get failed:', error);
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
async set(key, value) {
|
|
140
|
-
const { PutCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
141
|
-
const client = await this.getClient();
|
|
142
|
-
const expiresAt = Math.floor(value.windowEnd / 1000);
|
|
143
|
-
try {
|
|
144
|
-
// @ts-expect-error - client type is complex
|
|
145
|
-
await client.send(new PutCommand({
|
|
146
|
-
TableName: this.tableName,
|
|
147
|
-
Item: {
|
|
148
|
-
bucketId: key,
|
|
149
|
-
count: value.count,
|
|
150
|
-
windowEnd: value.windowEnd,
|
|
151
|
-
expiresAt,
|
|
152
|
-
},
|
|
153
|
-
}));
|
|
154
|
-
}
|
|
155
|
-
catch (error) {
|
|
156
|
-
logger.error('DynamoDB rate limit set failed:', error);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
async increment(key) {
|
|
108
|
+
async consume(key, windowEnd, maxRequests) {
|
|
160
109
|
const { UpdateCommand } = await import('@aws-sdk/lib-dynamodb');
|
|
161
110
|
const client = await this.getClient();
|
|
162
111
|
try {
|
|
163
112
|
// @ts-expect-error - client type is complex
|
|
164
|
-
await client.send(new UpdateCommand({
|
|
113
|
+
const result = await client.send(new UpdateCommand({
|
|
165
114
|
TableName: this.tableName,
|
|
166
115
|
Key: { bucketId: key },
|
|
167
|
-
UpdateExpression: 'SET #
|
|
168
|
-
|
|
169
|
-
|
|
116
|
+
UpdateExpression: 'SET #windowEnd = :windowEnd, #expiresAt = :expiresAt ADD #count :one',
|
|
117
|
+
ConditionExpression: 'attribute_not_exists(#count) OR #count < :maxRequests',
|
|
118
|
+
ExpressionAttributeNames: {
|
|
119
|
+
'#count': 'count',
|
|
120
|
+
'#windowEnd': 'windowEnd',
|
|
121
|
+
'#expiresAt': 'expiresAt',
|
|
122
|
+
},
|
|
123
|
+
ExpressionAttributeValues: {
|
|
124
|
+
':one': 1,
|
|
125
|
+
':maxRequests': maxRequests,
|
|
126
|
+
':windowEnd': windowEnd,
|
|
127
|
+
':expiresAt': Math.ceil(windowEnd / 1000),
|
|
128
|
+
},
|
|
129
|
+
ReturnValues: 'ALL_NEW',
|
|
170
130
|
}));
|
|
131
|
+
const count = Number(result.Attributes?.count ?? 1);
|
|
132
|
+
return { allowed: true, count, windowEnd };
|
|
171
133
|
}
|
|
172
134
|
catch (error) {
|
|
173
|
-
|
|
135
|
+
if (isConditionalCheckFailed(error)) {
|
|
136
|
+
return { allowed: false, count: maxRequests, windowEnd };
|
|
137
|
+
}
|
|
138
|
+
throw error;
|
|
174
139
|
}
|
|
175
140
|
}
|
|
176
141
|
}
|
|
142
|
+
function isConditionalCheckFailed(error) {
|
|
143
|
+
return error instanceof Error && error.name === 'ConditionalCheckFailedException';
|
|
144
|
+
}
|
|
177
145
|
/**
|
|
178
146
|
* Create rate limiting middleware
|
|
179
147
|
*/
|
|
180
148
|
export function createRateLimitMiddleware(options) {
|
|
181
|
-
const { storage, windowMs = 60000, maxRequests = 100, dynamodb } = options;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
149
|
+
const { storage, windowMs = 60000, maxRequests = 100, dynamodb, keyGenerator } = options;
|
|
150
|
+
if (!Number.isFinite(windowMs) || windowMs <= 0) {
|
|
151
|
+
throw new Error('Rate limit windowMs must be greater than zero');
|
|
152
|
+
}
|
|
153
|
+
if (!Number.isInteger(maxRequests) || maxRequests <= 0) {
|
|
154
|
+
throw new Error('Rate limit maxRequests must be a positive integer');
|
|
155
|
+
}
|
|
156
|
+
let store;
|
|
157
|
+
if (storage === 'dynamodb') {
|
|
158
|
+
if (!dynamodb?.tableName.trim()) {
|
|
159
|
+
throw new Error('Rate limit DynamoDB storage requires dynamodb.tableName');
|
|
160
|
+
}
|
|
161
|
+
store = new DynamoDBStore(dynamodb.tableName, dynamodb.region);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
store = new MemoryStore();
|
|
165
|
+
}
|
|
186
166
|
// Start cleanup for memory store
|
|
187
167
|
if (store instanceof MemoryStore) {
|
|
188
168
|
store.startCleanup();
|
|
@@ -193,9 +173,9 @@ export function createRateLimitMiddleware(options) {
|
|
|
193
173
|
if (resolvedTrustProxy !== context.get('trustProxy')) {
|
|
194
174
|
context.set('trustProxy', resolvedTrustProxy);
|
|
195
175
|
}
|
|
196
|
-
const clientId = getClientIp(context);
|
|
197
176
|
const now = Date.now();
|
|
198
|
-
const
|
|
177
|
+
const windowNumber = Math.floor(now / windowMs);
|
|
178
|
+
const windowEnd = (windowNumber + 1) * windowMs;
|
|
199
179
|
const setHeaders = (remaining, resetMs) => {
|
|
200
180
|
context.header('RateLimit-Limit', String(maxRequests));
|
|
201
181
|
context.header('RateLimit-Remaining', String(Math.max(0, remaining)));
|
|
@@ -203,28 +183,16 @@ export function createRateLimitMiddleware(options) {
|
|
|
203
183
|
};
|
|
204
184
|
// Rate limiting logic - fail open on errors
|
|
205
185
|
let shouldBlock = false;
|
|
206
|
-
let remaining = maxRequests
|
|
207
|
-
let resetMs =
|
|
186
|
+
let remaining = maxRequests;
|
|
187
|
+
let resetMs = windowEnd - now;
|
|
208
188
|
try {
|
|
209
|
-
const
|
|
210
|
-
if (!
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
else if (item.count >= maxRequests) {
|
|
217
|
-
// Rate limit exceeded
|
|
218
|
-
shouldBlock = true;
|
|
219
|
-
remaining = 0;
|
|
220
|
-
resetMs = item.windowEnd - now;
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
// Increment counter
|
|
224
|
-
await store.increment(clientId);
|
|
225
|
-
remaining = maxRequests - (item.count + 1);
|
|
226
|
-
resetMs = item.windowEnd - now;
|
|
227
|
-
}
|
|
189
|
+
const clientId = keyGenerator ? await keyGenerator(context) : getClientIp(context);
|
|
190
|
+
if (!clientId)
|
|
191
|
+
throw new Error('Rate limit key generator returned an empty key');
|
|
192
|
+
const result = await store.consume(`${clientId}:${windowNumber}`, windowEnd, maxRequests);
|
|
193
|
+
shouldBlock = !result.allowed;
|
|
194
|
+
remaining = Math.max(0, maxRequests - result.count);
|
|
195
|
+
resetMs = Math.max(0, result.windowEnd - now);
|
|
228
196
|
}
|
|
229
197
|
catch (error) {
|
|
230
198
|
logger.error('Rate limiter error:', error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,MAAM,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAC;AAEnD,2DAA2D;AAC3D,MAAM,2BAA2B,GAAG,MAAM,CAAC;AAE3C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAe,CAAC;AAC5C,IAAI,sBAAsB,GAAG,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../../src/middleware/rate-limit.ts"],"names":[],"mappings":"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"}
|
|
@@ -44,10 +44,7 @@ export interface ConfigureOpenAPIResult {
|
|
|
44
44
|
*
|
|
45
45
|
* @example
|
|
46
46
|
* ```typescript
|
|
47
|
-
* //
|
|
48
|
-
* configureOpenAPI({ app, environment, openapi });
|
|
49
|
-
*
|
|
50
|
-
* // Explicit write after routes are registered (recommended)
|
|
47
|
+
* // Configure first, then explicitly write after routes are registered.
|
|
51
48
|
* const { writeSpec } = configureOpenAPI({ app, environment, openapi });
|
|
52
49
|
* // ... register all routes ...
|
|
53
50
|
* await writeSpec?.();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/openapi/openapi.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"openapi.d.ts","sourceRoot":"","sources":["../../src/openapi/openapi.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAqB,MAAM,MAAM,CAAC;AAGpD,OAAO,KAAK,EACV,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAK1B,MAAM,WAAW,uBAAuB;IACtC,GAAG,EAAE,IAAI,CAAC;IACV,WAAW,EAAE,WAAW,CAAC;IACzB,OAAO,EAAE,cAAc,CAAC;IACxB,SAAS,CAAC,EAAE,gBAAgB,CAAC;IAC7B,UAAU,CAAC,EAAE,iBAAiB,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;;;;;;;;;;;OAcG;IACH,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,sBAAsB,CA8DzF"}
|
package/dist/openapi/openapi.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { writeFile } from 'node:fs/promises';
|
|
2
|
-
import {
|
|
3
|
-
import { openAPIRouteHandler } from 'hono-openapi';
|
|
2
|
+
import { generateSpecs, openAPIRouteHandler } from 'hono-openapi';
|
|
4
3
|
import { deepMerge } from '../utils/deep-merge.js';
|
|
5
4
|
import { createLogger } from '../utils/logger.js';
|
|
6
5
|
import { defaultOpenAPIComponents } from './defaults.js';
|
|
7
|
-
/** Default delay before writing OpenAPI spec (ms). Allows routes to register. */
|
|
8
|
-
const DEFAULT_WRITE_DELAY_MS = 1000;
|
|
9
6
|
/**
|
|
10
7
|
* Configure OpenAPI documentation for the application.
|
|
11
8
|
*
|
|
@@ -22,10 +19,7 @@ const DEFAULT_WRITE_DELAY_MS = 1000;
|
|
|
22
19
|
*
|
|
23
20
|
* @example
|
|
24
21
|
* ```typescript
|
|
25
|
-
* //
|
|
26
|
-
* configureOpenAPI({ app, environment, openapi });
|
|
27
|
-
*
|
|
28
|
-
* // Explicit write after routes are registered (recommended)
|
|
22
|
+
* // Configure first, then explicitly write after routes are registered.
|
|
29
23
|
* const { writeSpec } = configureOpenAPI({ app, environment, openapi });
|
|
30
24
|
* // ... register all routes ...
|
|
31
25
|
* await writeSpec?.();
|
|
@@ -54,40 +48,26 @@ export function configureOpenAPI(options) {
|
|
|
54
48
|
}
|
|
55
49
|
// Serve Swagger UI (development only by default)
|
|
56
50
|
if (shouldServeUI) {
|
|
57
|
-
|
|
51
|
+
let handlerPromise;
|
|
52
|
+
app.get('/api', async (c, next) => {
|
|
53
|
+
handlerPromise ??= import('@hono/swagger-ui')
|
|
54
|
+
.then(({ swaggerUI }) => swaggerUI({ url: '/api/openapi.json' }))
|
|
55
|
+
.catch((cause) => {
|
|
56
|
+
throw new Error('Unable to load Swagger UI. Install the optional peer with: npm install @hono/swagger-ui', { cause });
|
|
57
|
+
});
|
|
58
|
+
const handler = await handlerPromise;
|
|
59
|
+
return handler(c, next);
|
|
60
|
+
});
|
|
58
61
|
}
|
|
59
62
|
// Create writeSpec function if file writing is configured
|
|
60
63
|
let writeSpec;
|
|
61
64
|
if (openapi.writeToFile) {
|
|
62
65
|
const filePath = openapi.writeToFile;
|
|
63
66
|
writeSpec = async () => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
// Use Hono's built-in request method to simulate the request
|
|
68
|
-
const response = await app.request('/api/openapi.json');
|
|
69
|
-
specContent = await response.text();
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
// If not serving specs, generate manually
|
|
73
|
-
// Mount a temporary internal endpoint
|
|
74
|
-
app.get('/api/openapi-internal.json', openAPIRouteHandler(app, { documentation: mergedDocumentation }));
|
|
75
|
-
const response = await app.request('/api/openapi-internal.json');
|
|
76
|
-
const spec = (await response.json());
|
|
77
|
-
specContent = JSON.stringify(spec, null, 2);
|
|
78
|
-
}
|
|
79
|
-
await writeFile(filePath, specContent, 'utf-8');
|
|
80
|
-
logger.info(`OpenAPI spec written to ${filePath}`);
|
|
81
|
-
}
|
|
82
|
-
catch (error) {
|
|
83
|
-
logger.error('Failed to write OpenAPI spec:', error);
|
|
84
|
-
}
|
|
67
|
+
const spec = await generateSpecs(app, { documentation: mergedDocumentation });
|
|
68
|
+
await writeFile(filePath, JSON.stringify(spec, null, 2), 'utf-8');
|
|
69
|
+
logger.info(`OpenAPI spec written to ${filePath}`);
|
|
85
70
|
};
|
|
86
|
-
// Auto-write with delay for backward compatibility
|
|
87
|
-
// NOTE: For more reliable writes, call writeSpec() explicitly after registering routes
|
|
88
|
-
setTimeout(() => {
|
|
89
|
-
writeSpec?.();
|
|
90
|
-
}, DEFAULT_WRITE_DELAY_MS);
|
|
91
71
|
}
|
|
92
72
|
return { writeSpec };
|
|
93
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/openapi/openapi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"openapi.js","sourceRoot":"","sources":["../../src/openapi/openapi.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ModuleConfig } from '../core/types.js';
|
|
2
|
+
import { type SseBroadcasterOptions } from './sse-broadcaster.js';
|
|
3
|
+
export { SseBroadcaster, type SseBroadcasterOptions } from './sse-broadcaster.js';
|
|
4
|
+
/** Register one broadcaster per application container, without exposing a public route. */
|
|
5
|
+
export declare function createSseModule(options?: SseBroadcasterOptions): ModuleConfig;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sse/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElF,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAElF,2FAA2F;AAC3F,wBAAgB,eAAe,CAAC,OAAO,GAAE,qBAA0B,GAAG,YAAY,CAYjF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineModule } from '../core/module.js';
|
|
2
|
+
import { SseBroadcaster } from './sse-broadcaster.js';
|
|
3
|
+
export { SseBroadcaster } from './sse-broadcaster.js';
|
|
4
|
+
/** Register one broadcaster per application container, without exposing a public route. */
|
|
5
|
+
export function createSseModule(options = {}) {
|
|
6
|
+
return defineModule({
|
|
7
|
+
name: 'sse',
|
|
8
|
+
providers: [
|
|
9
|
+
{
|
|
10
|
+
provide: 'sseBroadcaster',
|
|
11
|
+
useFactory: () => new SseBroadcaster(options),
|
|
12
|
+
scope: 'SINGLETON',
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
exports: ['sseBroadcaster'],
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/sse/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAElF,OAAO,EAAE,cAAc,EAA8B,MAAM,sBAAsB,CAAC;AAElF,2FAA2F;AAC3F,MAAM,UAAU,eAAe,CAAC,OAAO,GAA0B,EAAE;IACjE,OAAO,YAAY,CAAC;QAClB,IAAI,EAAE,KAAK;QACX,SAAS,EAAE;YACT;gBACE,OAAO,EAAE,gBAAgB;gBACzB,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC;gBAC7C,KAAK,EAAE,WAAW;aACnB;SACF;QACD,OAAO,EAAE,CAAC,gBAAgB,CAAC;KAC5B,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { OnModuleDestroy } from '../core/types.js';
|
|
2
|
+
interface StreamContext {
|
|
3
|
+
readonly req: {
|
|
4
|
+
readonly raw: Request;
|
|
5
|
+
};
|
|
6
|
+
header(name: string, value: string): void;
|
|
7
|
+
newResponse(body: ReadableStream<Uint8Array>): Response;
|
|
8
|
+
body(body: null, status: 503): Response;
|
|
9
|
+
}
|
|
10
|
+
export interface SseBroadcasterOptions {
|
|
11
|
+
/** Heartbeat interval; 0 disables heartbeats. Defaults to 15 seconds. */
|
|
12
|
+
readonly heartbeatIntervalMs?: number;
|
|
13
|
+
/** Maximum queued bytes per connection. Slow clients are disconnected. Defaults to 64 KiB. */
|
|
14
|
+
readonly maxBufferedBytes?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* In-process, best-effort notifications for a single authorized audience.
|
|
18
|
+
* Mount stream() behind application middleware. Clients must refresh state on
|
|
19
|
+
* every connection: events are not persisted or replayed across reconnects.
|
|
20
|
+
*/
|
|
21
|
+
export declare class SseBroadcaster<Events extends object = Record<string, unknown>> implements OnModuleDestroy {
|
|
22
|
+
private readonly connections;
|
|
23
|
+
private readonly encoder;
|
|
24
|
+
private readonly heartbeatIntervalMs;
|
|
25
|
+
private readonly maxBufferedBytes;
|
|
26
|
+
private isStopped;
|
|
27
|
+
constructor(options?: SseBroadcasterOptions);
|
|
28
|
+
get clientCount(): number;
|
|
29
|
+
/** Open an ordinary HTTP response; authentication/authorization belongs to the route. */
|
|
30
|
+
stream(context: StreamContext): Response;
|
|
31
|
+
/** Serialize once and deliver without letting slow consumers block the publisher. */
|
|
32
|
+
broadcast<Event extends keyof Events & string>(event: Event, payload: Events[Event]): void;
|
|
33
|
+
/** Synchronous cleanup also works when a consumer never reads its response. */
|
|
34
|
+
onModuleDestroy(): void;
|
|
35
|
+
private createConnection;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=sse-broadcaster.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-broadcaster.d.ts","sourceRoot":"","sources":["../../src/sse/sse-broadcaster.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQxD,UAAU,aAAa;IACrB,QAAQ,CAAC,GAAG,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;KAAE,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,WAAW,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,QAAQ,CAAC;IACxD,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,GAAG,QAAQ,CAAC;CACzC;AAED,MAAM,WAAW,qBAAqB;IACpC,yEAAyE;IACzE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IACtC,8FAA8F;IAC9F,QAAQ,CAAC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CACpC;AAQD;;;;GAIG;AACH,qBAAa,cAAc,CAAC,MAAM,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CACzE,YAAW,eAAe;IAE1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,SAAS,CAAS;IAE1B,YAAY,OAAO,GAAE,qBAA0B,EAW9C;IAED,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,yFAAyF;IACzF,MAAM,CAAC,OAAO,EAAE,aAAa,GAAG,QAAQ,CAsBvC;IAED,qFAAqF;IACrF,SAAS,CAAC,KAAK,SAAS,MAAM,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAkBzF;IAED,+EAA+E;IAC/E,eAAe,IAAI,IAAI,CAMtB;IAED,OAAO,CAAC,gBAAgB;CA+DzB"}
|