glasswork 1.1.0 → 1.2.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 +36 -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/worker.d.ts +2 -0
- package/dist/jobs/worker.d.ts.map +1 -1
- package/dist/jobs/worker.js +2 -0
- 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/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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const DEFAULT_HEARTBEAT_INTERVAL_MS = 15_000;
|
|
2
|
+
const DEFAULT_MAX_BUFFERED_BYTES = 65_536;
|
|
3
|
+
const CONNECTED_FRAME = 'retry: 3000\n: connected\n\n';
|
|
4
|
+
const HEARTBEAT_FRAME = ': heartbeat\n\n';
|
|
5
|
+
/**
|
|
6
|
+
* In-process, best-effort notifications for a single authorized audience.
|
|
7
|
+
* Mount stream() behind application middleware. Clients must refresh state on
|
|
8
|
+
* every connection: events are not persisted or replayed across reconnects.
|
|
9
|
+
*/
|
|
10
|
+
export class SseBroadcaster {
|
|
11
|
+
connections = new Set();
|
|
12
|
+
encoder = new TextEncoder();
|
|
13
|
+
heartbeatIntervalMs;
|
|
14
|
+
maxBufferedBytes;
|
|
15
|
+
isStopped = false;
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
|
|
18
|
+
this.maxBufferedBytes = options.maxBufferedBytes ?? DEFAULT_MAX_BUFFERED_BYTES;
|
|
19
|
+
if (!Number.isFinite(this.heartbeatIntervalMs) || this.heartbeatIntervalMs < 0) {
|
|
20
|
+
throw new RangeError('heartbeatIntervalMs must be a finite non-negative number');
|
|
21
|
+
}
|
|
22
|
+
if (!Number.isSafeInteger(this.maxBufferedBytes) || this.maxBufferedBytes < 64) {
|
|
23
|
+
throw new RangeError('maxBufferedBytes must be an integer of at least 64');
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
get clientCount() {
|
|
27
|
+
return this.connections.size;
|
|
28
|
+
}
|
|
29
|
+
/** Open an ordinary HTTP response; authentication/authorization belongs to the route. */
|
|
30
|
+
stream(context) {
|
|
31
|
+
if (this.isStopped) {
|
|
32
|
+
return context.body(null, 503);
|
|
33
|
+
}
|
|
34
|
+
let connection;
|
|
35
|
+
const body = new ReadableStream({
|
|
36
|
+
start: (controller) => {
|
|
37
|
+
connection = this.createConnection(controller, context.req.raw.signal);
|
|
38
|
+
},
|
|
39
|
+
cancel: () => connection?.cancel(),
|
|
40
|
+
}, { highWaterMark: this.maxBufferedBytes, size: (chunk) => chunk.byteLength });
|
|
41
|
+
context.header('Content-Type', 'text/event-stream; charset=utf-8');
|
|
42
|
+
context.header('Cache-Control', 'no-cache, no-transform');
|
|
43
|
+
context.header('X-Accel-Buffering', 'no');
|
|
44
|
+
return context.newResponse(body);
|
|
45
|
+
}
|
|
46
|
+
/** Serialize once and deliver without letting slow consumers block the publisher. */
|
|
47
|
+
broadcast(event, payload) {
|
|
48
|
+
if (!event || /[\r\n\0]/.test(event)) {
|
|
49
|
+
throw new TypeError('SSE event names must be non-empty and contain no CR, LF or NUL');
|
|
50
|
+
}
|
|
51
|
+
const data = JSON.stringify(payload);
|
|
52
|
+
if (data === undefined) {
|
|
53
|
+
throw new TypeError('SSE payload must be JSON serializable');
|
|
54
|
+
}
|
|
55
|
+
const frame = this.encoder.encode(`event: ${event}\ndata: ${data}\n\n`);
|
|
56
|
+
if (frame.byteLength > this.maxBufferedBytes) {
|
|
57
|
+
throw new RangeError('SSE event exceeds maxBufferedBytes');
|
|
58
|
+
}
|
|
59
|
+
for (const connection of this.connections) {
|
|
60
|
+
connection.send(frame);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/** Synchronous cleanup also works when a consumer never reads its response. */
|
|
64
|
+
onModuleDestroy() {
|
|
65
|
+
this.isStopped = true;
|
|
66
|
+
for (const connection of this.connections) {
|
|
67
|
+
connection.close();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
createConnection(controller, signal) {
|
|
71
|
+
let isClosed = false;
|
|
72
|
+
let heartbeat;
|
|
73
|
+
const connection = {
|
|
74
|
+
cancel: () => {
|
|
75
|
+
if (isClosed) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
isClosed = true;
|
|
79
|
+
clearInterval(heartbeat);
|
|
80
|
+
signal.removeEventListener('abort', connection.close);
|
|
81
|
+
this.connections.delete(connection);
|
|
82
|
+
},
|
|
83
|
+
close: () => {
|
|
84
|
+
if (isClosed) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
connection.cancel();
|
|
88
|
+
// Close synchronously without waiting for the bounded queue to drain.
|
|
89
|
+
controller.close();
|
|
90
|
+
},
|
|
91
|
+
send: (frame) => {
|
|
92
|
+
if (isClosed) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
if ((controller.desiredSize ?? 0) < frame.byteLength) {
|
|
96
|
+
connection.cancel();
|
|
97
|
+
controller.error(new Error('SSE client exceeded its buffer limit'));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
controller.enqueue(frame);
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
this.connections.add(connection);
|
|
104
|
+
signal.addEventListener('abort', connection.close, { once: true });
|
|
105
|
+
if (signal.aborted) {
|
|
106
|
+
connection.close();
|
|
107
|
+
return connection;
|
|
108
|
+
}
|
|
109
|
+
// Flush response headers and tell native EventSource how long to wait before retrying.
|
|
110
|
+
connection.send(this.encoder.encode(CONNECTED_FRAME));
|
|
111
|
+
if (this.heartbeatIntervalMs > 0) {
|
|
112
|
+
const frame = this.encoder.encode(HEARTBEAT_FRAME);
|
|
113
|
+
heartbeat = setInterval(() => connection.send(frame), this.heartbeatIntervalMs);
|
|
114
|
+
}
|
|
115
|
+
return connection;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=sse-broadcaster.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-broadcaster.js","sourceRoot":"","sources":["../../src/sse/sse-broadcaster.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-client-ip.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-ip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"get-client-ip.d.ts","sourceRoot":"","sources":["../../src/utils/get-client-ip.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAyB9C"}
|
|
@@ -20,6 +20,9 @@
|
|
|
20
20
|
* ```
|
|
21
21
|
*/
|
|
22
22
|
export function getClientIp(c) {
|
|
23
|
+
const lambdaIp = getLambdaClientIp(c.env);
|
|
24
|
+
if (lambdaIp)
|
|
25
|
+
return lambdaIp;
|
|
23
26
|
const trustProxy = c.get('trustProxy') === true;
|
|
24
27
|
// Only honor proxy headers when explicitly trusted
|
|
25
28
|
if (trustProxy) {
|
|
@@ -36,19 +39,25 @@ export function getClientIp(c) {
|
|
|
36
39
|
return trimmed;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// This will throw in non-Node environments
|
|
43
|
-
const { getConnInfo } = require('@hono/node-server/conninfo');
|
|
44
|
-
const info = getConnInfo(c);
|
|
45
|
-
if (info?.remote?.address) {
|
|
46
|
-
return info.remote.address;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
// Not in Node.js environment or module not available
|
|
51
|
-
}
|
|
42
|
+
const nodeIp = getNodeClientIp(c.env);
|
|
43
|
+
if (nodeIp)
|
|
44
|
+
return nodeIp;
|
|
52
45
|
return 'unknown';
|
|
53
46
|
}
|
|
47
|
+
function getLambdaClientIp(environment) {
|
|
48
|
+
if (!environment || typeof environment !== 'object')
|
|
49
|
+
return undefined;
|
|
50
|
+
const env = environment;
|
|
51
|
+
const sourceIp = env.requestContext?.http?.sourceIp ?? env.requestContext?.identity?.sourceIp;
|
|
52
|
+
return typeof sourceIp === 'string' && sourceIp.trim() ? sourceIp.trim() : undefined;
|
|
53
|
+
}
|
|
54
|
+
function getNodeClientIp(environment) {
|
|
55
|
+
if (!environment || typeof environment !== 'object')
|
|
56
|
+
return undefined;
|
|
57
|
+
const remoteAddress = environment
|
|
58
|
+
.incoming?.socket?.remoteAddress;
|
|
59
|
+
return typeof remoteAddress === 'string' && remoteAddress.trim()
|
|
60
|
+
? remoteAddress.trim()
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
54
63
|
//# sourceMappingURL=get-client-ip.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-client-ip.js","sourceRoot":"","sources":["../../src/utils/get-client-ip.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,WAAW,CAAC,CAAU;IACpC,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IAEhD,mDAAmD;IACnD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtD,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAC/C,IAAI,EAAE;gBAAE,OAAO,EAAE,CAAC;QACpB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,
|
|
1
|
+
{"version":3,"file":"get-client-ip.js","sourceRoot":"","sources":["../../src/utils/get-client-ip.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,WAAW,CAAC,CAAU;IACpC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC;IAEhD,mDAAmD;IACnD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,aAAa,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;QACtD,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;YAC/C,IAAI,EAAE;gBAAE,OAAO,EAAE,CAAC;QACpB,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC1C,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YAC/B,IAAI,OAAO;gBAAE,OAAO,OAAO,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,MAAM;QAAE,OAAO,MAAM,CAAC;IAE1B,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAoB;IAC7C,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEtE,MAAM,GAAG,GAAG,WAKX,CAAC;IACF,MAAM,QAAQ,GAAG,GAAG,CAAC,cAAc,EAAE,IAAI,EAAE,QAAQ,IAAI,GAAG,CAAC,cAAc,EAAE,QAAQ,EAAE,QAAQ,CAAC;IAC9F,OAAO,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACvF,CAAC;AAED,SAAS,eAAe,CAAC,WAAoB;IAC3C,IAAI,CAAC,WAAW,IAAI,OAAO,WAAW,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEtE,MAAM,aAAa,GAAI,WAAuE;SAC3F,QAAQ,EAAE,MAAM,EAAE,aAAa,CAAC;IACnC,OAAO,OAAO,aAAa,KAAK,QAAQ,IAAI,aAAa,CAAC,IAAI,EAAE;QAC9D,CAAC,CAAC,aAAa,CAAC,IAAI,EAAE;QACtB,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "glasswork",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A transparent, Lambda-optimized web framework for building OpenAPI-compliant REST APIs.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -61,7 +61,12 @@
|
|
|
61
61
|
"import": "./dist/audit/index.js",
|
|
62
62
|
"default": "./dist/audit/index.js"
|
|
63
63
|
},
|
|
64
|
-
"./package.json": "./package.json"
|
|
64
|
+
"./package.json": "./package.json",
|
|
65
|
+
"./sse": {
|
|
66
|
+
"types": "./dist/sse/index.d.ts",
|
|
67
|
+
"import": "./dist/sse/index.js",
|
|
68
|
+
"default": "./dist/sse/index.js"
|
|
69
|
+
}
|
|
65
70
|
},
|
|
66
71
|
"files": [
|
|
67
72
|
"dist",
|
|
@@ -204,11 +209,13 @@
|
|
|
204
209
|
"@types/node": "^26.5.0",
|
|
205
210
|
"@vitest/coverage-v8": "^4.1.11",
|
|
206
211
|
"awilix": "^13.0.5",
|
|
212
|
+
"better-auth": "^1.7.5",
|
|
207
213
|
"dotenv": "^17.4.2",
|
|
208
214
|
"hono": "^4.13.7",
|
|
209
215
|
"hono-openapi": "^1.3.2",
|
|
210
216
|
"mermaid": "^11.17.2",
|
|
211
217
|
"mjml": "^5.4.0",
|
|
218
|
+
"postal-mime": "^2.7.6",
|
|
212
219
|
"prisma": "7.10.0",
|
|
213
220
|
"typescript": "^7.0.2",
|
|
214
221
|
"valibot": "^1.4.2",
|
|
@@ -216,7 +223,8 @@
|
|
|
216
223
|
"vitepress-plugin-llms": "^1.13.5",
|
|
217
224
|
"vitepress-plugin-mermaid": "^2.0.17",
|
|
218
225
|
"vitest": "^4.1.11",
|
|
219
|
-
"vue": "^3.5.42"
|
|
226
|
+
"vue": "^3.5.42",
|
|
227
|
+
"yaml": "^2.9.1"
|
|
220
228
|
},
|
|
221
229
|
"dependencies": {
|
|
222
230
|
"@hono/standard-validator": "^0.2.3",
|