unnbound-events 2.0.17 → 2.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.
- package/README.md +2 -2
- package/dist/lib/adapters/extended-sqs-client.d.ts +3 -3
- package/dist/lib/adapters/extended-sqs-client.js +2 -6
- package/dist/lib/adapters/http-adapter.d.ts +2 -2
- package/dist/lib/adapters/http-adapter.js +2 -2
- package/dist/lib/adapters/queue-adapter.d.ts +3 -4
- package/dist/lib/adapters/queue-adapter.js +4 -4
- package/dist/lib/enqueue.d.ts +5 -1
- package/dist/lib/enqueue.js +106 -11
- package/dist/lib/error.d.ts +2 -2
- package/dist/lib/event.d.ts +2 -2
- package/dist/lib/routing/endpoint.d.ts +4 -4
- package/dist/lib/routing/endpoint.js +2 -2
- package/dist/lib/routing/middleware.d.ts +2 -2
- package/dist/lib/routing/types.d.ts +2 -2
- package/dist/lib/server.d.ts +5 -6
- package/dist/lib/server.js +3 -2
- package/dist/lib/utils.d.ts +3 -3
- package/dist/lib/utils.js +3 -3
- package/package.json +20 -19
- package/LICENSE +0 -21
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@ Unified HTTP and SQS queue routing with a single API. Register handlers once, ha
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
|
|
8
|
+
bun add unnbound-events
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Quick Start
|
|
@@ -120,7 +120,7 @@ const server = createServer({
|
|
|
120
120
|
The queue adapter reads from:
|
|
121
121
|
|
|
122
122
|
- `UNNBOUND_SQS_URL` - Queue URL (required for queue listener)
|
|
123
|
-
- `UNNBOUND_AWS_REGION` - AWS region (default: `us-
|
|
123
|
+
- `UNNBOUND_AWS_REGION` - AWS region (default: `us-east-1`)
|
|
124
124
|
- `UNNBOUND_SQS_ENDPOINT` - Custom endpoint (optional)
|
|
125
125
|
|
|
126
126
|
```bash
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { S3Client } from '@aws-sdk/client-s3';
|
|
2
|
-
import { Message, ReceiveMessageCommand, SQSClient } from '@aws-sdk/client-sqs';
|
|
3
|
-
import { IncomingEvent, IncomingRequest } from '../event';
|
|
1
|
+
import { type S3Client } from '@aws-sdk/client-s3';
|
|
2
|
+
import { type Message, type ReceiveMessageCommand, SQSClient } from '@aws-sdk/client-sqs';
|
|
3
|
+
import type { IncomingEvent, IncomingRequest } from '../event';
|
|
4
4
|
export interface S3Pointer {
|
|
5
5
|
bucket: string;
|
|
6
6
|
key: string;
|
|
@@ -40,18 +40,14 @@ class ExtendedSQSClient extends client_sqs_1.SQSClient {
|
|
|
40
40
|
return this.parseEvent({ ...parsed, request: { ...parsed.request, body } });
|
|
41
41
|
}
|
|
42
42
|
isSqsMessage(message) {
|
|
43
|
-
return (!!message &&
|
|
44
|
-
typeof message === 'object' &&
|
|
45
|
-
'id' in message &&
|
|
46
|
-
'timestamp' in message &&
|
|
47
|
-
'request' in message);
|
|
43
|
+
return (!!message && typeof message === 'object' && 'id' in message && 'timestamp' in message && 'request' in message);
|
|
48
44
|
}
|
|
49
45
|
isS3PointerMessage(body) {
|
|
50
46
|
return Array.isArray(body) && body.length === 2 && body[0] === this.S3_POINTER_CLASS;
|
|
51
47
|
}
|
|
52
48
|
parseEvent(message) {
|
|
53
49
|
const method = message.request.method.toLowerCase();
|
|
54
|
-
const url = new URL(message.request.url,
|
|
50
|
+
const url = new URL(message.request.url, 'https://unnbound.ai');
|
|
55
51
|
const request = {
|
|
56
52
|
url: url.toString(),
|
|
57
53
|
method,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.HttpAdapter = void 0;
|
|
4
|
+
const node_server_1 = require("@hono/node-server");
|
|
4
5
|
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
5
6
|
const internal_1 = require("unnbound-logger-sdk/dist/internal");
|
|
6
|
-
const node_server_1 = require("@hono/node-server");
|
|
7
7
|
class HttpAdapter {
|
|
8
8
|
logger;
|
|
9
9
|
app;
|
|
@@ -13,7 +13,7 @@ class HttpAdapter {
|
|
|
13
13
|
}
|
|
14
14
|
async listen() {
|
|
15
15
|
try {
|
|
16
|
-
const port = parseInt(process.env.PORT ?? '3000');
|
|
16
|
+
const port = Number.parseInt(process.env.PORT ?? '3000');
|
|
17
17
|
const server = await new Promise((resolve, reject) => {
|
|
18
18
|
try {
|
|
19
19
|
const server = (0, node_server_1.serve)({ fetch: this.app.fetch, port }, () => resolve(server));
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import { type ILogger } from 'unnbound-logger-sdk';
|
|
3
3
|
export interface SqsRequest {
|
|
4
4
|
method: string;
|
|
5
5
|
url: string;
|
|
6
6
|
headers: Record<string, string>;
|
|
7
7
|
body?: any;
|
|
8
8
|
}
|
|
9
|
-
export
|
|
10
|
-
}
|
|
9
|
+
export type SqsMetadata = {};
|
|
11
10
|
export interface SqsMessage {
|
|
12
11
|
id: string;
|
|
13
12
|
timestamp: number;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.QueueAdapter = void 0;
|
|
4
|
-
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
5
|
-
const internal_1 = require("unnbound-logger-sdk/dist/internal");
|
|
6
4
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
7
5
|
const client_sqs_1 = require("@aws-sdk/client-sqs");
|
|
6
|
+
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
7
|
+
const internal_1 = require("unnbound-logger-sdk/dist/internal");
|
|
8
8
|
const utils_1 = require("../utils");
|
|
9
9
|
const extended_sqs_client_1 = require("./extended-sqs-client");
|
|
10
10
|
class QueueAdapter {
|
|
@@ -20,7 +20,7 @@ class QueueAdapter {
|
|
|
20
20
|
maxMessages: options?.maxMessages ?? 10,
|
|
21
21
|
visibilityTimeout: options?.visibilityTimeout ?? 20,
|
|
22
22
|
};
|
|
23
|
-
const region = process.env.UNNBOUND_AWS_REGION ?? process.env.AWS_REGION ?? 'us-
|
|
23
|
+
const region = process.env.UNNBOUND_AWS_REGION ?? process.env.AWS_REGION ?? 'us-east-1';
|
|
24
24
|
const endpoint = process.env.UNNBOUND_S3_ENDPOINT;
|
|
25
25
|
const s3 = new client_s3_1.S3Client({ region, endpoint, maxAttempts: 3 });
|
|
26
26
|
this.sqs = new extended_sqs_client_1.ExtendedSQSClient({ region, endpoint, s3, maxAttempts: 3 });
|
|
@@ -77,7 +77,7 @@ class QueueAdapter {
|
|
|
77
77
|
}
|
|
78
78
|
};
|
|
79
79
|
}
|
|
80
|
-
async processMessage({ message, event
|
|
80
|
+
async processMessage({ message, event }) {
|
|
81
81
|
try {
|
|
82
82
|
// It forward the request to the HTTP server that will
|
|
83
83
|
// handle it according to the routes the user set up.
|
package/dist/lib/enqueue.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
import { EventMetadata, IncomingRequest } from './event';
|
|
1
|
+
import type { EventMetadata, IncomingRequest } from './event';
|
|
2
2
|
export interface EnqueuedRequest extends Omit<IncomingRequest, 'url' | 'headers' | 'query'> {
|
|
3
3
|
query?: IncomingRequest['query'];
|
|
4
4
|
headers?: IncomingRequest['headers'];
|
|
5
5
|
}
|
|
6
|
+
/**
|
|
7
|
+
* Create an enqueuer that posts to the ingress service via HTTP.
|
|
8
|
+
* The ingress service publishes to SQS for async processing.
|
|
9
|
+
*/
|
|
6
10
|
export declare const createEnqueuer: () => (event: EnqueuedRequest, metadata?: Partial<EventMetadata>) => Promise<undefined>;
|
package/dist/lib/enqueue.js
CHANGED
|
@@ -5,29 +5,117 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.createEnqueuer = void 0;
|
|
7
7
|
const axios_1 = __importDefault(require("axios"));
|
|
8
|
-
const types_1 = require("unnbound-logger-sdk/dist/types");
|
|
9
8
|
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
10
9
|
const internal_1 = require("unnbound-logger-sdk/dist/internal");
|
|
11
10
|
const storage_1 = require("unnbound-logger-sdk/dist/storage");
|
|
11
|
+
const types_1 = require("unnbound-logger-sdk/dist/types");
|
|
12
|
+
/**
|
|
13
|
+
* Extract workspace shortId from workflow URL
|
|
14
|
+
*
|
|
15
|
+
* Supported formats:
|
|
16
|
+
* - New path-based: {env}.workflow.gotemper.com/sandbox/{shortId} → {shortId}
|
|
17
|
+
* - New path-based: {env}.workflow.gotemper.com/{shortId} → {shortId}
|
|
18
|
+
* - Legacy hostname: {shortId}.workspaces.{env}.unnbound.ai → {shortId}
|
|
19
|
+
* - Custom domain: proxy.domain.com/{shortId} → {shortId}
|
|
20
|
+
*/
|
|
12
21
|
const getWorkspaceId = (url) => {
|
|
13
22
|
url = url.replace(/^https?:\/\//, '');
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
23
|
+
// Custom domain: extract path after domain (not gotemper.com or legacy unnbound.ai)
|
|
24
|
+
if (!url.includes('gotemper.com') && !url.includes('unnbound.ai')) {
|
|
25
|
+
return url
|
|
26
|
+
.replace(/^.+?\/(.+)$/, '$1')
|
|
27
|
+
.replace(/^(sandbox\/)?a?sync\//, '')
|
|
28
|
+
.split('/')[0];
|
|
29
|
+
}
|
|
30
|
+
// New path-based format: {env}.workflow.gotemper.com/{sandbox/}{shortId} or workflow.gotemper.com/{sandbox/}{shortId}
|
|
31
|
+
if (url.includes('.workflow.') || url.startsWith('workflow.')) {
|
|
32
|
+
// Extract everything after the domain, then remove sandbox/ and async/ prefixes
|
|
33
|
+
const path = url.replace(/^.+?\/(.+)$/, '$1');
|
|
34
|
+
return path
|
|
35
|
+
.replace(/^sandbox\//, '')
|
|
36
|
+
.replace(/^a?sync\//, '')
|
|
37
|
+
.split('/')[0];
|
|
38
|
+
}
|
|
39
|
+
// Legacy hostname format: {shortId}.workspaces.{env}.unnbound.ai
|
|
40
|
+
return url.split('.')[0];
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Check if the workflow URL indicates a sandbox environment
|
|
44
|
+
*/
|
|
45
|
+
const isSandboxUrl = (url) => {
|
|
46
|
+
// Check if URL contains /sandbox/ path
|
|
47
|
+
return url.includes('/sandbox/') || url.includes('/sandbox');
|
|
19
48
|
};
|
|
20
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Extract workflow domain from URL
|
|
51
|
+
*
|
|
52
|
+
* Supports all environments by extracting the domain from the URL:
|
|
53
|
+
* - nick.dev.workflow.gotemper.com → nick.dev.workflow.gotemper.com (new pattern)
|
|
54
|
+
* - stg.dev.workflow.gotemper.com → stg.dev.workflow.gotemper.com (new pattern)
|
|
55
|
+
* - workflow.gotemper.com → workflow.gotemper.com (prod)
|
|
56
|
+
* - Custom domain: proxy.api.goaugment.com → proxy.api.goaugment.com
|
|
57
|
+
*
|
|
58
|
+
* Also handles legacy formats:
|
|
59
|
+
* - {shortId}.workspaces.{env}.unnbound.ai → {env}.dev.workflow.gotemper.com
|
|
60
|
+
*/
|
|
21
61
|
const getWorkflowDomain = (url) => {
|
|
22
|
-
|
|
62
|
+
// Remove protocol and extract hostname
|
|
63
|
+
const cleanUrl = url.replace(/^https?:\/\//, '');
|
|
64
|
+
const hostname = cleanUrl.split('/')[0];
|
|
65
|
+
// For gotemper.com or unnbound.ai domains, ensure we use the workflow subdomain pattern
|
|
66
|
+
if (hostname.includes('gotemper.com') || hostname.includes('unnbound.ai')) {
|
|
67
|
+
// New pattern: {env}.dev.workflow.{domain} - return as-is
|
|
68
|
+
if (hostname.includes('.workflow.')) {
|
|
69
|
+
return hostname;
|
|
70
|
+
}
|
|
71
|
+
// Prod pattern: workflow.{domain} - return as-is
|
|
72
|
+
if (hostname.startsWith('workflow.')) {
|
|
73
|
+
return hostname;
|
|
74
|
+
}
|
|
75
|
+
// Legacy hostname format: {shortId}.workspaces.{env}.unnbound.ai
|
|
76
|
+
// Extract env and construct workflow domain using new pattern with gotemper.com
|
|
77
|
+
const parts = hostname.split('.');
|
|
78
|
+
const workspacesIdx = parts.indexOf('workspaces');
|
|
79
|
+
if (workspacesIdx !== -1) {
|
|
80
|
+
// Everything after 'workspaces' is the env domain (e.g., 'stg.unnbound.ai')
|
|
81
|
+
const envParts = parts.slice(workspacesIdx + 1); // ['stg', 'unnbound', 'ai']
|
|
82
|
+
const env = envParts[0]; // 'stg'
|
|
83
|
+
// New pattern: {env}.dev.workflow.gotemper.com (always use gotemper.com now)
|
|
84
|
+
// 'unnbound' means prod (legacy unnbound.ai prod URL)
|
|
85
|
+
return env === 'unnbound' ? 'workflow.gotemper.com' : `${env}.dev.workflow.gotemper.com`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Custom domain - return hostname as-is
|
|
89
|
+
return hostname;
|
|
23
90
|
};
|
|
24
|
-
|
|
91
|
+
// Generate a simple UUID v4
|
|
92
|
+
const _generateId = () => {
|
|
93
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
94
|
+
const r = (Math.random() * 16) | 0;
|
|
95
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
96
|
+
return v.toString(16);
|
|
97
|
+
});
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Create an HTTP-based enqueuer that posts to the ingress service.
|
|
101
|
+
* Used for legacy SQS mode or cross-workflow communication.
|
|
102
|
+
*
|
|
103
|
+
* URL format:
|
|
104
|
+
* - Sandbox: https://{env}.dev.workflow.gotemper.com/sandbox/async/{shortId} (dev) or https://workflow.gotemper.com/sandbox/async/{shortId} (prod)
|
|
105
|
+
* - Production: https://{env}.dev.workflow.gotemper.com/async/{shortId} (dev) or https://workflow.gotemper.com/async/{shortId} (prod)
|
|
106
|
+
*/
|
|
107
|
+
const createHttpEnqueuer = () => {
|
|
25
108
|
const url = process.env.UNNBOUND_WORKFLOW_URL;
|
|
26
109
|
if (!url)
|
|
27
110
|
throw new Error('UNNBOUND_WORKFLOW_URL is not configured. Reach out to support.');
|
|
28
|
-
|
|
111
|
+
// Construct base URL with sandbox prefix if applicable
|
|
112
|
+
const workspaceId = getWorkspaceId(url);
|
|
113
|
+
const domain = getWorkflowDomain(url);
|
|
114
|
+
const sandboxPrefix = isSandboxUrl(url) ? '/sandbox' : '';
|
|
115
|
+
const baseURL = `https://${domain}${sandboxPrefix}/async/${workspaceId}`;
|
|
116
|
+
const client = (0, unnbound_logger_sdk_1.traceAxios)(axios_1.default.create({ baseURL }), { getPayload: internal_1.internal });
|
|
29
117
|
return async (event, metadata) => {
|
|
30
|
-
unnbound_logger_sdk_1.logger.info({ event, metadata }, 'Enqueuing event...');
|
|
118
|
+
unnbound_logger_sdk_1.logger.info({ event, metadata }, 'Enqueuing event via HTTP...');
|
|
31
119
|
if (!event.path.startsWith('/'))
|
|
32
120
|
throw new Error('Path must be relative.');
|
|
33
121
|
const { traceId, messageId } = storage_1.storage.getStore() ?? {};
|
|
@@ -51,4 +139,11 @@ const createEnqueuer = () => {
|
|
|
51
139
|
throw new Error(`Unhandled enqueue method: ${event.method}`);
|
|
52
140
|
};
|
|
53
141
|
};
|
|
142
|
+
/**
|
|
143
|
+
* Create an enqueuer that posts to the ingress service via HTTP.
|
|
144
|
+
* The ingress service publishes to SQS for async processing.
|
|
145
|
+
*/
|
|
146
|
+
const createEnqueuer = () => {
|
|
147
|
+
return createHttpEnqueuer();
|
|
148
|
+
};
|
|
54
149
|
exports.createEnqueuer = createEnqueuer;
|
package/dist/lib/error.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { StatusCode } from 'hono/utils/http-status';
|
|
2
|
-
import { StrictEventHandlerResult } from './event';
|
|
1
|
+
import type { StatusCode } from 'hono/utils/http-status';
|
|
2
|
+
import type { StrictEventHandlerResult } from './event';
|
|
3
3
|
export interface ServerErrorOptions extends ErrorOptions {
|
|
4
4
|
status?: StatusCode;
|
|
5
5
|
message?: string;
|
package/dist/lib/event.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { StatusCode } from 'hono/utils/http-status';
|
|
1
2
|
import type { HttpMethod } from 'unnbound-logger-sdk';
|
|
2
|
-
import { StatusCode } from 'hono/utils/http-status';
|
|
3
3
|
export interface IncomingRequest<B = any> {
|
|
4
4
|
url: string;
|
|
5
5
|
method: HttpMethod;
|
|
@@ -27,4 +27,4 @@ export interface StrictEventHandlerResult {
|
|
|
27
27
|
headers?: Record<string, string>;
|
|
28
28
|
body?: object | undefined | null;
|
|
29
29
|
}
|
|
30
|
-
export type EventHandlerResult = Partial<StrictEventHandlerResult> | undefined | null |
|
|
30
|
+
export type EventHandlerResult = Partial<StrictEventHandlerResult> | undefined | null | undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { Context } from 'hono';
|
|
2
|
-
import { EventHandlerResult, StrictEventHandlerResult } from '../event';
|
|
3
|
-
import { MiddlewareHandler } from './middleware';
|
|
4
|
-
import { EventEnvironment, EventVariables, MaybePromise } from './types';
|
|
1
|
+
import type { Context } from 'hono';
|
|
2
|
+
import type { EventHandlerResult, StrictEventHandlerResult } from '../event';
|
|
3
|
+
import { type MiddlewareHandler } from './middleware';
|
|
4
|
+
import type { EventEnvironment, EventVariables, MaybePromise } from './types';
|
|
5
5
|
export type Handler<I, R = EventHandlerResult> = (input: I) => MaybePromise<R>;
|
|
6
6
|
export interface Endpoint<I> {
|
|
7
7
|
(path: string, handler: Handler<I>): MaybePromise<void>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.attachTraceHeaders = exports.respondWith = exports.patchEndpoint = exports.parseEndpointArguments = exports.buildEndpointArguments = void 0;
|
|
4
|
-
const types_1 = require("unnbound-logger-sdk/dist/types");
|
|
5
|
-
const storage_1 = require("unnbound-logger-sdk/dist/storage");
|
|
6
4
|
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
5
|
+
const storage_1 = require("unnbound-logger-sdk/dist/storage");
|
|
6
|
+
const types_1 = require("unnbound-logger-sdk/dist/types");
|
|
7
7
|
const utils_1 = require("../utils");
|
|
8
8
|
const middleware_1 = require("./middleware");
|
|
9
9
|
const buildEndpointArguments = (...args) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Context, Next } from 'hono';
|
|
2
|
-
import { EventEnvironment, EventVariables, MaybePromise } from './types';
|
|
1
|
+
import type { Context, Next } from 'hono';
|
|
2
|
+
import type { EventEnvironment, EventVariables, MaybePromise } from './types';
|
|
3
3
|
export type MiddlewareHandler<I> = (input: I, next: Next) => MaybePromise<void>;
|
|
4
4
|
export interface Middleware<I> {
|
|
5
5
|
(...middlewares: MiddlewareHandler<I>[]): MaybePromise<void>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Env } from 'hono';
|
|
2
|
-
import { IncomingEvent, MatchedIncomingRequest } from '../event';
|
|
1
|
+
import type { Env } from 'hono';
|
|
2
|
+
import type { IncomingEvent, MatchedIncomingRequest } from '../event';
|
|
3
3
|
export type MaybePromise<V> = Promise<V> | V;
|
|
4
4
|
interface EventInternalVariables<V extends object> {
|
|
5
5
|
set: <K extends keyof V>(key: K, value: V[K]) => void;
|
package/dist/lib/server.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { ILogger } from 'unnbound-logger-sdk';
|
|
2
|
-
import { Endpoint } from './routing/endpoint';
|
|
3
|
-
import { Middleware } from './routing/middleware';
|
|
4
|
-
import { EventVariables } from './routing/types';
|
|
5
|
-
|
|
6
|
-
}
|
|
1
|
+
import { type ILogger } from 'unnbound-logger-sdk';
|
|
2
|
+
import { type Endpoint } from './routing/endpoint';
|
|
3
|
+
import { type Middleware } from './routing/middleware';
|
|
4
|
+
import type { EventVariables } from './routing/types';
|
|
5
|
+
type HttpOptions = {};
|
|
7
6
|
interface QueueOptions {
|
|
8
7
|
maxMessages?: number;
|
|
9
8
|
visibilityTimeout?: number;
|
package/dist/lib/server.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createServer = void 0;
|
|
4
|
-
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
5
4
|
const hono_1 = require("hono");
|
|
5
|
+
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
6
6
|
const http_adapter_1 = require("./adapters/http-adapter");
|
|
7
7
|
const queue_adapter_1 = require("./adapters/queue-adapter");
|
|
8
|
+
const error_1 = require("./error");
|
|
8
9
|
const endpoint_1 = require("./routing/endpoint");
|
|
9
10
|
const middleware_1 = require("./routing/middleware");
|
|
10
11
|
const utils_1 = require("./utils");
|
|
11
|
-
const error_1 = require("./error");
|
|
12
12
|
class HttpQueueServer {
|
|
13
13
|
logger;
|
|
14
14
|
app = new hono_1.Hono();
|
|
@@ -33,6 +33,7 @@ class HttpQueueServer {
|
|
|
33
33
|
return (0, endpoint_1.respondWith)(c, error.toJson());
|
|
34
34
|
});
|
|
35
35
|
this.http = new http_adapter_1.HttpAdapter({ app: this.app, logger: this.logger, ...options.http });
|
|
36
|
+
// SQS adapter for async message processing
|
|
36
37
|
this.queue = new queue_adapter_1.QueueAdapter({
|
|
37
38
|
app: this.app,
|
|
38
39
|
logger: this.logger,
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { EventHandlerResult, EventMetadata, EventSource, IncomingEvent, IncomingRequest, MatchedIncomingRequest, StrictEventHandlerResult } from './event';
|
|
1
|
+
import type { HonoRequest } from 'hono';
|
|
2
|
+
import { type Maybe } from 'unnbound-logger-sdk/dist/types';
|
|
3
|
+
import type { EventHandlerResult, EventMetadata, EventSource, IncomingEvent, IncomingRequest, MatchedIncomingRequest, StrictEventHandlerResult } from './event';
|
|
4
4
|
export declare const normalizeHeaders: (headers: Record<string, string | string[]>) => Record<string, string>;
|
|
5
5
|
export declare const getIncomingEvent: (event: HonoRequest) => Promise<IncomingEvent<MatchedIncomingRequest>>;
|
|
6
6
|
export declare const getMetadataFromRequest: (request: IncomingRequest, source: EventSource) => EventMetadata;
|
package/dist/lib/utils.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.batchArray = exports.buildIncomingPayload = exports.serializeMetadata = exports.getMetadataFromRequest = exports.getIncomingEvent = exports.normalizeHeaders = void 0;
|
|
4
4
|
const unnbound_logger_sdk_1 = require("unnbound-logger-sdk");
|
|
5
|
-
const types_1 = require("unnbound-logger-sdk/dist/types");
|
|
6
5
|
const trace_1 = require("unnbound-logger-sdk/dist/trace");
|
|
6
|
+
const types_1 = require("unnbound-logger-sdk/dist/types");
|
|
7
7
|
const utils_1 = require("unnbound-logger-sdk/dist/utils");
|
|
8
8
|
const error_1 = require("./error");
|
|
9
9
|
const normalizeHeaders = (headers) => {
|
|
@@ -33,7 +33,7 @@ const parseParams = (request) => {
|
|
|
33
33
|
}
|
|
34
34
|
};
|
|
35
35
|
const getIncomingRequest = async (request) => {
|
|
36
|
-
const url = new URL(request.url,
|
|
36
|
+
const url = new URL(request.url, 'https://unnbound.ai');
|
|
37
37
|
const headers = (0, exports.normalizeHeaders)(request.header());
|
|
38
38
|
return {
|
|
39
39
|
url: url.toString(),
|
|
@@ -76,7 +76,7 @@ const serializeMetadata = (metadata) => ({
|
|
|
76
76
|
exports.serializeMetadata = serializeMetadata;
|
|
77
77
|
const deserializeMetadata = (request) => ({
|
|
78
78
|
source: request.headers[sourceKey],
|
|
79
|
-
timestamp: request.headers[timestampKey] ? parseInt(request.headers[timestampKey]) : undefined,
|
|
79
|
+
timestamp: request.headers[timestampKey] ? Number.parseInt(request.headers[timestampKey]) : undefined,
|
|
80
80
|
});
|
|
81
81
|
const buildResponsePayload = (result) => ({
|
|
82
82
|
status: result?.status ?? 204,
|
package/package.json
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unnbound-events",
|
|
3
3
|
"description": "Unified events SDK to handle HTTP routes and queued messages with a single routing API.",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.18",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "echo 'No tests'",
|
|
10
|
+
"typecheck": "tsc -noEmit",
|
|
11
|
+
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
|
|
12
|
+
"lint:fix": "bun run lint --fix",
|
|
13
|
+
"format": "biome format --write .",
|
|
14
|
+
"format:check": "biome format .",
|
|
15
|
+
"prepublishOnly": "bun run build",
|
|
16
|
+
"start:example": "bun --watch examples/node-server.ts",
|
|
17
|
+
"version:bump": "npm version patch"
|
|
18
|
+
},
|
|
7
19
|
"author": "Unnbound Team",
|
|
8
20
|
"license": "MIT",
|
|
9
21
|
"repository": {
|
|
@@ -19,12 +31,14 @@
|
|
|
19
31
|
"@aws-sdk/client-sqs": "^3.0.0",
|
|
20
32
|
"@hono/node-server": "^1.19.6",
|
|
21
33
|
"axios": "^1.12.2",
|
|
22
|
-
"hono": "^4.
|
|
23
|
-
"
|
|
34
|
+
"hono": "^4.11.4",
|
|
35
|
+
"ioredis": "^5.4.1",
|
|
36
|
+
"unnbound-logger-sdk": "^3.0.34"
|
|
24
37
|
},
|
|
25
38
|
"devDependencies": {
|
|
26
39
|
"@types/jest": "^29.5.12",
|
|
27
|
-
"@types/node": "^22"
|
|
40
|
+
"@types/node": "^22",
|
|
41
|
+
"typescript": "^5.8.3"
|
|
28
42
|
},
|
|
29
43
|
"files": [
|
|
30
44
|
"dist/**/*",
|
|
@@ -34,18 +48,5 @@
|
|
|
34
48
|
"engines": {
|
|
35
49
|
"node": ">=22"
|
|
36
50
|
},
|
|
37
|
-
"sideEffects": false
|
|
38
|
-
|
|
39
|
-
"build": "tsc",
|
|
40
|
-
"test": "jest",
|
|
41
|
-
"test:coverage": "jest --coverage",
|
|
42
|
-
"test:watch": "jest --watch",
|
|
43
|
-
"typecheck": "tsc -noEmit",
|
|
44
|
-
"lint": "eslint --cache --cache-location ./node_modules/.cache/eslint .",
|
|
45
|
-
"lint:fix": "pnpm lint --fix",
|
|
46
|
-
"format": "prettier --write .",
|
|
47
|
-
"format:check": "prettier --check .",
|
|
48
|
-
"start:example": "npx --yes tsx --watch examples/node-server.ts",
|
|
49
|
-
"version:bump": "npm version patch"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
51
|
+
"sideEffects": false
|
|
52
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025 Unnbound Team
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|