@grapity/grapity 0.3.0 → 0.4.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/README.md +47 -14
- package/dist/assets/index-JAhtTTW2.js +336 -0
- package/dist/assets/index-JAhtTTW2.js.map +1 -0
- package/dist/assets/index-LDlidn22.css +1 -0
- package/dist/cli/index.js +647 -69
- package/dist/core/index.d.ts +391 -23
- package/dist/hub/index.js +34 -7
- package/dist/hub/serve.d.ts +9 -1
- package/dist/hub/serve.js +34 -7
- package/dist/index.html +3 -2
- package/dist/registry/{index-DUPbMrAe.d.ts → index-Bx-7YlUF.d.ts} +15 -0
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.js +151 -3
- package/dist/registry/serve.d.ts +2 -1
- package/dist/registry/serve.js +202 -7
- package/package.json +13 -11
- package/dist/assets/index-Dq5tdnlb.js +0 -326
- package/dist/assets/index-Dq5tdnlb.js.map +0 -1
- package/dist/assets/index-NJpHAonA.css +0 -1
package/dist/hub/index.js
CHANGED
|
@@ -17,15 +17,34 @@ var DEFAULT_REGISTRY_URL = "http://localhost:3750";
|
|
|
17
17
|
async function startHubServer(userConfig) {
|
|
18
18
|
const config = {
|
|
19
19
|
port: userConfig?.port ?? DEFAULT_PORT,
|
|
20
|
-
registryUrl: userConfig?.registryUrl ?? DEFAULT_REGISTRY_URL
|
|
20
|
+
registryUrl: userConfig?.registryUrl ?? DEFAULT_REGISTRY_URL,
|
|
21
|
+
auth: userConfig?.auth
|
|
21
22
|
};
|
|
22
23
|
const app = new Hono();
|
|
24
|
+
app.get("/config.js", (c) => {
|
|
25
|
+
const clientConfig = {
|
|
26
|
+
registryUrl: config.registryUrl,
|
|
27
|
+
auth: config.auth ? {
|
|
28
|
+
mode: config.auth.mode,
|
|
29
|
+
serverUrl: config.auth.serverUrl,
|
|
30
|
+
realm: config.auth.realm,
|
|
31
|
+
clientId: config.auth.clientId,
|
|
32
|
+
audience: config.auth.audience
|
|
33
|
+
} : void 0
|
|
34
|
+
};
|
|
35
|
+
c.header("Content-Type", "application/javascript");
|
|
36
|
+
return c.body(
|
|
37
|
+
`window.__GRAPITY_CONFIG__ = ${JSON.stringify(clientConfig)};`
|
|
38
|
+
);
|
|
39
|
+
});
|
|
23
40
|
app.use("/v1/*", async (c) => {
|
|
24
41
|
const url = new URL(c.req.url);
|
|
25
42
|
const targetUrl = config.registryUrl + url.pathname + url.search;
|
|
43
|
+
const headers = new Headers(c.req.raw.headers);
|
|
44
|
+
headers.delete("host");
|
|
26
45
|
const response = await fetch(targetUrl, {
|
|
27
46
|
method: c.req.method,
|
|
28
|
-
headers
|
|
47
|
+
headers,
|
|
29
48
|
body: c.req.raw.body
|
|
30
49
|
});
|
|
31
50
|
return response;
|
|
@@ -33,13 +52,21 @@ async function startHubServer(userConfig) {
|
|
|
33
52
|
app.use("/*", serveStatic({ root: HUB_DIST_PATH }));
|
|
34
53
|
app.get("/*", async (c) => {
|
|
35
54
|
const indexPath = path.join(HUB_DIST_PATH, "index.html");
|
|
36
|
-
if (fs.existsSync(indexPath)) {
|
|
37
|
-
return c.
|
|
55
|
+
if (!fs.existsSync(indexPath)) {
|
|
56
|
+
return c.text(
|
|
57
|
+
"index.html not found. Build the project with 'bun run build' first.",
|
|
58
|
+
404
|
|
59
|
+
);
|
|
38
60
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
const html = fs.readFileSync(indexPath, "utf-8");
|
|
62
|
+
const configScript = `
|
|
63
|
+
<script src="/config.js"></script>
|
|
64
|
+
`;
|
|
65
|
+
const injected = html.replace(
|
|
66
|
+
"</head>",
|
|
67
|
+
`${configScript}</head>`
|
|
42
68
|
);
|
|
69
|
+
return c.html(injected);
|
|
43
70
|
});
|
|
44
71
|
serve({
|
|
45
72
|
fetch: app.fetch,
|
package/dist/hub/serve.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
interface HubAuthConfig {
|
|
2
|
+
mode: "keycloak";
|
|
3
|
+
serverUrl: string;
|
|
4
|
+
realm: string;
|
|
5
|
+
clientId: string;
|
|
6
|
+
audience?: string;
|
|
7
|
+
}
|
|
1
8
|
interface HubConfig {
|
|
2
9
|
port?: number;
|
|
3
10
|
registryUrl?: string;
|
|
11
|
+
auth?: HubAuthConfig;
|
|
4
12
|
}
|
|
5
13
|
declare function startHubServer(userConfig?: Partial<HubConfig>): Promise<void>;
|
|
6
14
|
|
|
7
|
-
export { type HubConfig, startHubServer };
|
|
15
|
+
export { type HubAuthConfig, type HubConfig, startHubServer };
|
package/dist/hub/serve.js
CHANGED
|
@@ -17,15 +17,34 @@ var DEFAULT_REGISTRY_URL = "http://localhost:3750";
|
|
|
17
17
|
async function startHubServer(userConfig) {
|
|
18
18
|
const config = {
|
|
19
19
|
port: userConfig?.port ?? DEFAULT_PORT,
|
|
20
|
-
registryUrl: userConfig?.registryUrl ?? DEFAULT_REGISTRY_URL
|
|
20
|
+
registryUrl: userConfig?.registryUrl ?? DEFAULT_REGISTRY_URL,
|
|
21
|
+
auth: userConfig?.auth
|
|
21
22
|
};
|
|
22
23
|
const app = new Hono();
|
|
24
|
+
app.get("/config.js", (c) => {
|
|
25
|
+
const clientConfig = {
|
|
26
|
+
registryUrl: config.registryUrl,
|
|
27
|
+
auth: config.auth ? {
|
|
28
|
+
mode: config.auth.mode,
|
|
29
|
+
serverUrl: config.auth.serverUrl,
|
|
30
|
+
realm: config.auth.realm,
|
|
31
|
+
clientId: config.auth.clientId,
|
|
32
|
+
audience: config.auth.audience
|
|
33
|
+
} : void 0
|
|
34
|
+
};
|
|
35
|
+
c.header("Content-Type", "application/javascript");
|
|
36
|
+
return c.body(
|
|
37
|
+
`window.__GRAPITY_CONFIG__ = ${JSON.stringify(clientConfig)};`
|
|
38
|
+
);
|
|
39
|
+
});
|
|
23
40
|
app.use("/v1/*", async (c) => {
|
|
24
41
|
const url = new URL(c.req.url);
|
|
25
42
|
const targetUrl = config.registryUrl + url.pathname + url.search;
|
|
43
|
+
const headers = new Headers(c.req.raw.headers);
|
|
44
|
+
headers.delete("host");
|
|
26
45
|
const response = await fetch(targetUrl, {
|
|
27
46
|
method: c.req.method,
|
|
28
|
-
headers
|
|
47
|
+
headers,
|
|
29
48
|
body: c.req.raw.body
|
|
30
49
|
});
|
|
31
50
|
return response;
|
|
@@ -33,13 +52,21 @@ async function startHubServer(userConfig) {
|
|
|
33
52
|
app.use("/*", serveStatic({ root: HUB_DIST_PATH }));
|
|
34
53
|
app.get("/*", async (c) => {
|
|
35
54
|
const indexPath = path.join(HUB_DIST_PATH, "index.html");
|
|
36
|
-
if (fs.existsSync(indexPath)) {
|
|
37
|
-
return c.
|
|
55
|
+
if (!fs.existsSync(indexPath)) {
|
|
56
|
+
return c.text(
|
|
57
|
+
"index.html not found. Build the project with 'bun run build' first.",
|
|
58
|
+
404
|
|
59
|
+
);
|
|
38
60
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
const html = fs.readFileSync(indexPath, "utf-8");
|
|
62
|
+
const configScript = `
|
|
63
|
+
<script src="/config.js"></script>
|
|
64
|
+
`;
|
|
65
|
+
const injected = html.replace(
|
|
66
|
+
"</head>",
|
|
67
|
+
`${configScript}</head>`
|
|
42
68
|
);
|
|
69
|
+
return c.html(injected);
|
|
43
70
|
});
|
|
44
71
|
serve({
|
|
45
72
|
fetch: app.fetch,
|
package/dist/index.html
CHANGED
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
10
10
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
11
11
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
|
|
12
|
-
<script
|
|
13
|
-
<
|
|
12
|
+
<script src="/config.js"></script>
|
|
13
|
+
<script type="module" crossorigin src="/assets/index-JAhtTTW2.js"></script>
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-LDlidn22.css">
|
|
14
15
|
</head>
|
|
15
16
|
<body>
|
|
16
17
|
<div id="root"></div>
|
|
@@ -191,18 +191,33 @@ interface GatewayConfigStore {
|
|
|
191
191
|
deleteGatewayLogsOlderThan(days: number): Promise<void>;
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
+
type RoleSource = "scope" | "realm_access.roles";
|
|
195
|
+
interface KeycloakAuthConfig {
|
|
196
|
+
mode: "keycloak";
|
|
197
|
+
serverUrl: string;
|
|
198
|
+
realm: string;
|
|
199
|
+
audience?: string;
|
|
200
|
+
roleSource?: RoleSource;
|
|
201
|
+
}
|
|
202
|
+
type AuthConfig = {
|
|
203
|
+
mode: "none";
|
|
204
|
+
} | KeycloakAuthConfig;
|
|
205
|
+
|
|
194
206
|
type DatabaseBackend = "sqlite" | "postgresql";
|
|
195
207
|
interface ServerConfig {
|
|
196
208
|
port: number;
|
|
197
209
|
database: DatabaseBackend;
|
|
198
210
|
sqlitePath?: string;
|
|
199
211
|
postgresUrl?: string;
|
|
212
|
+
auth: AuthConfig;
|
|
200
213
|
}
|
|
201
214
|
|
|
202
215
|
type AppEnv = {
|
|
203
216
|
Variables: {
|
|
204
217
|
store: SpecStore & GatewayConfigStore;
|
|
205
218
|
config: ServerConfig;
|
|
219
|
+
actor?: string;
|
|
220
|
+
claims?: Record<string, unknown>;
|
|
206
221
|
};
|
|
207
222
|
};
|
|
208
223
|
declare function createApp(config: ServerConfig, store: SpecStore & GatewayConfigStore): Hono<AppEnv, hono_types.BlankSchema, "/">;
|
package/dist/registry/index.d.ts
CHANGED
package/dist/registry/index.js
CHANGED
|
@@ -1751,6 +1751,7 @@ var pushRoute = new Hono().post("/", async (c) => {
|
|
|
1751
1751
|
}
|
|
1752
1752
|
const store = c.get("store");
|
|
1753
1753
|
const service = new RegistryService(store);
|
|
1754
|
+
const actor = c.get("actor") ?? body.pushedBy;
|
|
1754
1755
|
try {
|
|
1755
1756
|
const result = await service.pushSpec(body.content, body.name, {
|
|
1756
1757
|
type: body.type,
|
|
@@ -1759,7 +1760,7 @@ var pushRoute = new Hono().post("/", async (c) => {
|
|
|
1759
1760
|
sourceRepo: body.sourceRepo,
|
|
1760
1761
|
tags: Array.isArray(body.tags) ? body.tags : void 0,
|
|
1761
1762
|
gitRef: body.gitRef,
|
|
1762
|
-
pushedBy:
|
|
1763
|
+
pushedBy: actor,
|
|
1763
1764
|
prerelease: body.prerelease,
|
|
1764
1765
|
force: body.force,
|
|
1765
1766
|
reason: body.reason
|
|
@@ -1924,7 +1925,8 @@ var deleteSpecRoute = new Hono5().delete(
|
|
|
1924
1925
|
const name = c.req.param("name");
|
|
1925
1926
|
const store = c.get("store");
|
|
1926
1927
|
const service = new RegistryService(store);
|
|
1927
|
-
const
|
|
1928
|
+
const actor = c.get("actor");
|
|
1929
|
+
const deleted = await service.deleteSpec(name, actor);
|
|
1928
1930
|
if (!deleted) {
|
|
1929
1931
|
return c.json({ error: "not_found", message: `Spec "${name}" not found`, statusCode: 404 }, 404);
|
|
1930
1932
|
}
|
|
@@ -2665,6 +2667,7 @@ var pushGatewayConfigRoute = new Hono13().post("/", async (c) => {
|
|
|
2665
2667
|
}
|
|
2666
2668
|
const store = c.get("store");
|
|
2667
2669
|
const service = new GatewayService(store, store);
|
|
2670
|
+
const actor = c.get("actor") ?? body.pushedBy;
|
|
2668
2671
|
try {
|
|
2669
2672
|
const result = await service.pushGatewayConfig({
|
|
2670
2673
|
name: body.name,
|
|
@@ -2675,7 +2678,7 @@ var pushGatewayConfigRoute = new Hono13().post("/", async (c) => {
|
|
|
2675
2678
|
environments: body.environments ?? {},
|
|
2676
2679
|
callerIdentification: body.callerIdentification,
|
|
2677
2680
|
content: body.content,
|
|
2678
|
-
pushedBy:
|
|
2681
|
+
pushedBy: actor
|
|
2679
2682
|
});
|
|
2680
2683
|
return c.json({ data: result }, 201);
|
|
2681
2684
|
} catch (err) {
|
|
@@ -2940,7 +2943,137 @@ var gatewayLogStatsRoute = new Hono21().get("/stats", async (c) => {
|
|
|
2940
2943
|
});
|
|
2941
2944
|
});
|
|
2942
2945
|
|
|
2946
|
+
// src/registry/auth/middleware.ts
|
|
2947
|
+
import { createRemoteJWKSet, jwtVerify } from "jose";
|
|
2948
|
+
var AuthError = class extends Error {
|
|
2949
|
+
constructor(statusCode, code, message) {
|
|
2950
|
+
super(message);
|
|
2951
|
+
this.statusCode = statusCode;
|
|
2952
|
+
this.code = code;
|
|
2953
|
+
this.name = "AuthError";
|
|
2954
|
+
}
|
|
2955
|
+
statusCode;
|
|
2956
|
+
code;
|
|
2957
|
+
};
|
|
2958
|
+
function buildKeycloakUrls(config) {
|
|
2959
|
+
const base = `${config.serverUrl}/realms/${config.realm}`;
|
|
2960
|
+
return {
|
|
2961
|
+
issuer: base,
|
|
2962
|
+
jwksUri: `${base}/protocol/openid-connect/certs`,
|
|
2963
|
+
tokenUrl: `${base}/protocol/openid-connect/token`
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
|
+
function createAuthMiddleware(config, routeScopes) {
|
|
2967
|
+
if (config.auth?.mode !== "keycloak") {
|
|
2968
|
+
return async (_c, next) => await next();
|
|
2969
|
+
}
|
|
2970
|
+
const authConfig = config.auth;
|
|
2971
|
+
const { issuer, jwksUri } = buildKeycloakUrls(authConfig);
|
|
2972
|
+
const jwks = createRemoteJWKSet(new URL(jwksUri));
|
|
2973
|
+
const scopeByRoute = /* @__PURE__ */ new Map();
|
|
2974
|
+
for (const route of routeScopes) {
|
|
2975
|
+
const key = `${route.method.toUpperCase()}:${route.path}`;
|
|
2976
|
+
scopeByRoute.set(key, {
|
|
2977
|
+
operationId: route.operationId,
|
|
2978
|
+
scopes: route.scopes
|
|
2979
|
+
});
|
|
2980
|
+
}
|
|
2981
|
+
return async (c, next) => {
|
|
2982
|
+
const matchedPath = c.req.matchedRoutes.map((r) => r.path).filter((p) => p !== "/*").pop();
|
|
2983
|
+
const routeKey = matchedPath ? `${c.req.method}:${matchedPath}` : `${c.req.method}:${c.req.routePath}`;
|
|
2984
|
+
const required = scopeByRoute.get(routeKey);
|
|
2985
|
+
if (!required || required.scopes.length === 0) {
|
|
2986
|
+
return await next();
|
|
2987
|
+
}
|
|
2988
|
+
const authHeader = c.req.header("Authorization");
|
|
2989
|
+
if (!authHeader || !authHeader.startsWith("Bearer ")) {
|
|
2990
|
+
throw new AuthError(401, "unauthorized", "Bearer token required");
|
|
2991
|
+
}
|
|
2992
|
+
const token = authHeader.slice("Bearer ".length).trim();
|
|
2993
|
+
if (!token) {
|
|
2994
|
+
throw new AuthError(401, "unauthorized", "Bearer token required");
|
|
2995
|
+
}
|
|
2996
|
+
let payload;
|
|
2997
|
+
try {
|
|
2998
|
+
const result = await jwtVerify(token, jwks, {
|
|
2999
|
+
issuer,
|
|
3000
|
+
audience: authConfig.audience
|
|
3001
|
+
});
|
|
3002
|
+
payload = result.payload;
|
|
3003
|
+
} catch (err) {
|
|
3004
|
+
const message = err instanceof Error ? err.message : "Invalid token";
|
|
3005
|
+
throw new AuthError(401, "unauthorized", `Invalid or expired token: ${message}`);
|
|
3006
|
+
}
|
|
3007
|
+
const subject = payload.sub;
|
|
3008
|
+
if (!subject) {
|
|
3009
|
+
throw new AuthError(401, "unauthorized", "Token missing subject claim");
|
|
3010
|
+
}
|
|
3011
|
+
const grantedScopes = extractScopes(payload, authConfig.roleSource ?? "scope");
|
|
3012
|
+
const missing = required.scopes.filter((s) => !grantedScopes.has(s));
|
|
3013
|
+
if (missing.length > 0) {
|
|
3014
|
+
throw new AuthError(
|
|
3015
|
+
403,
|
|
3016
|
+
"forbidden",
|
|
3017
|
+
`Missing required scope${missing.length > 1 ? "s" : ""}: ${missing.join(", ")}`
|
|
3018
|
+
);
|
|
3019
|
+
}
|
|
3020
|
+
c.set("actor", subject);
|
|
3021
|
+
c.set("claims", payload);
|
|
3022
|
+
await next();
|
|
3023
|
+
};
|
|
3024
|
+
}
|
|
3025
|
+
function extractScopes(payload, source) {
|
|
3026
|
+
if (source === "realm_access.roles") {
|
|
3027
|
+
const roles = payload.realm_access?.roles;
|
|
3028
|
+
return new Set(roles ?? []);
|
|
3029
|
+
}
|
|
3030
|
+
const scopeValue = payload.scope;
|
|
3031
|
+
if (typeof scopeValue === "string") {
|
|
3032
|
+
return new Set(scopeValue.split(/\s+/).filter(Boolean));
|
|
3033
|
+
}
|
|
3034
|
+
return /* @__PURE__ */ new Set();
|
|
3035
|
+
}
|
|
3036
|
+
function parseRouteScopes(spec) {
|
|
3037
|
+
const routes = [];
|
|
3038
|
+
const paths = spec.paths;
|
|
3039
|
+
if (!paths) return routes;
|
|
3040
|
+
for (const [path, operations] of Object.entries(paths)) {
|
|
3041
|
+
for (const [method, operation] of Object.entries(operations)) {
|
|
3042
|
+
if (typeof operation !== "object" || operation === null) continue;
|
|
3043
|
+
const op = operation;
|
|
3044
|
+
const operationId = op.operationId;
|
|
3045
|
+
if (!operationId) continue;
|
|
3046
|
+
const security = op.security;
|
|
3047
|
+
const scopes = [];
|
|
3048
|
+
if (security) {
|
|
3049
|
+
for (const sec of security) {
|
|
3050
|
+
for (const [name, required] of Object.entries(sec)) {
|
|
3051
|
+
if (name === "keycloak" && Array.isArray(required)) {
|
|
3052
|
+
scopes.push(...required);
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
routes.push({
|
|
3058
|
+
method: method.toUpperCase(),
|
|
3059
|
+
path: path.replace(/\{([^}]+)\}/g, ":$1"),
|
|
3060
|
+
operationId,
|
|
3061
|
+
scopes
|
|
3062
|
+
});
|
|
3063
|
+
}
|
|
3064
|
+
}
|
|
3065
|
+
return routes;
|
|
3066
|
+
}
|
|
3067
|
+
|
|
2943
3068
|
// src/registry/server.ts
|
|
3069
|
+
import { readFileSync } from "fs";
|
|
3070
|
+
import { fileURLToPath } from "url";
|
|
3071
|
+
import yaml6 from "js-yaml";
|
|
3072
|
+
function loadOpenApiSpec() {
|
|
3073
|
+
const path = fileURLToPath(new URL("../../openapi.yaml", import.meta.url));
|
|
3074
|
+
const content = readFileSync(path, "utf-8");
|
|
3075
|
+
return yaml6.load(content);
|
|
3076
|
+
}
|
|
2944
3077
|
function createApp(config, store) {
|
|
2945
3078
|
const app = new Hono22();
|
|
2946
3079
|
app.use("*", logger());
|
|
@@ -2951,6 +3084,21 @@ function createApp(config, store) {
|
|
|
2951
3084
|
c.set("config", config);
|
|
2952
3085
|
await next();
|
|
2953
3086
|
});
|
|
3087
|
+
const routeScopes = parseRouteScopes(loadOpenApiSpec());
|
|
3088
|
+
app.use("*", createAuthMiddleware(config, routeScopes));
|
|
3089
|
+
app.onError((err, c) => {
|
|
3090
|
+
if (err instanceof AuthError) {
|
|
3091
|
+
return c.json(
|
|
3092
|
+
{ error: err.code, message: err.message, statusCode: err.statusCode },
|
|
3093
|
+
err.statusCode
|
|
3094
|
+
);
|
|
3095
|
+
}
|
|
3096
|
+
console.error("Unhandled error:", err);
|
|
3097
|
+
return c.json(
|
|
3098
|
+
{ error: "internal_error", message: "Internal server error", statusCode: 500 },
|
|
3099
|
+
500
|
|
3100
|
+
);
|
|
3101
|
+
});
|
|
2954
3102
|
app.route("/v1/specs", pushRoute);
|
|
2955
3103
|
app.route("/v1/specs", validateRoute);
|
|
2956
3104
|
app.route("/v1/specs", listRoute);
|
package/dist/registry/serve.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ServerType } from '@hono/node-server';
|
|
2
|
-
import { S as SpecStore, G as GatewayConfigStore, a as Spec, b as SpecVersion, c as SpecFilters, C as CompatReport, A as AuditAction, d as GatewayConfig, e as GatewayConfigVersion, P as Provision, f as GatewayLog, g as GatewayLogFilters, h as GatewayLogStats, i as createApp, j as ServerConfig } from './index-
|
|
2
|
+
import { S as SpecStore, G as GatewayConfigStore, a as Spec, b as SpecVersion, c as SpecFilters, C as CompatReport, A as AuditAction, d as GatewayConfig, e as GatewayConfigVersion, P as Provision, f as GatewayLog, g as GatewayLogFilters, h as GatewayLogStats, i as createApp, j as ServerConfig } from './index-Bx-7YlUF.js';
|
|
3
3
|
import 'hono/types';
|
|
4
4
|
import 'hono';
|
|
5
5
|
|
|
@@ -47,6 +47,7 @@ declare class SQLiteSpecStore implements SpecStore, GatewayConfigStore {
|
|
|
47
47
|
declare class PostgreSQLSpecStore implements SpecStore, GatewayConfigStore {
|
|
48
48
|
private db;
|
|
49
49
|
private pool;
|
|
50
|
+
private postgresUrl;
|
|
50
51
|
constructor(postgresUrl: string);
|
|
51
52
|
migrate(): Promise<void>;
|
|
52
53
|
end(): Promise<void>;
|