@objectstack/plugin-hono-server 4.0.2 → 4.0.4
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +15 -0
- package/README.md +71 -1
- package/dist/index.d.mts +44 -40
- package/dist/index.d.ts +44 -40
- package/dist/index.js +84 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +84 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +7 -7
- package/src/adapter.ts +13 -7
- package/src/hono-plugin.test.ts +123 -0
- package/src/hono-plugin.ts +171 -43
- package/src/pattern-matcher.test.ts +180 -0
- package/vitest.config.ts +22 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @objectstack/plugin-hono-server@4.0.
|
|
2
|
+
> @objectstack/plugin-hono-server@4.0.4 build /home/runner/work/framework/framework/packages/plugins/plugin-hono-server
|
|
3
3
|
> tsup --config ../../../tsup.config.ts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mESM[39m Build start
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m17.42 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m36.85 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 102ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m18.38 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m36.84 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 104ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.
|
|
22
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 19746ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m3.39 KB[39m
|
|
22
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.39 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @objectstack/plugin-hono-server
|
|
2
2
|
|
|
3
|
+
## 4.0.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [326b66b]
|
|
8
|
+
- @objectstack/spec@4.0.4
|
|
9
|
+
- @objectstack/core@4.0.4
|
|
10
|
+
|
|
11
|
+
## 4.0.3
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- @objectstack/spec@4.0.3
|
|
16
|
+
- @objectstack/core@4.0.3
|
|
17
|
+
|
|
3
18
|
## 4.0.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@ HTTP Server adapter for ObjectStack using Hono.
|
|
|
8
8
|
- **Fast**: Built on Hono, a high-performance web framework.
|
|
9
9
|
- **Full Protocol Support**: Automatically provides all ObjectStack Runtime endpoints (Auth, Data, Metadata, etc.).
|
|
10
10
|
- **Middleware**: Supports standard Hono middleware.
|
|
11
|
+
- **Wildcard CORS**: Supports wildcard patterns in CORS origins (compatible with better-auth).
|
|
11
12
|
|
|
12
13
|
## Usage
|
|
13
14
|
|
|
@@ -18,7 +19,7 @@ import { HonoServerPlugin } from '@objectstack/plugin-hono-server';
|
|
|
18
19
|
const kernel = new ObjectKernel();
|
|
19
20
|
|
|
20
21
|
// Register the server plugin
|
|
21
|
-
kernel.use(new HonoServerPlugin({
|
|
22
|
+
kernel.use(new HonoServerPlugin({
|
|
22
23
|
port: 3000,
|
|
23
24
|
restConfig: {
|
|
24
25
|
api: {
|
|
@@ -30,6 +31,75 @@ kernel.use(new HonoServerPlugin({
|
|
|
30
31
|
await kernel.start();
|
|
31
32
|
```
|
|
32
33
|
|
|
34
|
+
## CORS Configuration
|
|
35
|
+
|
|
36
|
+
The Hono server plugin supports flexible CORS configuration with wildcard pattern matching.
|
|
37
|
+
|
|
38
|
+
### Basic CORS
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
kernel.use(new HonoServerPlugin({
|
|
42
|
+
port: 3000,
|
|
43
|
+
cors: {
|
|
44
|
+
origins: ['https://app.example.com'],
|
|
45
|
+
credentials: true
|
|
46
|
+
}
|
|
47
|
+
}));
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Wildcard Patterns (better-auth compatible)
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
// Subdomain wildcards
|
|
54
|
+
kernel.use(new HonoServerPlugin({
|
|
55
|
+
cors: {
|
|
56
|
+
origins: ['https://*.objectui.org', 'https://*.objectstack.ai'],
|
|
57
|
+
credentials: true
|
|
58
|
+
}
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
// Port wildcards (useful for development)
|
|
62
|
+
kernel.use(new HonoServerPlugin({
|
|
63
|
+
cors: {
|
|
64
|
+
origins: 'http://localhost:*'
|
|
65
|
+
}
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
// Comma-separated patterns
|
|
69
|
+
kernel.use(new HonoServerPlugin({
|
|
70
|
+
cors: {
|
|
71
|
+
origins: 'https://*.objectui.org,https://*.objectstack.ai,http://localhost:*'
|
|
72
|
+
}
|
|
73
|
+
}));
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Environment Variables
|
|
77
|
+
|
|
78
|
+
CORS can also be configured via environment variables:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Single origin
|
|
82
|
+
CORS_ORIGIN=https://app.example.com
|
|
83
|
+
|
|
84
|
+
# Wildcard patterns (comma-separated)
|
|
85
|
+
CORS_ORIGIN=https://*.objectui.org,https://*.objectstack.ai
|
|
86
|
+
|
|
87
|
+
# Disable CORS
|
|
88
|
+
CORS_ENABLED=false
|
|
89
|
+
|
|
90
|
+
# Additional options
|
|
91
|
+
CORS_CREDENTIALS=true
|
|
92
|
+
CORS_MAX_AGE=86400
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Disable CORS
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
kernel.use(new HonoServerPlugin({
|
|
99
|
+
cors: false // Completely disable CORS
|
|
100
|
+
}));
|
|
101
|
+
```
|
|
102
|
+
|
|
33
103
|
## Architecture
|
|
34
104
|
|
|
35
105
|
This plugin wraps `@objectstack/hono` to provide a turnkey HTTP server solution for the Runtime. It binds the standard `HttpDispatcher` to a Hono application and starts listening on the configured port.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IHttpServer, RouteHandler, Middleware, Plugin, PluginContext } from '@objectstack/core';
|
|
2
2
|
export * from '@objectstack/core';
|
|
3
3
|
import { RestServerConfig } from '@objectstack/spec/api';
|
|
4
4
|
import * as hono_types from 'hono/types';
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
6
|
|
|
7
|
+
interface HonoCorsOptions {
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
origins?: string | string[];
|
|
10
|
+
methods?: string[];
|
|
11
|
+
credentials?: boolean;
|
|
12
|
+
maxAge?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Hono Implementation of IHttpServer
|
|
16
|
+
*/
|
|
17
|
+
declare class HonoHttpServer implements IHttpServer {
|
|
18
|
+
private port;
|
|
19
|
+
private staticRoot?;
|
|
20
|
+
private app;
|
|
21
|
+
private server;
|
|
22
|
+
private listeningPort;
|
|
23
|
+
constructor(port?: number, staticRoot?: string | undefined);
|
|
24
|
+
private wrap;
|
|
25
|
+
get(path: string, handler: RouteHandler): void;
|
|
26
|
+
post(path: string, handler: RouteHandler): void;
|
|
27
|
+
put(path: string, handler: RouteHandler): void;
|
|
28
|
+
delete(path: string, handler: RouteHandler): void;
|
|
29
|
+
patch(path: string, handler: RouteHandler): void;
|
|
30
|
+
use(pathOrHandler: string | Middleware, handler?: Middleware): void;
|
|
31
|
+
/**
|
|
32
|
+
* Mount a sub-application or router
|
|
33
|
+
*/
|
|
34
|
+
mount(path: string, subApp: Hono): void;
|
|
35
|
+
listen(port: number): Promise<void>;
|
|
36
|
+
private tryListen;
|
|
37
|
+
getPort(): number;
|
|
38
|
+
getRawApp(): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
|
|
7
42
|
interface StaticMount {
|
|
8
43
|
root: string;
|
|
9
44
|
path?: string;
|
|
@@ -38,17 +73,14 @@ interface HonoPluginOptions {
|
|
|
38
73
|
* @default false
|
|
39
74
|
*/
|
|
40
75
|
spaFallback?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* CORS configuration. Set to `false` to disable entirely.
|
|
78
|
+
* Enabled by default with origin '*'.
|
|
79
|
+
* Can also be controlled via environment variables:
|
|
80
|
+
* CORS_ENABLED, CORS_ORIGIN, CORS_CREDENTIALS, CORS_MAX_AGE
|
|
81
|
+
*/
|
|
82
|
+
cors?: HonoCorsOptions | false;
|
|
41
83
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Hono Server Plugin
|
|
44
|
-
*
|
|
45
|
-
* Provides HTTP server capabilities using Hono framework.
|
|
46
|
-
* Registers the IHttpServer service so other plugins can register routes.
|
|
47
|
-
*
|
|
48
|
-
* Route registration is handled by plugins:
|
|
49
|
-
* - `@objectstack/rest` → CRUD, metadata, discovery, UI, batch
|
|
50
|
-
* - `createDispatcherPlugin()` → auth, graphql, analytics, packages, etc.
|
|
51
|
-
*/
|
|
52
84
|
declare class HonoServerPlugin implements Plugin {
|
|
53
85
|
name: string;
|
|
54
86
|
type: string;
|
|
@@ -78,32 +110,4 @@ declare class HonoServerPlugin implements Plugin {
|
|
|
78
110
|
destroy(): Promise<void>;
|
|
79
111
|
}
|
|
80
112
|
|
|
81
|
-
|
|
82
|
-
* Hono Implementation of IHttpServer
|
|
83
|
-
*/
|
|
84
|
-
declare class HonoHttpServer implements IHttpServer {
|
|
85
|
-
private port;
|
|
86
|
-
private staticRoot?;
|
|
87
|
-
private app;
|
|
88
|
-
private server;
|
|
89
|
-
private listeningPort;
|
|
90
|
-
constructor(port?: number, staticRoot?: string | undefined);
|
|
91
|
-
private wrap;
|
|
92
|
-
get(path: string, handler: RouteHandler): void;
|
|
93
|
-
post(path: string, handler: RouteHandler): void;
|
|
94
|
-
put(path: string, handler: RouteHandler): void;
|
|
95
|
-
delete(path: string, handler: RouteHandler): void;
|
|
96
|
-
patch(path: string, handler: RouteHandler): void;
|
|
97
|
-
use(pathOrHandler: string | Middleware, handler?: Middleware): void;
|
|
98
|
-
/**
|
|
99
|
-
* Mount a sub-application or router
|
|
100
|
-
*/
|
|
101
|
-
mount(path: string, subApp: Hono): void;
|
|
102
|
-
listen(port: number): Promise<void>;
|
|
103
|
-
private tryListen;
|
|
104
|
-
getPort(): number;
|
|
105
|
-
getRawApp(): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
106
|
-
close(): Promise<void>;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export { HonoHttpServer, type HonoPluginOptions, HonoServerPlugin, type StaticMount };
|
|
113
|
+
export { type HonoCorsOptions, HonoHttpServer, type HonoPluginOptions, HonoServerPlugin, type StaticMount };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,44 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { IHttpServer, RouteHandler, Middleware, Plugin, PluginContext } from '@objectstack/core';
|
|
2
2
|
export * from '@objectstack/core';
|
|
3
3
|
import { RestServerConfig } from '@objectstack/spec/api';
|
|
4
4
|
import * as hono_types from 'hono/types';
|
|
5
5
|
import { Hono } from 'hono';
|
|
6
6
|
|
|
7
|
+
interface HonoCorsOptions {
|
|
8
|
+
enabled?: boolean;
|
|
9
|
+
origins?: string | string[];
|
|
10
|
+
methods?: string[];
|
|
11
|
+
credentials?: boolean;
|
|
12
|
+
maxAge?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Hono Implementation of IHttpServer
|
|
16
|
+
*/
|
|
17
|
+
declare class HonoHttpServer implements IHttpServer {
|
|
18
|
+
private port;
|
|
19
|
+
private staticRoot?;
|
|
20
|
+
private app;
|
|
21
|
+
private server;
|
|
22
|
+
private listeningPort;
|
|
23
|
+
constructor(port?: number, staticRoot?: string | undefined);
|
|
24
|
+
private wrap;
|
|
25
|
+
get(path: string, handler: RouteHandler): void;
|
|
26
|
+
post(path: string, handler: RouteHandler): void;
|
|
27
|
+
put(path: string, handler: RouteHandler): void;
|
|
28
|
+
delete(path: string, handler: RouteHandler): void;
|
|
29
|
+
patch(path: string, handler: RouteHandler): void;
|
|
30
|
+
use(pathOrHandler: string | Middleware, handler?: Middleware): void;
|
|
31
|
+
/**
|
|
32
|
+
* Mount a sub-application or router
|
|
33
|
+
*/
|
|
34
|
+
mount(path: string, subApp: Hono): void;
|
|
35
|
+
listen(port: number): Promise<void>;
|
|
36
|
+
private tryListen;
|
|
37
|
+
getPort(): number;
|
|
38
|
+
getRawApp(): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
39
|
+
close(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
|
|
7
42
|
interface StaticMount {
|
|
8
43
|
root: string;
|
|
9
44
|
path?: string;
|
|
@@ -38,17 +73,14 @@ interface HonoPluginOptions {
|
|
|
38
73
|
* @default false
|
|
39
74
|
*/
|
|
40
75
|
spaFallback?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* CORS configuration. Set to `false` to disable entirely.
|
|
78
|
+
* Enabled by default with origin '*'.
|
|
79
|
+
* Can also be controlled via environment variables:
|
|
80
|
+
* CORS_ENABLED, CORS_ORIGIN, CORS_CREDENTIALS, CORS_MAX_AGE
|
|
81
|
+
*/
|
|
82
|
+
cors?: HonoCorsOptions | false;
|
|
41
83
|
}
|
|
42
|
-
/**
|
|
43
|
-
* Hono Server Plugin
|
|
44
|
-
*
|
|
45
|
-
* Provides HTTP server capabilities using Hono framework.
|
|
46
|
-
* Registers the IHttpServer service so other plugins can register routes.
|
|
47
|
-
*
|
|
48
|
-
* Route registration is handled by plugins:
|
|
49
|
-
* - `@objectstack/rest` → CRUD, metadata, discovery, UI, batch
|
|
50
|
-
* - `createDispatcherPlugin()` → auth, graphql, analytics, packages, etc.
|
|
51
|
-
*/
|
|
52
84
|
declare class HonoServerPlugin implements Plugin {
|
|
53
85
|
name: string;
|
|
54
86
|
type: string;
|
|
@@ -78,32 +110,4 @@ declare class HonoServerPlugin implements Plugin {
|
|
|
78
110
|
destroy(): Promise<void>;
|
|
79
111
|
}
|
|
80
112
|
|
|
81
|
-
|
|
82
|
-
* Hono Implementation of IHttpServer
|
|
83
|
-
*/
|
|
84
|
-
declare class HonoHttpServer implements IHttpServer {
|
|
85
|
-
private port;
|
|
86
|
-
private staticRoot?;
|
|
87
|
-
private app;
|
|
88
|
-
private server;
|
|
89
|
-
private listeningPort;
|
|
90
|
-
constructor(port?: number, staticRoot?: string | undefined);
|
|
91
|
-
private wrap;
|
|
92
|
-
get(path: string, handler: RouteHandler): void;
|
|
93
|
-
post(path: string, handler: RouteHandler): void;
|
|
94
|
-
put(path: string, handler: RouteHandler): void;
|
|
95
|
-
delete(path: string, handler: RouteHandler): void;
|
|
96
|
-
patch(path: string, handler: RouteHandler): void;
|
|
97
|
-
use(pathOrHandler: string | Middleware, handler?: Middleware): void;
|
|
98
|
-
/**
|
|
99
|
-
* Mount a sub-application or router
|
|
100
|
-
*/
|
|
101
|
-
mount(path: string, subApp: Hono): void;
|
|
102
|
-
listen(port: number): Promise<void>;
|
|
103
|
-
private tryListen;
|
|
104
|
-
getPort(): number;
|
|
105
|
-
getRawApp(): Hono<hono_types.BlankEnv, hono_types.BlankSchema, "/">;
|
|
106
|
-
close(): Promise<void>;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export { HonoHttpServer, type HonoPluginOptions, HonoServerPlugin, type StaticMount };
|
|
113
|
+
export { type HonoCorsOptions, HonoHttpServer, type HonoPluginOptions, HonoServerPlugin, type StaticMount };
|
package/dist/index.js
CHANGED
|
@@ -49,8 +49,8 @@ var import_node_server = require("@hono/node-server");
|
|
|
49
49
|
var import_serve_static = require("@hono/node-server/serve-static");
|
|
50
50
|
var HonoHttpServer = class {
|
|
51
51
|
constructor(port = 3e3, staticRoot) {
|
|
52
|
-
this
|
|
53
|
-
this
|
|
52
|
+
__publicField(this, "port", port);
|
|
53
|
+
__publicField(this, "staticRoot", staticRoot);
|
|
54
54
|
__publicField(this, "app");
|
|
55
55
|
__publicField(this, "server");
|
|
56
56
|
__publicField(this, "listeningPort");
|
|
@@ -229,9 +229,33 @@ var HonoHttpServer = class {
|
|
|
229
229
|
};
|
|
230
230
|
|
|
231
231
|
// src/hono-plugin.ts
|
|
232
|
+
var import_cors = require("hono/cors");
|
|
232
233
|
var import_serve_static2 = require("@hono/node-server/serve-static");
|
|
233
234
|
var fs = __toESM(require("fs"));
|
|
234
235
|
var path = __toESM(require("path"));
|
|
236
|
+
function matchOriginPattern(origin, pattern) {
|
|
237
|
+
if (pattern === "*") return true;
|
|
238
|
+
if (pattern === origin) return true;
|
|
239
|
+
const regexPattern = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
240
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
241
|
+
return regex.test(origin);
|
|
242
|
+
}
|
|
243
|
+
function createOriginMatcher(patterns) {
|
|
244
|
+
let patternList;
|
|
245
|
+
if (typeof patterns === "string") {
|
|
246
|
+
patternList = patterns.includes(",") ? patterns.split(",").map((s) => s.trim()).filter(Boolean) : [patterns];
|
|
247
|
+
} else {
|
|
248
|
+
patternList = patterns;
|
|
249
|
+
}
|
|
250
|
+
return (requestOrigin) => {
|
|
251
|
+
for (const pattern of patternList) {
|
|
252
|
+
if (matchOriginPattern(requestOrigin, pattern)) {
|
|
253
|
+
return requestOrigin;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return null;
|
|
257
|
+
};
|
|
258
|
+
}
|
|
235
259
|
var HonoServerPlugin = class {
|
|
236
260
|
constructor(options = {}) {
|
|
237
261
|
__publicField(this, "name", "com.objectstack.server.hono");
|
|
@@ -250,6 +274,46 @@ var HonoServerPlugin = class {
|
|
|
250
274
|
ctx.registerService("http.server", this.server);
|
|
251
275
|
ctx.registerService("http-server", this.server);
|
|
252
276
|
ctx.logger.debug("HTTP server service registered", { serviceName: "http.server" });
|
|
277
|
+
const corsDisabledByEnv = process.env.CORS_ENABLED === "false";
|
|
278
|
+
if (this.options.cors !== false && !corsDisabledByEnv) {
|
|
279
|
+
const corsOpts = typeof this.options.cors === "object" ? this.options.cors : {};
|
|
280
|
+
const enabled = corsOpts.enabled ?? true;
|
|
281
|
+
if (enabled) {
|
|
282
|
+
let configuredOrigin;
|
|
283
|
+
if (corsOpts.origins) {
|
|
284
|
+
configuredOrigin = corsOpts.origins;
|
|
285
|
+
} else if (process.env.CORS_ORIGIN) {
|
|
286
|
+
const envOrigin = process.env.CORS_ORIGIN.trim();
|
|
287
|
+
configuredOrigin = envOrigin.includes(",") ? envOrigin.split(",").map((s) => s.trim()) : envOrigin;
|
|
288
|
+
} else {
|
|
289
|
+
configuredOrigin = "*";
|
|
290
|
+
}
|
|
291
|
+
const credentials = corsOpts.credentials ?? process.env.CORS_CREDENTIALS !== "false";
|
|
292
|
+
const maxAge = corsOpts.maxAge ?? (process.env.CORS_MAX_AGE ? parseInt(process.env.CORS_MAX_AGE, 10) : 86400);
|
|
293
|
+
let origin;
|
|
294
|
+
const hasWildcard = (patterns) => {
|
|
295
|
+
const list = Array.isArray(patterns) ? patterns : [patterns];
|
|
296
|
+
return list.some((p) => p.includes("*"));
|
|
297
|
+
};
|
|
298
|
+
if (configuredOrigin === "*" && credentials) {
|
|
299
|
+
origin = (requestOrigin) => requestOrigin || "*";
|
|
300
|
+
} else if (hasWildcard(configuredOrigin)) {
|
|
301
|
+
origin = createOriginMatcher(configuredOrigin);
|
|
302
|
+
} else {
|
|
303
|
+
origin = configuredOrigin;
|
|
304
|
+
}
|
|
305
|
+
const rawApp = this.server.getRawApp();
|
|
306
|
+
rawApp.use("*", (0, import_cors.cors)({
|
|
307
|
+
origin,
|
|
308
|
+
allowMethods: corsOpts.methods || ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"],
|
|
309
|
+
allowHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
|
310
|
+
exposeHeaders: [],
|
|
311
|
+
credentials,
|
|
312
|
+
maxAge
|
|
313
|
+
}));
|
|
314
|
+
ctx.logger.debug("CORS middleware enabled", { origin: configuredOrigin, credentials });
|
|
315
|
+
}
|
|
316
|
+
}
|
|
253
317
|
});
|
|
254
318
|
/**
|
|
255
319
|
* Start phase - Configure static files and start listening
|
|
@@ -399,30 +463,34 @@ var HonoServerPlugin = class {
|
|
|
399
463
|
rawApp.get("/.well-known/objectstack", (c) => c.redirect(`${prefix}/discovery`));
|
|
400
464
|
rawApp.get(`${prefix}/discovery`, (c) => c.json({ data: discovery }));
|
|
401
465
|
ctx.logger.info("Registered discovery endpoints", { prefix });
|
|
402
|
-
const
|
|
466
|
+
const getObjectQL = () => ctx.getService("objectql");
|
|
403
467
|
rawApp.post(`${prefix}/data/:object`, async (c) => {
|
|
404
|
-
const
|
|
405
|
-
if (!
|
|
468
|
+
const ql = getObjectQL();
|
|
469
|
+
if (!ql) return c.json({ error: "Data service not available" }, 503);
|
|
406
470
|
const object = c.req.param("object");
|
|
407
471
|
const data = await c.req.json().catch(() => ({}));
|
|
408
|
-
const
|
|
409
|
-
|
|
472
|
+
const res = await ql.insert(object, data);
|
|
473
|
+
const record = { ...data, ...res };
|
|
474
|
+
return c.json({ object, id: record.id, record });
|
|
410
475
|
});
|
|
411
476
|
rawApp.get(`${prefix}/data/:object/:id`, async (c) => {
|
|
412
|
-
const
|
|
413
|
-
if (!
|
|
477
|
+
const ql = getObjectQL();
|
|
478
|
+
if (!ql) return c.json({ error: "Data service not available" }, 503);
|
|
414
479
|
const object = c.req.param("object");
|
|
415
480
|
const id = c.req.param("id");
|
|
416
|
-
|
|
417
|
-
|
|
481
|
+
let all = await ql.find(object);
|
|
482
|
+
if (!all) all = [];
|
|
483
|
+
const match = all.find((i) => i.id === id);
|
|
484
|
+
return match ? c.json({ object, id, record: match }) : c.json({ error: "Not found" }, 404);
|
|
418
485
|
});
|
|
419
486
|
rawApp.get(`${prefix}/data/:object`, async (c) => {
|
|
420
|
-
const
|
|
421
|
-
if (!
|
|
487
|
+
const ql = getObjectQL();
|
|
488
|
+
if (!ql) return c.json({ error: "Data service not available" }, 503);
|
|
422
489
|
const object = c.req.param("object");
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
490
|
+
let all = await ql.find(object);
|
|
491
|
+
if (!Array.isArray(all) && all && all.value) all = all.value;
|
|
492
|
+
if (!all) all = [];
|
|
493
|
+
return c.json({ object, records: all, total: all.length });
|
|
426
494
|
});
|
|
427
495
|
ctx.logger.debug("Registered standard CRUD data endpoints", { prefix });
|
|
428
496
|
}
|