@q32/core 0.1.1

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.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +60 -0
  3. package/dist/ai.d.ts +26 -0
  4. package/dist/ai.d.ts.map +1 -0
  5. package/dist/ai.js +16 -0
  6. package/dist/ai.js.map +1 -0
  7. package/dist/api.d.ts +25 -0
  8. package/dist/api.d.ts.map +1 -0
  9. package/dist/api.js +66 -0
  10. package/dist/api.js.map +1 -0
  11. package/dist/billing.d.ts +21 -0
  12. package/dist/billing.d.ts.map +1 -0
  13. package/dist/billing.js +18 -0
  14. package/dist/billing.js.map +1 -0
  15. package/dist/cloudflare.d.ts +12 -0
  16. package/dist/cloudflare.d.ts.map +1 -0
  17. package/dist/cloudflare.js +25 -0
  18. package/dist/cloudflare.js.map +1 -0
  19. package/dist/crypto.d.ts +10 -0
  20. package/dist/crypto.d.ts.map +1 -0
  21. package/dist/crypto.js +42 -0
  22. package/dist/crypto.js.map +1 -0
  23. package/dist/d1.d.ts +34 -0
  24. package/dist/d1.d.ts.map +1 -0
  25. package/dist/d1.js +44 -0
  26. package/dist/d1.js.map +1 -0
  27. package/dist/email.d.ts +33 -0
  28. package/dist/email.d.ts.map +1 -0
  29. package/dist/email.js +16 -0
  30. package/dist/email.js.map +1 -0
  31. package/dist/env.d.ts +11 -0
  32. package/dist/env.d.ts.map +1 -0
  33. package/dist/env.js +55 -0
  34. package/dist/env.js.map +1 -0
  35. package/dist/http.d.ts +14 -0
  36. package/dist/http.d.ts.map +1 -0
  37. package/dist/http.js +53 -0
  38. package/dist/http.js.map +1 -0
  39. package/dist/ids.d.ts +7 -0
  40. package/dist/ids.d.ts.map +1 -0
  41. package/dist/ids.js +35 -0
  42. package/dist/ids.js.map +1 -0
  43. package/dist/index.d.ts +22 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +22 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/jobs.d.ts +52 -0
  48. package/dist/jobs.d.ts.map +1 -0
  49. package/dist/jobs.js +195 -0
  50. package/dist/jobs.js.map +1 -0
  51. package/dist/mcp.d.ts +18 -0
  52. package/dist/mcp.d.ts.map +1 -0
  53. package/dist/mcp.js +33 -0
  54. package/dist/mcp.js.map +1 -0
  55. package/dist/oauth.d.ts +17 -0
  56. package/dist/oauth.d.ts.map +1 -0
  57. package/dist/oauth.js +33 -0
  58. package/dist/oauth.js.map +1 -0
  59. package/dist/ops-events.d.ts +25 -0
  60. package/dist/ops-events.d.ts.map +1 -0
  61. package/dist/ops-events.js +43 -0
  62. package/dist/ops-events.js.map +1 -0
  63. package/dist/pg.d.ts +27 -0
  64. package/dist/pg.d.ts.map +1 -0
  65. package/dist/pg.js +51 -0
  66. package/dist/pg.js.map +1 -0
  67. package/dist/r2-json.d.ts +8 -0
  68. package/dist/r2-json.d.ts.map +1 -0
  69. package/dist/r2-json.js +21 -0
  70. package/dist/r2-json.js.map +1 -0
  71. package/dist/rate-limit.d.ts +19 -0
  72. package/dist/rate-limit.d.ts.map +1 -0
  73. package/dist/rate-limit.js +48 -0
  74. package/dist/rate-limit.js.map +1 -0
  75. package/dist/seo.d.ts +23 -0
  76. package/dist/seo.d.ts.map +1 -0
  77. package/dist/seo.js +60 -0
  78. package/dist/seo.js.map +1 -0
  79. package/dist/session.d.ts +11 -0
  80. package/dist/session.d.ts.map +1 -0
  81. package/dist/session.js +55 -0
  82. package/dist/session.js.map +1 -0
  83. package/dist/testing.d.ts +25 -0
  84. package/dist/testing.d.ts.map +1 -0
  85. package/dist/testing.js +94 -0
  86. package/dist/testing.js.map +1 -0
  87. package/dist/time.d.ts +5 -0
  88. package/dist/time.d.ts.map +1 -0
  89. package/dist/time.js +17 -0
  90. package/dist/time.js.map +1 -0
  91. package/docs/evaluation.md +74 -0
  92. package/docs/goal-audit.md +28 -0
  93. package/package.json +129 -0
