@verdict-ai/api 0.0.0-stage → 0.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/LICENSE +9 -0
- package/README.md +21 -2
- package/dist/app.d.ts +94 -0
- package/dist/app.js +120 -0
- package/dist/app.js.map +1 -0
- package/dist/github.d.ts +15 -0
- package/dist/github.js +40 -0
- package/dist/github.js.map +1 -0
- package/dist/hub-pages.d.ts +24 -0
- package/dist/hub-pages.js +119 -0
- package/dist/hub-pages.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/openapi.d.ts +463 -0
- package/dist/openapi.js +58 -0
- package/dist/openapi.js.map +1 -0
- package/dist/present.d.ts +110 -0
- package/dist/present.js +10 -0
- package/dist/present.js.map +1 -0
- package/dist/queue-cloudflare.d.ts +17 -0
- package/dist/queue-cloudflare.js +11 -0
- package/dist/queue-cloudflare.js.map +1 -0
- package/dist/rate-limit.d.ts +44 -0
- package/dist/rate-limit.js +40 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/routes/admin.d.ts +4 -0
- package/dist/routes/admin.js +81 -0
- package/dist/routes/admin.js.map +1 -0
- package/dist/routes/batches.d.ts +4 -0
- package/dist/routes/batches.js +27 -0
- package/dist/routes/batches.js.map +1 -0
- package/dist/routes/evaluations.d.ts +4 -0
- package/dist/routes/evaluations.js +104 -0
- package/dist/routes/evaluations.js.map +1 -0
- package/dist/routes/hub.d.ts +12 -0
- package/dist/routes/hub.js +66 -0
- package/dist/routes/hub.js.map +1 -0
- package/dist/routes/project-versions.d.ts +4 -0
- package/dist/routes/project-versions.js +56 -0
- package/dist/routes/project-versions.js.map +1 -0
- package/dist/routes/projects.d.ts +4 -0
- package/dist/routes/projects.js +91 -0
- package/dist/routes/projects.js.map +1 -0
- package/dist/routes/promotions.d.ts +4 -0
- package/dist/routes/promotions.js +72 -0
- package/dist/routes/promotions.js.map +1 -0
- package/dist/routes/public-hub.d.ts +41 -0
- package/dist/routes/public-hub.js +119 -0
- package/dist/routes/public-hub.js.map +1 -0
- package/dist/routes/publications.d.ts +4 -0
- package/dist/routes/publications.js +79 -0
- package/dist/routes/publications.js.map +1 -0
- package/dist/routes/reports.d.ts +4 -0
- package/dist/routes/reports.js +84 -0
- package/dist/routes/reports.js.map +1 -0
- package/dist/routes/rubrics.d.ts +4 -0
- package/dist/routes/rubrics.js +50 -0
- package/dist/routes/rubrics.js.map +1 -0
- package/dist/routes/shared.d.ts +42 -0
- package/dist/routes/shared.js +94 -0
- package/dist/routes/shared.js.map +1 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.js +69 -0
- package/dist/server.js.map +1 -0
- package/dist/worker.d.ts +58 -0
- package/dist/worker.js +81 -0
- package/dist/worker.js.map +1 -0
- package/package.json +69 -3
- package/wrangler.example.toml +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Verdict contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @verdict-ai/api
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Hono REST API for Node and Cloudflare Workers.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @verdict-ai/api @verdict-ai/core
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { Engine, MemoryStore } from "@verdict-ai/core";
|
|
11
|
+
import { createApp } from "@verdict-ai/api";
|
|
12
|
+
const engine = new Engine({ store: new MemoryStore() });
|
|
13
|
+
const app = createApp({ engine });
|
|
14
|
+
const response = await app.request("/v1/health");
|
|
15
|
+
console.log(response.status);
|
|
16
|
+
console.log(await response.json());
|
|
17
|
+
// Export app.fetch for a compatible HTTP runtime.
|
|
18
|
+
// Configure authentication before exposing a public service.
|
|
19
|
+
export default app;
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Requires Node 20 or newer. [Documentation](https://verdict-docs.developerolim.workers.dev/reference/rest). MIT licensed.
|
package/dist/app.d.ts
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assembles authenticated REST routes around an injected engine.
|
|
3
|
+
* Request bodies are validated at the boundary; Workers imports must remain free of eager Node I/O.
|
|
4
|
+
*/
|
|
5
|
+
import { Engine, type Actor, type Authorize } from "@verdict-ai/core";
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import { type ClientKey, type HubLimits } from "./rate-limit.js";
|
|
8
|
+
import type { GithubConfig } from "./github.js";
|
|
9
|
+
/** A request's account and who made it. `claims` reach `authorize` as they are (a role, what a key may reach). */
|
|
10
|
+
export interface Identity {
|
|
11
|
+
tenantId: string;
|
|
12
|
+
actor: Actor;
|
|
13
|
+
claims?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export interface Auth {
|
|
16
|
+
/**
|
|
17
|
+
* Map an API key to a tenant id — or to a tenant and who is asking — or undefined to reject. Return "" for
|
|
18
|
+
* single-tenant open mode. A bare tenant id means an unnamed key made the request.
|
|
19
|
+
*
|
|
20
|
+
* `request` is the request being authenticated, for servers where the key alone does not settle the tenant: a
|
|
21
|
+
* person who belongs to several organisations names one (`x-verdict-org`), and a browser sends a session cookie
|
|
22
|
+
* and no key. Servers that map a key to one tenant ignore it.
|
|
23
|
+
*/
|
|
24
|
+
resolve(apiKey: string | undefined, request?: Request): Promise<string | Identity | undefined> | string | Identity | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** How this server signs people in from the CLI, when it runs the approval itself. */
|
|
27
|
+
export interface BrowserSignIn {
|
|
28
|
+
kind: "browser";
|
|
29
|
+
/** POST → `{ deviceCode, userCode, verificationUri, expiresIn, interval }`. Path on this server. */
|
|
30
|
+
start: string;
|
|
31
|
+
/** POST `{ deviceCode }` → `{ apiKey, keyId?, handle? }`, or an error of type `authorization_pending`, `slow_down`, `expired_token` or `access_denied`. */
|
|
32
|
+
token: string;
|
|
33
|
+
}
|
|
34
|
+
/** Route groups an app can serve (docs/design/control-plane.md §9.2). Admin and discovery routes are always there. */
|
|
35
|
+
export declare const ROUTE_GROUPS: readonly ["evaluations", "rubrics", "hub", "control"];
|
|
36
|
+
export type RouteGroup = (typeof ROUTE_GROUPS)[number];
|
|
37
|
+
/** Reads `VERDICT_ROUTES="hub,control"`; unset serves every group. Throws on a name that is not a group, at startup. */
|
|
38
|
+
export declare function routeGroups(value: string | undefined): readonly RouteGroup[];
|
|
39
|
+
/** `VERDICT_API_KEYS="key1:tenantA,key2:tenantB"`; a bare key maps to tenant "default". Unset = open (single tenant). */
|
|
40
|
+
export declare function envAuth(env?: Record<string, string | undefined>): Auth;
|
|
41
|
+
/** Optional API-key management (backed by @verdict-ai/db's DrizzleAuth). Exposed under /v1/admin with VERDICT_ADMIN_KEY. */
|
|
42
|
+
export interface KeyManager {
|
|
43
|
+
createKey(tenantId: string, name: string): Promise<{
|
|
44
|
+
id: string;
|
|
45
|
+
key: string;
|
|
46
|
+
prefix: string;
|
|
47
|
+
}>;
|
|
48
|
+
revokeKey(id: string, tenantId?: string): Promise<boolean>;
|
|
49
|
+
listKeys(tenantId: string): Promise<Array<{
|
|
50
|
+
id: string;
|
|
51
|
+
name: string;
|
|
52
|
+
prefix: string;
|
|
53
|
+
createdAt: string;
|
|
54
|
+
lastUsedAt: string | null;
|
|
55
|
+
revokedAt: string | null;
|
|
56
|
+
}>>;
|
|
57
|
+
}
|
|
58
|
+
export interface AppOptions {
|
|
59
|
+
engine: Engine;
|
|
60
|
+
auth?: Auth;
|
|
61
|
+
keys?: KeyManager;
|
|
62
|
+
/** Bearer token for /v1/admin/* (default: env VERDICT_ADMIN_KEY). Unset = admin routes disabled. */
|
|
63
|
+
adminKey?: string;
|
|
64
|
+
/** Return 202 immediately and finish in the background when the client asks (`"async": true`). */
|
|
65
|
+
background?: (promise: Promise<unknown>) => void;
|
|
66
|
+
allowAsync?: boolean;
|
|
67
|
+
log?: boolean;
|
|
68
|
+
/** Public handle a tenant publishes under on the hub; undefined refuses publishing. Default: the tenant id. */
|
|
69
|
+
publisherOf?: (tenantId: string | undefined) => Promise<string | undefined> | string | undefined;
|
|
70
|
+
/** Clock for stored timestamps (tests). */
|
|
71
|
+
now?: () => number;
|
|
72
|
+
/** GitHub OAuth App for hub sign-in (GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET). Unset: tenants publish under their id. */
|
|
73
|
+
github?: GithubConfig;
|
|
74
|
+
/** Limits on sign-in, publishing and public reads. Default: in-memory counters (`DEFAULT_HUB_RULES`); `{}` turns them off. */
|
|
75
|
+
limits?: HubLimits;
|
|
76
|
+
/** Who a request comes from, for per-client limits. Default: Cloudflare's `cf-connecting-ip`, else one shared bucket. */
|
|
77
|
+
clientKey?: ClientKey;
|
|
78
|
+
/** Which route groups to serve; a group left out answers 404. Default: all of `ROUTE_GROUPS`. */
|
|
79
|
+
routes?: readonly RouteGroup[];
|
|
80
|
+
/** Allows or refuses each control-plane request (`/v1/projects…`). Default: a valid key may do everything. */
|
|
81
|
+
authorize?: Authorize;
|
|
82
|
+
/** Announced in `/v1/hub/config` so `verdict login` follows it. The routes it names are the embedding server's own. */
|
|
83
|
+
signIn?: BrowserSignIn;
|
|
84
|
+
}
|
|
85
|
+
export type Env = {
|
|
86
|
+
Variables: {
|
|
87
|
+
tenantId: string;
|
|
88
|
+
actor: Actor;
|
|
89
|
+
claims?: Record<string, unknown>;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
/** Builds the REST app around an engine; route failures are translated into HTTP error responses. */
|
|
93
|
+
export declare function createApp(options: AppOptions): Hono<Env, import("hono/types").BlankSchema, "/">;
|
|
94
|
+
export { present } from "./present.js";
|
package/dist/app.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assembles authenticated REST routes around an injected engine.
|
|
3
|
+
* Request bodies are validated at the boundary; Workers imports must remain free of eager Node I/O.
|
|
4
|
+
*/
|
|
5
|
+
import { ConflictError, NotFoundError, ValidationError } from "@verdict-ai/core";
|
|
6
|
+
import { Hono } from "hono";
|
|
7
|
+
import { cors } from "hono/cors";
|
|
8
|
+
import { HTTPException } from "hono/http-exception";
|
|
9
|
+
import { logger } from "hono/logger";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
import { openapiFor } from "./openapi.js";
|
|
12
|
+
import { registerAdmin } from "./routes/admin.js";
|
|
13
|
+
import { registerBatches } from "./routes/batches.js";
|
|
14
|
+
import { registerEvaluations } from "./routes/evaluations.js";
|
|
15
|
+
import { registerPublications } from "./routes/publications.js";
|
|
16
|
+
import { publisherFor, PUBLIC_HUB_PATHS, registerHub } from "./routes/hub.js";
|
|
17
|
+
import { isPublicHubPath, registerPublicHub } from "./routes/public-hub.js";
|
|
18
|
+
import { defaultClientKey, defaultHubLimits, RateLimitedError } from "./rate-limit.js";
|
|
19
|
+
import { registerRubrics } from "./routes/rubrics.js";
|
|
20
|
+
import { registerProjects } from "./routes/projects.js";
|
|
21
|
+
import { registerProjectVersions } from "./routes/project-versions.js";
|
|
22
|
+
import { registerPromotions } from "./routes/promotions.js";
|
|
23
|
+
import { registerReports } from "./routes/reports.js";
|
|
24
|
+
import { ApiError } from "./routes/shared.js";
|
|
25
|
+
/** Route groups an app can serve (docs/design/control-plane.md §9.2). Admin and discovery routes are always there. */
|
|
26
|
+
export const ROUTE_GROUPS = ["evaluations", "rubrics", "hub", "control"];
|
|
27
|
+
/** Reads `VERDICT_ROUTES="hub,control"`; unset serves every group. Throws on a name that is not a group, at startup. */
|
|
28
|
+
export function routeGroups(value) {
|
|
29
|
+
if (!value?.trim())
|
|
30
|
+
return ROUTE_GROUPS;
|
|
31
|
+
const names = value.split(",").map((name) => name.trim()).filter(Boolean);
|
|
32
|
+
const unknown = names.filter((name) => !ROUTE_GROUPS.includes(name));
|
|
33
|
+
if (unknown.length)
|
|
34
|
+
throw new Error(`VERDICT_ROUTES: unknown route group ${unknown.join(", ")}; use ${ROUTE_GROUPS.join(", ")}`);
|
|
35
|
+
return names;
|
|
36
|
+
}
|
|
37
|
+
/** `VERDICT_API_KEYS="key1:tenantA,key2:tenantB"`; a bare key maps to tenant "default". Unset = open (single tenant). */
|
|
38
|
+
export function envAuth(env = globalThis.process?.env ?? {}) {
|
|
39
|
+
const raw = env.VERDICT_API_KEYS?.trim();
|
|
40
|
+
if (!raw)
|
|
41
|
+
return { resolve: () => "default" };
|
|
42
|
+
const keys = new Map(raw.split(",").map((pair) => { const [k, t] = pair.trim().split(":"); return [k, t ?? "default"]; }));
|
|
43
|
+
return { resolve: (k) => (k ? keys.get(k) : undefined) };
|
|
44
|
+
}
|
|
45
|
+
/** Builds the REST app around an engine; route failures are translated into HTTP error responses. */
|
|
46
|
+
export function createApp(options) {
|
|
47
|
+
const { engine, auth = envAuth(), keys, adminKey = globalThis.process?.env?.VERDICT_ADMIN_KEY, allowAsync = true, background, log = false, now, routes = ROUTE_GROUPS } = options;
|
|
48
|
+
const app = new Hono();
|
|
49
|
+
if (log)
|
|
50
|
+
app.use(logger());
|
|
51
|
+
app.use("*", cors({ exposeHeaders: ["Idempotency-Replayed", "ETag"] }));
|
|
52
|
+
app.get("/", (c) => c.json({ name: "verdict", version: "0.1.0", docs: "/v1/openapi.json" }));
|
|
53
|
+
app.get("/v1/health", (c) => c.json({ ok: true }));
|
|
54
|
+
const openapi = openapiFor(routes);
|
|
55
|
+
app.get("/v1/openapi.json", (c) => c.json(openapi));
|
|
56
|
+
// why: admin routes use their own credential and must be registered before tenant authentication.
|
|
57
|
+
registerAdmin(app, { engine, keys, adminKey, allowAsync, background, now });
|
|
58
|
+
app.use("/v1/*", async (c, next) => {
|
|
59
|
+
if (c.req.path === "/v1/health" || c.req.path === "/v1/openapi.json" || c.req.path.startsWith("/v1/admin/") || PUBLIC_HUB_PATHS.has(c.req.path) || isPublicHubPath(c.req.path))
|
|
60
|
+
return next();
|
|
61
|
+
const header = c.req.header("authorization");
|
|
62
|
+
const key = header?.replace(/^Bearer\s+/i, "") ?? c.req.header("x-api-key");
|
|
63
|
+
const who = await auth.resolve(key, c.req.raw);
|
|
64
|
+
if (who === undefined)
|
|
65
|
+
throw new HTTPException(401, { message: "invalid or missing API key" });
|
|
66
|
+
const identity = typeof who === "string" ? { tenantId: who, actor: { kind: "key" } } : who;
|
|
67
|
+
c.set("tenantId", identity.tenantId);
|
|
68
|
+
c.set("actor", identity.actor);
|
|
69
|
+
if (identity.claims)
|
|
70
|
+
c.set("claims", identity.claims);
|
|
71
|
+
await next();
|
|
72
|
+
});
|
|
73
|
+
app.onError((err, c) => {
|
|
74
|
+
if (err instanceof RateLimitedError) {
|
|
75
|
+
c.header("retry-after", "60");
|
|
76
|
+
return c.json({ error: { type: "rate_limited", message: err.message } }, 429);
|
|
77
|
+
}
|
|
78
|
+
if (err instanceof ApiError)
|
|
79
|
+
return c.json({ error: { type: err.type, message: err.message, ...err.extra } }, err.status);
|
|
80
|
+
if (err instanceof HTTPException)
|
|
81
|
+
return c.json({ error: { type: "http", message: err.message } }, err.status);
|
|
82
|
+
if (err instanceof z.ZodError)
|
|
83
|
+
return c.json({ error: { type: "validation", message: "invalid request", issues: err.issues } }, 400);
|
|
84
|
+
if (err instanceof NotFoundError)
|
|
85
|
+
return c.json({ error: { type: "not_found", message: err.message } }, 404);
|
|
86
|
+
if (err instanceof ConflictError)
|
|
87
|
+
return c.json({ error: { type: "idempotency_conflict", message: err.message } }, 409);
|
|
88
|
+
if (err instanceof ValidationError)
|
|
89
|
+
return c.json({ error: { type: "validation", message: err.message } }, 400);
|
|
90
|
+
const message = err.message ?? "internal error";
|
|
91
|
+
// why: legacy rubric validators still throw plain errors; preserve their established 400 responses.
|
|
92
|
+
const status = /duplicate|unknown|requires|must/i.test(message) ? 400 : 500;
|
|
93
|
+
return c.json({ error: { type: status === 400 ? "validation" : "internal", message } }, status);
|
|
94
|
+
});
|
|
95
|
+
registerGroups(app, { ...options, engine, keys, adminKey, allowAsync, background, routes });
|
|
96
|
+
return app;
|
|
97
|
+
}
|
|
98
|
+
function registerGroups(app, options) {
|
|
99
|
+
const { engine, keys, adminKey, allowAsync, background, github, now, limits = defaultHubLimits(now), clientKey = defaultClientKey, publisherOf } = options;
|
|
100
|
+
const on = (group) => options.routes.includes(group);
|
|
101
|
+
if (on("rubrics"))
|
|
102
|
+
registerRubrics(app, { engine, keys, adminKey, allowAsync, background });
|
|
103
|
+
if (on("evaluations")) {
|
|
104
|
+
registerEvaluations(app, { engine, keys, adminKey, allowAsync, background });
|
|
105
|
+
registerBatches(app, { engine, keys, adminKey, allowAsync, background });
|
|
106
|
+
}
|
|
107
|
+
if (on("hub")) {
|
|
108
|
+
registerHub(app, { engine, keys, github, now, limits, clientKey, signIn: options.signIn });
|
|
109
|
+
registerPublications(app, { engine, publisherOf: publisherOf ?? publisherFor({ engine, github }), now, limits });
|
|
110
|
+
registerPublicHub(app, { engine, limits, clientKey });
|
|
111
|
+
}
|
|
112
|
+
if (on("control")) {
|
|
113
|
+
registerProjects(app, options);
|
|
114
|
+
registerProjectVersions(app, options);
|
|
115
|
+
registerPromotions(app, options);
|
|
116
|
+
registerReports(app, options);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export { present } from "./present.js";
|
|
120
|
+
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/github.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface GithubConfig {
|
|
2
|
+
/** OAuth App client id; public — the CLI reads it from GET /v1/hub/config to start the device flow. */
|
|
3
|
+
clientId: string;
|
|
4
|
+
/** OAuth App client secret; when set, tokens are checked against this app. */
|
|
5
|
+
clientSecret?: string;
|
|
6
|
+
/** Default https://api.github.com (GitHub Enterprise Server: https://HOST/api/v3). */
|
|
7
|
+
apiUrl?: string;
|
|
8
|
+
fetch?: typeof fetch;
|
|
9
|
+
}
|
|
10
|
+
export interface GithubAccount {
|
|
11
|
+
id: number;
|
|
12
|
+
login: string;
|
|
13
|
+
}
|
|
14
|
+
/** Resolves the account a token belongs to; 401 for a token GitHub rejects, 502 when GitHub cannot be asked. */
|
|
15
|
+
export declare function verifyGithubToken(token: string, cfg: GithubConfig): Promise<GithubAccount>;
|
package/dist/github.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verifies who a GitHub token belongs to, for hub sign-in (docs/design/hub.md H2). The CLI runs GitHub's device flow
|
|
3
|
+
* itself and hands the hub a token; the hub only asks GitHub whose it is, then forgets it.
|
|
4
|
+
* - With the OAuth App's client secret, the hub asks GitHub to check the token *for this app*
|
|
5
|
+
* (POST /applications/{client_id}/token): a token minted for another app is refused.
|
|
6
|
+
* - Without it, the hub reads GET /user: any valid token of the account is accepted. Fine for trying things out;
|
|
7
|
+
* production should set the secret.
|
|
8
|
+
* Only `fetch` is used, so this runs on Workers.
|
|
9
|
+
*/
|
|
10
|
+
import { HTTPException } from "hono/http-exception";
|
|
11
|
+
const HEADERS = { accept: "application/vnd.github+json", "x-github-api-version": "2022-11-28", "user-agent": "verdict-hub" };
|
|
12
|
+
/** Resolves the account a token belongs to; 401 for a token GitHub rejects, 502 when GitHub cannot be asked. */
|
|
13
|
+
export async function verifyGithubToken(token, cfg) {
|
|
14
|
+
const api = (cfg.apiUrl ?? "https://api.github.com").replace(/\/$/, "");
|
|
15
|
+
const doFetch = cfg.fetch ?? fetch;
|
|
16
|
+
let res;
|
|
17
|
+
try {
|
|
18
|
+
res = cfg.clientSecret
|
|
19
|
+
? await doFetch(`${api}/applications/${encodeURIComponent(cfg.clientId)}/token`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { ...HEADERS, authorization: `Basic ${btoa(`${cfg.clientId}:${cfg.clientSecret}`)}`, "content-type": "application/json" },
|
|
22
|
+
body: JSON.stringify({ access_token: token }),
|
|
23
|
+
})
|
|
24
|
+
: await doFetch(`${api}/user`, { headers: { ...HEADERS, authorization: `Bearer ${token}` } });
|
|
25
|
+
}
|
|
26
|
+
catch (cause) {
|
|
27
|
+
throw new HTTPException(502, { message: `could not reach GitHub to verify the sign-in (${cause instanceof Error ? cause.message : String(cause)})` });
|
|
28
|
+
}
|
|
29
|
+
// 401 (bad token), 404 (token not of this app), 422 (malformed) all mean "not a valid sign-in for this hub".
|
|
30
|
+
if (res.status === 401 || res.status === 404 || res.status === 422)
|
|
31
|
+
throw new HTTPException(401, { message: "GitHub did not accept this token for this hub; run `verdict hub login` again" });
|
|
32
|
+
if (!res.ok)
|
|
33
|
+
throw new HTTPException(502, { message: `GitHub answered ${res.status} while verifying the sign-in` });
|
|
34
|
+
const body = (await res.json());
|
|
35
|
+
const user = cfg.clientSecret ? body.user : body;
|
|
36
|
+
if (typeof user?.id !== "number" || typeof user.login !== "string")
|
|
37
|
+
throw new HTTPException(502, { message: "GitHub's answer did not name an account" });
|
|
38
|
+
return { id: user.id, login: user.login };
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=github.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github.js","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAcpD,MAAM,OAAO,GAAG,EAAE,MAAM,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AAE7H,gHAAgH;AAChH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,KAAa,EAAE,GAAiB;IACtE,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,IAAI,wBAAwB,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC;IACnC,IAAI,GAAa,CAAC;IAClB,IAAI,CAAC;QACH,GAAG,GAAG,GAAG,CAAC,YAAY;YACpB,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,GAAG,iBAAiB,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE;gBAC/E,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,SAAS,IAAI,CAAC,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAClI,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;aAC9C,CAAC;YACF,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,GAAG,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,OAAO,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAClG,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,iDAAiD,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IACxJ,CAAC;IACD,6GAA6G;IAC7G,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG;QAAE,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,8EAA8E,EAAE,CAAC,CAAC;IAC9L,IAAI,CAAC,GAAG,CAAC,EAAE;QAAE,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,mBAAmB,GAAG,CAAC,MAAM,8BAA8B,EAAE,CAAC,CAAC;IACpH,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAgF,CAAC;IAC/G,MAAM,IAAI,GAAG,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IACjD,IAAI,OAAO,IAAI,EAAE,EAAE,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,yCAAyC,EAAE,CAAC,CAAC;IACzJ,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-rendered hub pages (docs/design/hub.md §16.3). Plain HTML and inline CSS, no scripts: every string shown was
|
|
3
|
+
* written by an author and is escaped. Pages offer copyable `verdict pull` / `verdict fork` commands instead of links
|
|
4
|
+
* that open a local server (H4).
|
|
5
|
+
*/
|
|
6
|
+
import { type Publication, type PublicListing, type PublicPublication, type PublicVersionEntry } from "@verdict-ai/core";
|
|
7
|
+
export interface SearchView {
|
|
8
|
+
query: {
|
|
9
|
+
q?: string;
|
|
10
|
+
domain?: string;
|
|
11
|
+
locale?: string;
|
|
12
|
+
type?: string;
|
|
13
|
+
};
|
|
14
|
+
results: PublicListing[];
|
|
15
|
+
}
|
|
16
|
+
export declare function searchPage({ query, results }: SearchView): string;
|
|
17
|
+
export interface CardView {
|
|
18
|
+
origin: string;
|
|
19
|
+
publication: PublicPublication;
|
|
20
|
+
versions: PublicVersionEntry[];
|
|
21
|
+
}
|
|
22
|
+
export declare function cardPage({ origin, publication: p, versions }: CardView): string;
|
|
23
|
+
export declare function goneCardPage(p: Publication, message: string): string;
|
|
24
|
+
export declare function missingPage(message: string): string;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-rendered hub pages (docs/design/hub.md §16.3). Plain HTML and inline CSS, no scripts: every string shown was
|
|
3
|
+
* written by an author and is escaped. Pages offer copyable `verdict pull` / `verdict fork` commands instead of links
|
|
4
|
+
* that open a local server (H4).
|
|
5
|
+
*/
|
|
6
|
+
import { questionAgreement, rubricToYaml } from "@verdict-ai/core";
|
|
7
|
+
const STYLE = `
|
|
8
|
+
:root{color-scheme:light dark;--fg:#1d1d1f;--muted:#6e6e73;--line:#d2d2d7;--bg:#fff;--card:#f5f5f7;--accent:#0b5cad}
|
|
9
|
+
@media (prefers-color-scheme:dark){:root{--fg:#f5f5f7;--muted:#a1a1a6;--line:#3a3a3c;--bg:#111;--card:#1c1c1e;--accent:#6cb4ff}}
|
|
10
|
+
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.5 system-ui,-apple-system,"Segoe UI",sans-serif}
|
|
11
|
+
main{max-width:920px;margin:0 auto;padding:24px 16px 64px}a{color:var(--accent)}h1{font-size:26px;margin:8px 0}h2{font-size:18px;margin:28px 0 8px}
|
|
12
|
+
.muted{color:var(--muted)}.meta span{margin-right:12px}.box{background:var(--card);border:1px solid var(--line);border-radius:10px;padding:12px 16px;margin:8px 0}
|
|
13
|
+
pre,code{font:13px/1.45 ui-monospace,SFMono-Regular,Menlo,monospace}pre{white-space:pre-wrap;word-break:break-word;margin:0}pre.text{font:inherit}
|
|
14
|
+
code.cmd{display:block;user-select:all;background:var(--bg);border:1px solid var(--line);border-radius:6px;padding:8px;margin:4px 0;overflow-x:auto}
|
|
15
|
+
table{border-collapse:collapse;width:100%}td,th{border-bottom:1px solid var(--line);padding:6px 8px;text-align:left;vertical-align:top}
|
|
16
|
+
form{display:flex;flex-wrap:wrap;gap:8px}input,select,button{font:inherit;padding:6px 8px;border:1px solid var(--line);border-radius:6px;background:var(--bg);color:var(--fg)}
|
|
17
|
+
input[name=q]{flex:1 1 240px}.tag{display:inline-block;border:1px solid var(--line);border-radius:999px;padding:0 8px;font-size:12px;margin-right:4px}
|
|
18
|
+
`;
|
|
19
|
+
const esc = (value) => String(value ?? "").replace(/[&<>"']/g, (ch) => `&#${ch.charCodeAt(0)};`);
|
|
20
|
+
const day = (iso) => esc(iso.slice(0, 10));
|
|
21
|
+
const cardUrl = (ref, versionId) => `/hub/${ref.split("/").map(encodeURIComponent).join("/")}${versionId ? `?version=${encodeURIComponent(versionId)}` : ""}`;
|
|
22
|
+
const pct = (agreed, n) => (n ? `${Math.round((agreed / n) * 100)}%` : "–");
|
|
23
|
+
function layout(title, body) {
|
|
24
|
+
return `<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
|
25
|
+
<title>${esc(title)} · Verdict hub</title><style>${STYLE}</style></head><body><main>
|
|
26
|
+
<p class="muted"><a href="/hub">Verdict hub</a> — single-question judgment cards with their test cases</p>
|
|
27
|
+
${body}</main></body></html>`;
|
|
28
|
+
}
|
|
29
|
+
export function searchPage({ query, results }) {
|
|
30
|
+
const type = (value, label) => `<option value="${value}"${query.type === value ? " selected" : ""}>${label}</option>`;
|
|
31
|
+
const form = `<form method="get" action="/hub">
|
|
32
|
+
<input name="q" placeholder="Search titles, authors, slugs, domains" value="${esc(query.q)}">
|
|
33
|
+
<input name="domain" placeholder="domain" value="${esc(query.domain)}" size="14"><input name="locale" placeholder="locale" value="${esc(query.locale)}" size="8">
|
|
34
|
+
<select name="type">${type("", "any answer")}${type("noul", "yes / no")}${type("score", "score")}${type("choice", "choice")}</select><button>Search</button></form>`;
|
|
35
|
+
const list = results.length ? results.map(resultItem).join("") : `<p class="muted">No published cards match.</p>`;
|
|
36
|
+
return layout("Search", `<h1>Judgment cards</h1>${form}${list}`);
|
|
37
|
+
}
|
|
38
|
+
function resultItem(r) {
|
|
39
|
+
const tags = [r.judgmentType, r.domain, r.locale, r.license].filter(Boolean).map((t) => `<span class="tag">${esc(t)}</span>`).join("");
|
|
40
|
+
const fork = r.parent?.public ? ` · fork of <a href="${cardUrl(r.parent.ref, r.parent.versionId)}">${esc(r.parent.ref)}</a>` : r.parent ? " · fork of an unpublished version" : "";
|
|
41
|
+
return `<div class="box"><a href="${cardUrl(r.ref)}"><strong>${esc(r.title)}</strong></a> <span class="muted">${esc(r.ref)}</span><br>
|
|
42
|
+
${r.description ? `<span>${esc(r.description)}</span><br>` : ""}${tags} <span class="muted">${r.cases} public case(s) · ${r.runs} reported run(s) · ${day(r.latest.createdAt)}${fork}</span></div>`;
|
|
43
|
+
}
|
|
44
|
+
export function cardPage({ origin, publication: p, versions }) {
|
|
45
|
+
const header = `<h1>${esc(p.title)}</h1>
|
|
46
|
+
<p class="meta muted"><span>${esc(p.ref)}</span><span><code>${esc(p.version.id)}</code></span><span>${esc(p.judgmentType)}</span><span>${esc(p.license)}</span>${p.domain ? `<span>${esc(p.domain)}</span>` : ""}${p.locale ? `<span>${esc(p.locale)}</span>` : ""}<span>published ${day(p.createdAt)}</span></p>
|
|
47
|
+
${p.description ? `<p>${esc(p.description)}</p>` : ""}`;
|
|
48
|
+
return layout(p.title, [header, lineage(p), useIt(origin, p), question(p), runs(p), cases(p), provenance(p), history(p.ref, p.version.id, versions), rubricSource(p)].join(""));
|
|
49
|
+
}
|
|
50
|
+
function lineage(p) {
|
|
51
|
+
if (!p.parent)
|
|
52
|
+
return "";
|
|
53
|
+
const from = p.parent.public ? `Forked from <a href="${cardUrl(p.parent.ref, p.parent.versionId)}">${esc(p.parent.ref)}</a> at <code>${esc(p.parent.versionId)}</code>.` : "Derived from a version that is not public.";
|
|
54
|
+
const kinds = p.version.changeKinds?.length ? ` Changed: ${p.version.changeKinds.map((k) => `<span class="tag">${esc(k)}</span>`).join("")}` : "";
|
|
55
|
+
return `<div class="box">${from}${kinds}${p.version.forkNote ? `<br><span class="muted">Fork note:</span> ${esc(p.version.forkNote)}` : ""}
|
|
56
|
+
<br><span class="muted">Results of the parent are not results of this version; each version shows only its own runs.</span></div>`;
|
|
57
|
+
}
|
|
58
|
+
function useIt(origin, p) {
|
|
59
|
+
const ref = `hub:${p.ref}@${p.version.id}`, hub = `--hub ${origin}`;
|
|
60
|
+
return `<h2>Use it</h2><div class="box">Copy this version exactly (same id when you freeze it), with its public cases:
|
|
61
|
+
<code class="cmd">verdict pull ${esc(ref)} ${esc(hub)}</code>Or start your own version from it; the parent is recorded in verdict.lock:
|
|
62
|
+
<code class="cmd">verdict fork ${esc(ref)} --to ${esc(p.slug)}.yaml ${esc(hub)}</code></div>`;
|
|
63
|
+
}
|
|
64
|
+
function question(p) {
|
|
65
|
+
const c = p.version.rubric.criteria[0];
|
|
66
|
+
const answers = c.choices ? Object.entries(c.choices) : c.levels ? c.levels.map((l) => [l.label ?? String(l.value), l.description]) : Object.entries(c.anchors ?? {});
|
|
67
|
+
const list = answers.length ? `<table>${answers.map(([k, v]) => `<tr><th>${esc(k)}</th><td>${esc(v)}</td></tr>`).join("")}</table>` : "";
|
|
68
|
+
const threshold = c.threshold !== undefined ? `<p class="muted">Answers yes when the model's probability of yes is at least ${esc(c.threshold)}.</p>` : "";
|
|
69
|
+
return `<h2>The question</h2><div class="box"><strong>${esc(c.name)}</strong>${c.description ? `<pre class="text">${esc(c.description)}</pre>` : ""}${list}${threshold}</div>`;
|
|
70
|
+
}
|
|
71
|
+
function runs(p) {
|
|
72
|
+
const list = p.runs;
|
|
73
|
+
if (!list.length)
|
|
74
|
+
return `<h2>Reported runs</h2><p class="muted">The author attached no runs.</p>`;
|
|
75
|
+
return `<h2>Reported runs</h2>${list.map((r) => runBox(p, r)).join("")}`;
|
|
76
|
+
}
|
|
77
|
+
function runBox(p, r) {
|
|
78
|
+
const q = questionAgreement(p, r);
|
|
79
|
+
const models = r.fingerprint.models.map((m) => `${m.provider}${m.resolved ? ` ${m.resolved}` : m.requested ? ` ${m.requested} (requested)` : ""}${m.verified ? "" : " (unverified)"}`).join(", ");
|
|
80
|
+
const sources = r.labelSources ? Object.entries(r.labelSources).map(([k, n]) => `${esc(k)} ${n}`).join(" · ") : "unknown";
|
|
81
|
+
const criteria = Object.entries(r.agreement.criteria).map(([id, t]) => `<tr><td>${esc(id)}</td><td>${t.agreed}/${t.n} (${pct(t.agreed, t.n)})</td><td>${t.askedHuman}</td></tr>`).join("");
|
|
82
|
+
return `<div class="box"><strong>${pct(q.agreed, q.n)}</strong> agreement with the labels (${q.agreed} of ${q.n} labelled case(s)${q.askedHuman ? `; ${q.askedHuman} handed to a person` : ""}) over ${r.counts.cases} case(s) · ${esc(r.status)} · ${day(r.startedAt)}
|
|
83
|
+
<br><span class="muted">Reported by the author, not re-run by the hub. ${r.casesPublic ? "Every case of this run is public: anyone can repeat it." : "This run includes private cases: only its numbers are shown."}</span>
|
|
84
|
+
<br><span class="muted">Models:</span> ${esc(models || "–")} · <span class="muted">labels:</span> ${sources}
|
|
85
|
+
<table><tr><th>criterion</th><th>agreed</th><th>asked a person</th></tr>${criteria}</table></div>`;
|
|
86
|
+
}
|
|
87
|
+
function cases(p) {
|
|
88
|
+
if (!p.cases.length)
|
|
89
|
+
return `<h2>Public cases</h2><p class="muted">No public cases.</p>`;
|
|
90
|
+
const rows = p.cases.map((c) => `<tr><td>${esc(c.id)}</td><td><pre class="text">${esc(c.inputs.map(inputText).join("\n"))}</pre></td><td>${esc(Object.values(c.expected).join(", "))}</td><td>${esc(c.labelSource ?? "unknown")}${c.split ? ` · ${esc(c.split)}` : ""}</td></tr>`).join("");
|
|
91
|
+
return `<h2>Public cases (${p.cases.length})</h2><table><tr><th>case</th><th>input</th><th>expected</th><th>label</th></tr>${rows}</table>`;
|
|
92
|
+
}
|
|
93
|
+
function inputText(input) {
|
|
94
|
+
const raw = input;
|
|
95
|
+
const text = raw.type === "text" ? raw.text ?? "" : raw.type === "url" ? raw.url ?? "" : JSON.stringify(raw.data ?? raw);
|
|
96
|
+
return text.length > 600 ? `${text.slice(0, 600)}…` : text;
|
|
97
|
+
}
|
|
98
|
+
function provenance(p) {
|
|
99
|
+
if (!p.sources.length && !p.note)
|
|
100
|
+
return "";
|
|
101
|
+
return `<h2>Sources</h2><div class="box">${p.sources.map((s) => `<div>${esc(s)}</div>`).join("")}${p.note ? `<p>${esc(p.note)}</p>` : ""}</div>`;
|
|
102
|
+
}
|
|
103
|
+
function history(ref, current, versions) {
|
|
104
|
+
const rows = versions.map((v) => {
|
|
105
|
+
const label = v.versionId === current ? `<strong>${esc(v.versionId)}</strong>` : v.withdrawnAt ? esc(v.versionId) : `<a href="${cardUrl(ref, v.versionId)}">${esc(v.versionId)}</a>`;
|
|
106
|
+
return `<tr><td><code>${label}</code></td><td>${day(v.createdAt)}</td><td>${v.withdrawnAt ? `withdrawn ${day(v.withdrawnAt)}` : esc(v.changeKinds?.join(", ") ?? "")}</td></tr>`;
|
|
107
|
+
}).join("");
|
|
108
|
+
return `<h2>Versions</h2><table>${rows}</table>`;
|
|
109
|
+
}
|
|
110
|
+
function rubricSource(p) {
|
|
111
|
+
return `<h2>Rubric</h2><details class="box"><summary>YAML of ${esc(p.version.id)}</summary><pre>${esc(rubricToYaml(p.version.rubric))}</pre></details>`;
|
|
112
|
+
}
|
|
113
|
+
export function goneCardPage(p, message) {
|
|
114
|
+
return layout(p.title, `<h1>${esc(p.title)}</h1><p class="muted">${esc(p.ref)} · <code>${esc(p.version.id)}</code></p><div class="box">${esc(message)}.</div><p><a href="${cardUrl(p.ref)}">See this card's other versions</a></p>`);
|
|
115
|
+
}
|
|
116
|
+
export function missingPage(message) {
|
|
117
|
+
return layout("Not found", `<h1>Not found</h1><p>${esc(message)}.</p>`);
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=hub-pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-pages.js","sourceRoot":"","sources":["../src/hub-pages.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exports the package entry points without starting services.
|
|
3
|
+
* Consumers choose their runtime adapters explicitly; importing types must not open network or database connections.
|
|
4
|
+
*/
|
|
5
|
+
export { createApp, envAuth, present, ROUTE_GROUPS, routeGroups, type Auth, type AppOptions, type BrowserSignIn, type Identity, type RouteGroup } from "./app.js";
|
|
6
|
+
export { cloudflareLimiter, DEFAULT_HUB_RULES, defaultHubLimits, memoryLimiter, type ClientKey, type CloudflareRateLimit, type HubLimits, type RateLimiter, type Rule } from "./rate-limit.js";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exports the package entry points without starting services.
|
|
3
|
+
* Consumers choose their runtime adapters explicitly; importing types must not open network or database connections.
|
|
4
|
+
*/
|
|
5
|
+
export { createApp, envAuth, present, ROUTE_GROUPS, routeGroups } from "./app.js";
|
|
6
|
+
export { cloudflareLimiter, DEFAULT_HUB_RULES, defaultHubLimits, memoryLimiter } from "./rate-limit.js";
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,WAAW,EAAkF,MAAM,UAAU,CAAC;AAClK,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,aAAa,EAAyF,MAAM,iBAAiB,CAAC"}
|