package/dist/http.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ export type JsonResponseInit = ResponseInit & {
2
+ pretty?: boolean;
3
+ };
4
+ export declare class HttpError extends Error {
5
+ readonly status: number;
6
+ readonly code: string;
7
+ constructor(status: number, message: string, code?: string);
8
+ }
9
+ export declare function jsonResponse(value: unknown, init?: JsonResponseInit): Response;
10
+ export declare function errorResponse(error: unknown, fallbackStatus?: number): Response;
11
+ export declare function readJson<T = unknown>(request: Request): Promise<T>;
12
+ export declare function requireBearerToken(request: Request): string;
13
+ export declare function requireAdminToken(request: Request, expected: string | undefined): void;
14
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG;IAC5C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF,qBAAa,SAAU,SAAQ,KAAK;aAEhB,MAAM,EAAE,MAAM;aAEd,IAAI;gBAFJ,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM,EACC,IAAI,SAAe;CAKtC;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAE,gBAAqB,GAAG,QAAQ,CAOlF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,SAAM,GAAG,QAAQ,CAM5E;AAED,wBAAsB,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,CAUxE;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAK3D;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAItF"}
package/dist/http.js ADDED
@@ -0,0 +1,53 @@
1
+ export class HttpError extends Error {
2
+ status;
3
+ code;
4
+ constructor(status, message, code = "http_error") {
5
+ super(message);
6
+ this.status = status;
7
+ this.code = code;
8
+ this.name = "HttpError";
9
+ }
10
+ }
11
+ export function jsonResponse(value, init = {}) {
12
+ const headers = new Headers(init.headers);
13
+ if (!headers.has("content-type"))
14
+ headers.set("content-type", "application/json; charset=utf-8");
15
+ return new Response(JSON.stringify(value, null, init.pretty ? 2 : 0), {
16
+ ...init,
17
+ headers,
18
+ });
19
+ }
20
+ export function errorResponse(error, fallbackStatus = 500) {
21
+ if (error instanceof HttpError) {
22
+ return jsonResponse({ error: { code: error.code, message: error.message } }, { status: error.status });
23
+ }
24
+ const message = error instanceof Error ? error.message : String(error);
25
+ return jsonResponse({ error: { code: "internal_error", message } }, { status: fallbackStatus });
26
+ }
27
+ export async function readJson(request) {
28
+ const contentType = request.headers.get("content-type") ?? "";
29
+ if (!contentType.toLowerCase().includes("application/json")) {
30
+ throw new HttpError(415, "Expected application/json request body.", "unsupported_media_type");
31
+ }
32
+ try {
33
+ return (await request.json());
34
+ }
35
+ catch {
36
+ throw new HttpError(400, "Invalid JSON request body.", "invalid_json");
37
+ }
38
+ }
39
+ export function requireBearerToken(request) {
40
+ const value = request.headers.get("authorization") ?? "";
41
+ const match = value.match(/^Bearer\s+(.+)$/i);
42
+ if (!match)
43
+ throw new HttpError(401, "Missing bearer token.", "missing_bearer_token");
44
+ return match[1];
45
+ }
46
+ export function requireAdminToken(request, expected) {
47
+ if (!expected)
48
+ throw new HttpError(500, "Admin token is not configured.", "admin_token_not_configured");
49
+ const provided = request.headers.get("x-admin-token") ?? requireBearerToken(request);
50
+ if (provided !== expected)
51
+ throw new HttpError(403, "Invalid admin token.", "invalid_admin_token");
52
+ }
53
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
package/dist/ids.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ export declare function createId(prefix: string, bytes?: number): string;
2
+ export declare function createToken(prefix?: string, bytes?: number): string;
3
+ export declare function randomBase64Url(bytes?: number): string;
4
+ export declare function toBase64Url(input: string | Uint8Array): string;
5
+ export declare function fromBase64Url(value: string): Uint8Array;
6
+ export declare function sha256Hex(input: string): Promise<string>;
7
+ //# sourceMappingURL=ids.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.d.ts","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,MAAM,CAI3D;AAED,wBAAgB,WAAW,CAAC,MAAM,SAAQ,EAAE,KAAK,SAAsB,GAAG,MAAM,CAE/E;AAED,wBAAgB,eAAe,CAAC,KAAK,SAAsB,GAAG,MAAM,CAInE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAK9D;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAMvD;AAED,wBAAsB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAG9D"}
package/dist/ids.js ADDED
@@ -0,0 +1,35 @@
1
+ const DEFAULT_TOKEN_BYTES = 32;
2
+ export function createId(prefix, bytes = 12) {
3
+ const cleanPrefix = prefix.trim().replace(/[^a-zA-Z0-9_-]/g, "_");
4
+ if (!cleanPrefix)
5
+ throw new Error("ID prefix is required.");
6
+ return `${cleanPrefix}_${randomBase64Url(bytes)}`;
7
+ }
8
+ export function createToken(prefix = "tok", bytes = DEFAULT_TOKEN_BYTES) {
9
+ return createId(prefix, bytes);
10
+ }
11
+ export function randomBase64Url(bytes = DEFAULT_TOKEN_BYTES) {
12
+ const data = new Uint8Array(Math.max(1, Math.floor(bytes)));
13
+ crypto.getRandomValues(data);
14
+ return toBase64Url(data);
15
+ }
16
+ export function toBase64Url(input) {
17
+ const bytes = typeof input === "string" ? new TextEncoder().encode(input) : input;
18
+ let binary = "";
19
+ for (const byte of bytes)
20
+ binary += String.fromCharCode(byte);
21
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
22
+ }
23
+ export function fromBase64Url(value) {
24
+ const padded = value.replace(/-/g, "+").replace(/_/g, "/").padEnd(Math.ceil(value.length / 4) * 4, "=");
25
+ const binary = atob(padded);
26
+ const bytes = new Uint8Array(binary.length);
27
+ for (let i = 0; i < binary.length; i += 1)
28
+ bytes[i] = binary.charCodeAt(i);
29
+ return bytes;
30
+ }
31
+ export async function sha256Hex(input) {
32
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(input));
33
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
34
+ }
35
+ //# sourceMappingURL=ids.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAE/B,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,KAAK,GAAG,EAAE;IACjD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;IAClE,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5D,OAAO,GAAG,WAAW,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAM,GAAG,KAAK,EAAE,KAAK,GAAG,mBAAmB;IACrE,OAAO,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,KAAK,GAAG,mBAAmB;IACzD,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,WAAW,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAA0B;IACpD,MAAM,KAAK,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAClF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,MAAM,IAAI,IAAI,KAAK;QAAE,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClF,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACxG,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC3E,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,KAAa;IAC3C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAChG,CAAC"}
@@ -0,0 +1,22 @@
1
+ export * from "./api.js";
2
+ export * from "./ai.js";
3
+ export * from "./billing.js";
4
+ export * from "./cloudflare.js";
5
+ export * from "./crypto.js";
6
+ export * from "./d1.js";
7
+ export * from "./email.js";
8
+ export * from "./env.js";
9
+ export * from "./http.js";
10
+ export * from "./ids.js";
11
+ export * from "./jobs.js";
12
+ export * from "./mcp.js";
13
+ export * from "./oauth.js";
14
+ export * from "./ops-events.js";
15
+ export * from "./pg.js";
16
+ export * from "./r2-json.js";
17
+ export * from "./rate-limit.js";
18
+ export * from "./seo.js";
19
+ export * from "./session.js";
20
+ export * from "./testing.js";
21
+ export * from "./time.js";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ export * from "./api.js";
2
+ export * from "./ai.js";
3
+ export * from "./billing.js";
4
+ export * from "./cloudflare.js";
5
+ export * from "./crypto.js";
6
+ export * from "./d1.js";
7
+ export * from "./email.js";
8
+ export * from "./env.js";
9
+ export * from "./http.js";
10
+ export * from "./ids.js";
11
+ export * from "./jobs.js";
12
+ export * from "./mcp.js";
13
+ export * from "./oauth.js";
14
+ export * from "./ops-events.js";
15
+ export * from "./pg.js";
16
+ export * from "./r2-json.js";
17
+ export * from "./rate-limit.js";
18
+ export * from "./seo.js";
19
+ export * from "./session.js";
20
+ export * from "./testing.js";
21
+ export * from "./time.js";
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,WAAW,CAAC;AAC1B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC;AACzB,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC"}
package/dist/jobs.d.ts ADDED
@@ -0,0 +1,52 @@
1
+ import type { D1DatabaseLike } from "./d1.js";
2
+ export type JobStatus = "queued" | "running" | "succeeded" | "failed";
3
+ export type JobHandlerResult<TResult = unknown> = {
4
+ kind: "done";
5
+ result?: TResult | null;
6
+ } | {
7
+ kind: "requeue";
8
+ result?: TResult | null;
9
+ availableAt?: string | null;
10
+ };
11
+ export type JobRecord<TPayload = unknown, TResult = unknown> = {
12
+ jobId: string;
13
+ jobType: string;
14
+ status: JobStatus;
15
+ payload: TPayload;
16
+ result: TResult | null;
17
+ lockKey: string | null;
18
+ attemptCount: number;
19
+ maxAttempts: number;
20
+ availableAt: string | null;
21
+ startedAt: string | null;
22
+ completedAt: string | null;
23
+ lastError: string | null;
24
+ createdAt: string;
25
+ updatedAt: string;
26
+ };
27
+ export type EnqueueJobInput<TPayload = unknown> = {
28
+ jobType: string;
29
+ payload?: TPayload;
30
+ lockKey?: string | null;
31
+ maxAttempts?: number;
32
+ availableAt?: string | null;
33
+ };
34
+ export declare class D1JobStore {
35
+ private readonly db;
36
+ private readonly options;
37
+ constructor(db: D1DatabaseLike, options?: {
38
+ tableName?: string;
39
+ idPrefix?: string;
40
+ });
41
+ get tableName(): string;
42
+ enqueue<TPayload = unknown>(input: EnqueueJobInput<TPayload>): Promise<JobRecord<TPayload>>;
43
+ get<TPayload = unknown, TResult = unknown>(jobId: string): Promise<JobRecord<TPayload, TResult> | null>;
44
+ listQueued(limit?: number): Promise<JobRecord[]>;
45
+ claim<TPayload = unknown>(jobId: string): Promise<JobRecord<TPayload> | null>;
46
+ succeed<TResult = unknown>(jobId: string, result?: TResult | null): Promise<void>;
47
+ requeue<TResult = unknown>(jobId: string, result?: TResult | null, availableAt?: string | null): Promise<void>;
48
+ fail(jobId: string, error: unknown): Promise<void>;
49
+ run<TPayload = unknown, TResult = unknown>(jobId: string, handler: (job: JobRecord<TPayload, TResult>) => Promise<JobHandlerResult<TResult> | TResult | void>): Promise<JobHandlerResult<TResult>>;
50
+ }
51
+ export declare const D1_JOBS_SCHEMA = "\nCREATE TABLE IF NOT EXISTS jobs (\n job_id TEXT PRIMARY KEY,\n job_type TEXT NOT NULL,\n status TEXT NOT NULL,\n payload_json TEXT NOT NULL DEFAULT '{}',\n result_json TEXT,\n lock_key TEXT,\n attempt_count INTEGER NOT NULL DEFAULT 0,\n max_attempts INTEGER NOT NULL DEFAULT 3,\n available_at TEXT,\n started_at TEXT,\n completed_at TEXT,\n last_error TEXT,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL\n);\nCREATE INDEX IF NOT EXISTS jobs_status_available_idx ON jobs(status, available_at, created_at);\nCREATE INDEX IF NOT EXISTS jobs_type_status_idx ON jobs(job_type, status, created_at);\nCREATE UNIQUE INDEX IF NOT EXISTS jobs_active_lock_key_idx ON jobs(lock_key)\n WHERE lock_key IS NOT NULL AND status IN ('queued', 'running');\n";
52
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"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"}
package/dist/jobs.js ADDED
@@ -0,0 +1,195 @@
1
+ import { parseJsonColumn, stringifyJsonColumn } from "./d1.js";
2
+ import { createId } from "./ids.js";
3
+ import { isFutureIso, nowIso } from "./time.js";
4
+ export class D1JobStore {
5
+ db;
6
+ options;
7
+ constructor(db, options = {}) {
8
+ this.db = db;
9
+ this.options = options;
10
+ }
11
+ get tableName() {
12
+ return this.options.tableName ?? "jobs";
13
+ }
14
+ async enqueue(input) {
15
+ const jobId = createId(this.options.idPrefix ?? "job");
16
+ const now = nowIso();
17
+ await this.db
18
+ .prepare(`INSERT INTO ${this.tableName} (
19
+ job_id, job_type, status, payload_json, result_json, lock_key,
20
+ attempt_count, max_attempts, available_at, created_at, updated_at
21
+ ) VALUES (?, ?, 'queued', ?, NULL, ?, 0, ?, ?, ?, ?)`)
22
+ .bind(jobId, input.jobType, stringifyJsonColumn(input.payload ?? {}), input.lockKey ?? null, Math.max(1, Math.floor(input.maxAttempts ?? 3)), input.availableAt ?? null, now, now)
23
+ .run();
24
+ const job = await this.get(jobId);
25
+ if (!job)
26
+ throw new Error(`Failed to load enqueued job: ${jobId}`);
27
+ return job;
28
+ }
29
+ async get(jobId) {
30
+ const row = await this.db
31
+ .prepare(`SELECT
32
+ job_id AS jobId,
33
+ job_type AS jobType,
34
+ status,
35
+ payload_json AS payloadJson,
36
+ result_json AS resultJson,
37
+ lock_key AS lockKey,
38
+ attempt_count AS attemptCount,
39
+ max_attempts AS maxAttempts,
40
+ available_at AS availableAt,
41
+ started_at AS startedAt,
42
+ completed_at AS completedAt,
43
+ last_error AS lastError,
44
+ created_at AS createdAt,
45
+ updated_at AS updatedAt
46
+ FROM ${this.tableName}
47
+ WHERE job_id = ?
48
+ LIMIT 1`)
49
+ .bind(jobId)
50
+ .first();
51
+ return row ? rowToJob(row) : null;
52
+ }
53
+ async listQueued(limit = 25) {
54
+ const now = nowIso();
55
+ const rows = await this.db
56
+ .prepare(`SELECT
57
+ job_id AS jobId, job_type AS jobType, status, payload_json AS payloadJson,
58
+ result_json AS resultJson, lock_key AS lockKey, attempt_count AS attemptCount,
59
+ max_attempts AS maxAttempts, available_at AS availableAt, started_at AS startedAt,
60
+ completed_at AS completedAt, last_error AS lastError, created_at AS createdAt, updated_at AS updatedAt
61
+ FROM ${this.tableName}
62
+ WHERE status = 'queued' AND (available_at IS NULL OR available_at <= ?)
63
+ ORDER BY created_at ASC
64
+ LIMIT ?`)
65
+ .bind(now, Math.max(1, Math.min(100, Math.floor(limit))))
66
+ .all();
67
+ return (rows.results ?? []).map(rowToJob);
68
+ }
69
+ async claim(jobId) {
70
+ const current = await this.get(jobId);
71
+ if (!current || current.status === "succeeded" || current.status === "failed")
72
+ return null;
73
+ if (current.status === "queued" && isFutureIso(current.availableAt))
74
+ return null;
75
+ if (current.attemptCount >= current.maxAttempts) {
76
+ await this.fail(jobId, "Job exhausted all attempts.");
77
+ return null;
78
+ }
79
+ const now = nowIso();
80
+ const result = await this.db
81
+ .prepare(`UPDATE ${this.tableName}
82
+ SET status = 'running',
83
+ attempt_count = attempt_count + 1,
84
+ started_at = COALESCE(started_at, ?),
85
+ updated_at = ?,
86
+ last_error = NULL
87
+ WHERE job_id = ?
88
+ AND status IN ('queued', 'running')
89
+ AND (available_at IS NULL OR available_at <= ?)`)
90
+ .bind(now, now, jobId, now)
91
+ .run();
92
+ if (!Number(result.meta.changes ?? 0))
93
+ return null;
94
+ return this.get(jobId);
95
+ }
96
+ async succeed(jobId, result = null) {
97
+ const now = nowIso();
98
+ await this.db
99
+ .prepare(`UPDATE ${this.tableName}
100
+ SET status = 'succeeded', result_json = ?, completed_at = ?, updated_at = ?
101
+ WHERE job_id = ?`)
102
+ .bind(stringifyJsonColumn(result), now, now, jobId)
103
+ .run();
104
+ }
105
+ async requeue(jobId, result = null, availableAt = null) {
106
+ const now = nowIso();
107
+ await this.db
108
+ .prepare(`UPDATE ${this.tableName}
109
+ SET status = 'queued', result_json = ?, available_at = ?, updated_at = ?
110
+ WHERE job_id = ?`)
111
+ .bind(stringifyJsonColumn(result), availableAt, now, jobId)
112
+ .run();
113
+ }
114
+ async fail(jobId, error) {
115
+ const now = nowIso();
116
+ const message = error instanceof Error ? error.message : String(error);
117
+ await this.db
118
+ .prepare(`UPDATE ${this.tableName}
119
+ SET status = 'failed', last_error = ?, completed_at = ?, updated_at = ?
120
+ WHERE job_id = ?`)
121
+ .bind(message, now, now, jobId)
122
+ .run();
123
+ }
124
+ async run(jobId, handler) {
125
+ const job = await this.claim(jobId);
126
+ if (!job)
127
+ return { kind: "done", result: null };
128
+ try {
129
+ const output = await handler(job);
130
+ const normalized = normalizeJobResult(output);
131
+ if (normalized.kind === "requeue") {
132
+ await this.requeue(jobId, normalized.result ?? null, normalized.availableAt ?? null);
133
+ }
134
+ else {
135
+ await this.succeed(jobId, normalized.result ?? null);
136
+ }
137
+ return normalized;
138
+ }
139
+ catch (error) {
140
+ const latest = await this.get(jobId);
141
+ if (latest && latest.attemptCount < latest.maxAttempts) {
142
+ await this.requeue(jobId, { retryError: error instanceof Error ? error.message : String(error) });
143
+ return { kind: "requeue", result: null };
144
+ }
145
+ await this.fail(jobId, error);
146
+ throw error;
147
+ }
148
+ }
149
+ }
150
+ export const D1_JOBS_SCHEMA = `
151
+ CREATE TABLE IF NOT EXISTS jobs (
152
+ job_id TEXT PRIMARY KEY,
153
+ job_type TEXT NOT NULL,
154
+ status TEXT NOT NULL,
155
+ payload_json TEXT NOT NULL DEFAULT '{}',
156
+ result_json TEXT,
157
+ lock_key TEXT,
158
+ attempt_count INTEGER NOT NULL DEFAULT 0,
159
+ max_attempts INTEGER NOT NULL DEFAULT 3,
160
+ available_at TEXT,
161
+ started_at TEXT,
162
+ completed_at TEXT,
163
+ last_error TEXT,
164
+ created_at TEXT NOT NULL,
165
+ updated_at TEXT NOT NULL
166
+ );
167
+ CREATE INDEX IF NOT EXISTS jobs_status_available_idx ON jobs(status, available_at, created_at);
168
+ CREATE INDEX IF NOT EXISTS jobs_type_status_idx ON jobs(job_type, status, created_at);
169
+ CREATE UNIQUE INDEX IF NOT EXISTS jobs_active_lock_key_idx ON jobs(lock_key)
170
+ WHERE lock_key IS NOT NULL AND status IN ('queued', 'running');
171
+ `;
172
+ function rowToJob(row) {
173
+ return {
174
+ jobId: row.jobId,
175
+ jobType: row.jobType,
176
+ status: row.status,
177
+ payload: parseJsonColumn(row.payloadJson, {}),
178
+ result: parseJsonColumn(row.resultJson, null),
179
+ lockKey: row.lockKey,
180
+ attemptCount: Number(row.attemptCount),
181
+ maxAttempts: Number(row.maxAttempts),
182
+ availableAt: row.availableAt,
183
+ startedAt: row.startedAt,
184
+ completedAt: row.completedAt,
185
+ lastError: row.lastError,
186
+ createdAt: row.createdAt,
187
+ updatedAt: row.updatedAt,
188
+ };
189
+ }
190
+ function normalizeJobResult(output) {
191
+ if (output && typeof output === "object" && "kind" in output)
192
+ return output;
193
+ return { kind: "done", result: (output ?? null) };
194
+ }
195
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../src/jobs.ts"],"names":[],"mappings":"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"}
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ import type { ApiOperationRegistry } from "./api.js";
2
+ export type McpToolDescriptor = {
3
+ name: string;
4
+ title?: string;
5
+ description?: string;
6
+ inputSchema: Record<string, unknown>;
7
+ annotations?: Record<string, unknown>;
8
+ };
9
+ export declare function mcpToolsFromApiRegistry<TContext>(registry: ApiOperationRegistry<TContext>, options?: {
10
+ includeScopes?: boolean;
11
+ }): McpToolDescriptor[];
12
+ export declare function mcpWellKnownServerMetadata(options: {
13
+ name: string;
14
+ url: string;
15
+ description?: string;
16
+ authorizationServers?: string[];
17
+ }): Record<string, unknown>;
18
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF,wBAAgB,uBAAuB,CAAC,QAAQ,EAC9C,QAAQ,EAAE,oBAAoB,CAAC,QAAQ,CAAC,EACxC,OAAO,GAAE;IAAE,aAAa,CAAC,EAAE,OAAO,CAAA;CAAO,GACxC,iBAAiB,EAAE,CAQrB;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ1B"}
package/dist/mcp.js ADDED
@@ -0,0 +1,33 @@
1
+ export function mcpToolsFromApiRegistry(registry, options = {}) {
2
+ return Object.values(registry).map((operation) => ({
3
+ name: operation.name,
4
+ title: operation.title,
5
+ description: operation.description,
6
+ inputSchema: jsonSchemaPlaceholder(operation.path),
7
+ annotations: options.includeScopes && operation.scope ? { scope: operation.scope } : undefined,
8
+ }));
9
+ }
10
+ export function mcpWellKnownServerMetadata(options) {
11
+ return {
12
+ name: options.name,
13
+ description: options.description,
14
+ transport: "http",
15
+ url: options.url,
16
+ authorization_servers: options.authorizationServers,
17
+ };
18
+ }
19
+ function jsonSchemaPlaceholder(path) {
20
+ const properties = {};
21
+ const required = [];
22
+ for (const match of path.matchAll(/\{([A-Za-z_][A-Za-z0-9_]*)\}/g)) {
23
+ properties[match[1]] = { type: "string" };
24
+ required.push(match[1]);
25
+ }
26
+ return {
27
+ type: "object",
28
+ properties,
29
+ required,
30
+ additionalProperties: true,
31
+ };
32
+ }
33
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,uBAAuB,CACrC,QAAwC,EACxC,UAAuC,EAAE;IAEzC,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACjD,IAAI,EAAE,SAAS,CAAC,IAAI;QACpB,KAAK,EAAE,SAAS,CAAC,KAAK;QACtB,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,WAAW,EAAE,qBAAqB,CAAC,SAAS,CAAC,IAAI,CAAC;QAClD,WAAW,EAAE,OAAO,CAAC,aAAa,IAAI,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;KAC/F,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,OAK1C;IACC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,SAAS,EAAE,MAAM;QACjB,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,qBAAqB,EAAE,OAAO,CAAC,oBAAoB;KACpD,CAAC;AACJ,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY;IACzC,MAAM,UAAU,GAA4B,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,QAAQ,CAAC,+BAA+B,CAAC,EAAE,CAAC;QACnE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;QAC1C,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,UAAU;QACV,QAAQ;QACR,oBAAoB,EAAE,IAAI;KAC3B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ export type OAuthMetadataOptions = {
2
+ issuer: string;
3
+ authorizationPath?: string;
4
+ tokenPath?: string;
5
+ registrationPath?: string;
6
+ revocationPath?: string;
7
+ scopes?: string[];
8
+ resourceDocumentation?: string;
9
+ };
10
+ export declare function oauthAuthorizationServerMetadata(options: OAuthMetadataOptions): Record<string, unknown>;
11
+ export declare function oauthProtectedResourceMetadata(resource: string, authorizationServer: string, scopes?: string[]): Record<string, unknown>;
12
+ export declare function mcpServerCard(options: {
13
+ name: string;
14
+ description?: string;
15
+ url: string;
16
+ }): Record<string, unknown>;
17
+ //# sourceMappingURL=oauth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC,CAAC;AAEF,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAevG;AAED,wBAAgB,8BAA8B,CAAC,QAAQ,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOxI;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAOnH"}
package/dist/oauth.js ADDED
@@ -0,0 +1,33 @@
1
+ export function oauthAuthorizationServerMetadata(options) {
2
+ const issuer = options.issuer.replace(/\/$/, "");
3
+ return {
4
+ issuer,
5
+ authorization_endpoint: `${issuer}${options.authorizationPath ?? "/authorize"}`,
6
+ token_endpoint: `${issuer}${options.tokenPath ?? "/token"}`,
7
+ registration_endpoint: `${issuer}${options.registrationPath ?? "/register"}`,
8
+ revocation_endpoint: `${issuer}${options.revocationPath ?? "/revoke"}`,
9
+ response_types_supported: ["code"],
10
+ grant_types_supported: ["authorization_code", "refresh_token"],
11
+ token_endpoint_auth_methods_supported: ["client_secret_post", "none"],
12
+ code_challenge_methods_supported: ["S256"],
13
+ scopes_supported: options.scopes ?? ["mcp:read", "mcp:write"],
14
+ resource_documentation: options.resourceDocumentation ?? `${issuer}/mcp`,
15
+ };
16
+ }
17
+ export function oauthProtectedResourceMetadata(resource, authorizationServer, scopes) {
18
+ return {
19
+ resource,
20
+ authorization_servers: [authorizationServer.replace(/\/$/, "")],
21
+ scopes_supported: scopes ?? ["mcp:read", "mcp:write"],
22
+ bearer_methods_supported: ["header"],
23
+ };
24
+ }
25
+ export function mcpServerCard(options) {
26
+ return {
27
+ name: options.name,
28
+ description: options.description,
29
+ url: options.url,
30
+ transport: "http",
31
+ };
32
+ }
33
+ //# sourceMappingURL=oauth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAUA,MAAM,UAAU,gCAAgC,CAAC,OAA6B;IAC5E,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO;QACL,MAAM;QACN,sBAAsB,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,iBAAiB,IAAI,YAAY,EAAE;QAC/E,cAAc,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,SAAS,IAAI,QAAQ,EAAE;QAC3D,qBAAqB,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,gBAAgB,IAAI,WAAW,EAAE;QAC5E,mBAAmB,EAAE,GAAG,MAAM,GAAG,OAAO,CAAC,cAAc,IAAI,SAAS,EAAE;QACtE,wBAAwB,EAAE,CAAC,MAAM,CAAC;QAClC,qBAAqB,EAAE,CAAC,oBAAoB,EAAE,eAAe,CAAC;QAC9D,qCAAqC,EAAE,CAAC,oBAAoB,EAAE,MAAM,CAAC;QACrE,gCAAgC,EAAE,CAAC,MAAM,CAAC;QAC1C,gBAAgB,EAAE,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;QAC7D,sBAAsB,EAAE,OAAO,CAAC,qBAAqB,IAAI,GAAG,MAAM,MAAM;KACzE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,8BAA8B,CAAC,QAAgB,EAAE,mBAA2B,EAAE,MAAiB;IAC7G,OAAO;QACL,QAAQ;QACR,qBAAqB,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC/D,gBAAgB,EAAE,MAAM,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC;QACrD,wBAAwB,EAAE,CAAC,QAAQ,CAAC;KACrC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAA4D;IACxF,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,GAAG,EAAE,OAAO,CAAC,GAAG;QAChB,SAAS,EAAE,MAAM;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,25 @@
1
+ import type { D1DatabaseLike } from "./d1.js";
2
+ export type OpsSeverity = "debug" | "info" | "warn" | "error";
3
+ export type OpsEventInput = {
4
+ eventType: string;
5
+ severity?: OpsSeverity;
6
+ source: string;
7
+ fingerprint?: string | null;
8
+ payload?: unknown;
9
+ };
10
+ export type OpsEventRow = {
11
+ id: number;
12
+ event_type: string;
13
+ severity: OpsSeverity;
14
+ source: string;
15
+ fingerprint: string | null;
16
+ payload_json: string;
17
+ created_at: string;
18
+ };
19
+ export declare function recordOpsEvent(db: D1DatabaseLike, input: OpsEventInput): Promise<void>;
20
+ export declare function listRecentOpsEvents(db: D1DatabaseLike, options?: {
21
+ limit?: number;
22
+ eventType?: string | null;
23
+ }): Promise<OpsEventRow[]>;
24
+ export declare const D1_OPS_EVENTS_SCHEMA = "\nCREATE TABLE IF NOT EXISTS ops_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_type TEXT NOT NULL,\n severity TEXT NOT NULL DEFAULT 'info',\n source TEXT NOT NULL,\n fingerprint TEXT,\n payload_json TEXT NOT NULL DEFAULT '{}',\n created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP\n);\nCREATE INDEX IF NOT EXISTS ops_events_created_at_idx ON ops_events(created_at DESC);\nCREATE INDEX IF NOT EXISTS ops_events_type_created_idx ON ops_events(event_type, created_at DESC);\nCREATE INDEX IF NOT EXISTS ops_events_severity_created_idx ON ops_events(severity, created_at DESC);\n";
25
+ //# sourceMappingURL=ops-events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ops-events.d.ts","sourceRoot":"","sources":["../src/ops-events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAG9C,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9D,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,WAAW,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,WAAW,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,wBAAsB,cAAc,CAAC,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ5F;AAED,wBAAsB,mBAAmB,CACvC,EAAE,EAAE,cAAc,EAClB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAO,GAC1D,OAAO,CAAC,WAAW,EAAE,CAAC,CAuBxB;AAED,eAAO,MAAM,oBAAoB,olBAahC,CAAC"}