@sourcepress/server 0.1.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.
Files changed (184) hide show
  1. package/.omc/state/agent-replay-31d84b63-606a-4368-b9e6-93fe4f5ae0f7.jsonl +2 -0
  2. package/.omc/state/last-tool-error.json +7 -0
  3. package/.omc/state/mission-state.json +53 -0
  4. package/.omc/state/subagent-tracking.json +17 -0
  5. package/.turbo/turbo-build.log +4 -0
  6. package/.turbo/turbo-test.log +26 -0
  7. package/dist/__tests__/app-integration.test.d.ts +2 -0
  8. package/dist/__tests__/app-integration.test.d.ts.map +1 -0
  9. package/dist/__tests__/app-integration.test.js +71 -0
  10. package/dist/__tests__/app-integration.test.js.map +1 -0
  11. package/dist/__tests__/approval.test.d.ts +2 -0
  12. package/dist/__tests__/approval.test.d.ts.map +1 -0
  13. package/dist/__tests__/approval.test.js +170 -0
  14. package/dist/__tests__/approval.test.js.map +1 -0
  15. package/dist/__tests__/content.test.d.ts +2 -0
  16. package/dist/__tests__/content.test.d.ts.map +1 -0
  17. package/dist/__tests__/content.test.js +187 -0
  18. package/dist/__tests__/content.test.js.map +1 -0
  19. package/dist/__tests__/engine.test.d.ts +2 -0
  20. package/dist/__tests__/engine.test.d.ts.map +1 -0
  21. package/dist/__tests__/engine.test.js +77 -0
  22. package/dist/__tests__/engine.test.js.map +1 -0
  23. package/dist/__tests__/eval.test.d.ts +2 -0
  24. package/dist/__tests__/eval.test.d.ts.map +1 -0
  25. package/dist/__tests__/eval.test.js +320 -0
  26. package/dist/__tests__/eval.test.js.map +1 -0
  27. package/dist/__tests__/graph.test.d.ts +2 -0
  28. package/dist/__tests__/graph.test.d.ts.map +1 -0
  29. package/dist/__tests__/graph.test.js +169 -0
  30. package/dist/__tests__/graph.test.js.map +1 -0
  31. package/dist/__tests__/health.test.d.ts +2 -0
  32. package/dist/__tests__/health.test.d.ts.map +1 -0
  33. package/dist/__tests__/health.test.js +56 -0
  34. package/dist/__tests__/health.test.js.map +1 -0
  35. package/dist/__tests__/import.test.d.ts +2 -0
  36. package/dist/__tests__/import.test.d.ts.map +1 -0
  37. package/dist/__tests__/import.test.js +138 -0
  38. package/dist/__tests__/import.test.js.map +1 -0
  39. package/dist/__tests__/intent.test.d.ts +2 -0
  40. package/dist/__tests__/intent.test.d.ts.map +1 -0
  41. package/dist/__tests__/intent.test.js +122 -0
  42. package/dist/__tests__/intent.test.js.map +1 -0
  43. package/dist/__tests__/jobs.test.d.ts +2 -0
  44. package/dist/__tests__/jobs.test.d.ts.map +1 -0
  45. package/dist/__tests__/jobs.test.js +96 -0
  46. package/dist/__tests__/jobs.test.js.map +1 -0
  47. package/dist/__tests__/knowledge.test.d.ts +2 -0
  48. package/dist/__tests__/knowledge.test.d.ts.map +1 -0
  49. package/dist/__tests__/knowledge.test.js +110 -0
  50. package/dist/__tests__/knowledge.test.js.map +1 -0
  51. package/dist/__tests__/media-routes.test.d.ts +2 -0
  52. package/dist/__tests__/media-routes.test.d.ts.map +1 -0
  53. package/dist/__tests__/media-routes.test.js +88 -0
  54. package/dist/__tests__/media-routes.test.js.map +1 -0
  55. package/dist/__tests__/schema.test.d.ts +2 -0
  56. package/dist/__tests__/schema.test.d.ts.map +1 -0
  57. package/dist/__tests__/schema.test.js +92 -0
  58. package/dist/__tests__/schema.test.js.map +1 -0
  59. package/dist/app.d.ts +7 -0
  60. package/dist/app.d.ts.map +1 -0
  61. package/dist/app.js +85 -0
  62. package/dist/app.js.map +1 -0
  63. package/dist/engine.d.ts +38 -0
  64. package/dist/engine.d.ts.map +1 -0
  65. package/dist/engine.js +106 -0
  66. package/dist/engine.js.map +1 -0
  67. package/dist/index.d.ts +8 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +9 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/middleware/auth.d.ts +17 -0
  72. package/dist/middleware/auth.d.ts.map +1 -0
  73. package/dist/middleware/auth.js +54 -0
  74. package/dist/middleware/auth.js.map +1 -0
  75. package/dist/middleware/cors.d.ts +2 -0
  76. package/dist/middleware/cors.d.ts.map +1 -0
  77. package/dist/middleware/cors.js +13 -0
  78. package/dist/middleware/cors.js.map +1 -0
  79. package/dist/middleware/error-handler.d.ts +24 -0
  80. package/dist/middleware/error-handler.d.ts.map +1 -0
  81. package/dist/middleware/error-handler.js +30 -0
  82. package/dist/middleware/error-handler.js.map +1 -0
  83. package/dist/middleware/index.d.ts +7 -0
  84. package/dist/middleware/index.d.ts.map +1 -0
  85. package/dist/middleware/index.js +5 -0
  86. package/dist/middleware/index.js.map +1 -0
  87. package/dist/middleware/rate-limit.d.ts +11 -0
  88. package/dist/middleware/rate-limit.d.ts.map +1 -0
  89. package/dist/middleware/rate-limit.js +26 -0
  90. package/dist/middleware/rate-limit.js.map +1 -0
  91. package/dist/middleware/route-error-handler.d.ts +12 -0
  92. package/dist/middleware/route-error-handler.d.ts.map +1 -0
  93. package/dist/middleware/route-error-handler.js +9 -0
  94. package/dist/middleware/route-error-handler.js.map +1 -0
  95. package/dist/routes/approval.d.ts +4 -0
  96. package/dist/routes/approval.d.ts.map +1 -0
  97. package/dist/routes/approval.js +70 -0
  98. package/dist/routes/approval.js.map +1 -0
  99. package/dist/routes/content.d.ts +4 -0
  100. package/dist/routes/content.d.ts.map +1 -0
  101. package/dist/routes/content.js +145 -0
  102. package/dist/routes/content.js.map +1 -0
  103. package/dist/routes/eval.d.ts +4 -0
  104. package/dist/routes/eval.d.ts.map +1 -0
  105. package/dist/routes/eval.js +178 -0
  106. package/dist/routes/eval.js.map +1 -0
  107. package/dist/routes/graph.d.ts +4 -0
  108. package/dist/routes/graph.d.ts.map +1 -0
  109. package/dist/routes/graph.js +90 -0
  110. package/dist/routes/graph.js.map +1 -0
  111. package/dist/routes/health.d.ts +13 -0
  112. package/dist/routes/health.d.ts.map +1 -0
  113. package/dist/routes/health.js +19 -0
  114. package/dist/routes/health.js.map +1 -0
  115. package/dist/routes/import.d.ts +4 -0
  116. package/dist/routes/import.d.ts.map +1 -0
  117. package/dist/routes/import.js +85 -0
  118. package/dist/routes/import.js.map +1 -0
  119. package/dist/routes/index.d.ts +12 -0
  120. package/dist/routes/index.d.ts.map +1 -0
  121. package/dist/routes/index.js +12 -0
  122. package/dist/routes/index.js.map +1 -0
  123. package/dist/routes/intent.d.ts +4 -0
  124. package/dist/routes/intent.d.ts.map +1 -0
  125. package/dist/routes/intent.js +80 -0
  126. package/dist/routes/intent.js.map +1 -0
  127. package/dist/routes/jobs.d.ts +4 -0
  128. package/dist/routes/jobs.d.ts.map +1 -0
  129. package/dist/routes/jobs.js +67 -0
  130. package/dist/routes/jobs.js.map +1 -0
  131. package/dist/routes/knowledge.d.ts +4 -0
  132. package/dist/routes/knowledge.d.ts.map +1 -0
  133. package/dist/routes/knowledge.js +48 -0
  134. package/dist/routes/knowledge.js.map +1 -0
  135. package/dist/routes/media.d.ts +4 -0
  136. package/dist/routes/media.d.ts.map +1 -0
  137. package/dist/routes/media.js +87 -0
  138. package/dist/routes/media.js.map +1 -0
  139. package/dist/routes/schema.d.ts +4 -0
  140. package/dist/routes/schema.d.ts.map +1 -0
  141. package/dist/routes/schema.js +54 -0
  142. package/dist/routes/schema.js.map +1 -0
  143. package/dist/standalone.d.ts +2 -0
  144. package/dist/standalone.d.ts.map +1 -0
  145. package/dist/standalone.js +115 -0
  146. package/dist/standalone.js.map +1 -0
  147. package/package.json +36 -0
  148. package/src/__tests__/app-integration.test.ts +80 -0
  149. package/src/__tests__/approval.test.ts +195 -0
  150. package/src/__tests__/content.test.ts +202 -0
  151. package/src/__tests__/engine.test.ts +86 -0
  152. package/src/__tests__/eval.test.ts +343 -0
  153. package/src/__tests__/graph.test.ts +182 -0
  154. package/src/__tests__/health.test.ts +68 -0
  155. package/src/__tests__/import.test.ts +148 -0
  156. package/src/__tests__/intent.test.ts +133 -0
  157. package/src/__tests__/jobs.test.ts +107 -0
  158. package/src/__tests__/knowledge.test.ts +121 -0
  159. package/src/__tests__/media-routes.test.ts +109 -0
  160. package/src/__tests__/schema.test.ts +100 -0
  161. package/src/app.ts +92 -0
  162. package/src/engine.ts +168 -0
  163. package/src/index.ts +31 -0
  164. package/src/middleware/auth.ts +66 -0
  165. package/src/middleware/cors.ts +15 -0
  166. package/src/middleware/error-handler.ts +42 -0
  167. package/src/middleware/index.ts +6 -0
  168. package/src/middleware/rate-limit.ts +27 -0
  169. package/src/middleware/route-error-handler.ts +13 -0
  170. package/src/routes/approval.ts +90 -0
  171. package/src/routes/content.ts +256 -0
  172. package/src/routes/eval.ts +262 -0
  173. package/src/routes/graph.ts +111 -0
  174. package/src/routes/health.ts +33 -0
  175. package/src/routes/import.ts +122 -0
  176. package/src/routes/index.ts +11 -0
  177. package/src/routes/intent.ts +105 -0
  178. package/src/routes/jobs.ts +84 -0
  179. package/src/routes/knowledge.ts +73 -0
  180. package/src/routes/media.ts +117 -0
  181. package/src/routes/schema.ts +75 -0
  182. package/src/standalone.ts +130 -0
  183. package/tsconfig.json +8 -0
  184. package/vitest.config.ts +7 -0
@@ -0,0 +1,88 @@
1
+ import { Hono } from "hono";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { mediaRoutes } from "../routes/media.js";
4
+ const sampleRef = {
5
+ path: "assets/hero.webp",
6
+ content_type: "image/webp",
7
+ size_bytes: 50000,
8
+ hash: "abc123",
9
+ source: "uploaded",
10
+ uploaded_at: "2026-04-04T10:00:00Z",
11
+ uploaded_by: "test-user",
12
+ alt: "Hero image",
13
+ };
14
+ function createMockMedia() {
15
+ return {
16
+ upload: vi.fn().mockResolvedValue(sampleRef),
17
+ get: vi.fn().mockResolvedValue(Buffer.from("data")),
18
+ delete: vi.fn().mockResolvedValue(undefined),
19
+ list: vi.fn().mockResolvedValue([sampleRef]),
20
+ getMeta: vi.fn().mockResolvedValue(sampleRef),
21
+ updateMeta: vi.fn().mockResolvedValue({ ...sampleRef, alt: "Updated" }),
22
+ };
23
+ }
24
+ function createApp(media) {
25
+ const engine = { media };
26
+ const app = new Hono().basePath("/api");
27
+ app.route("/", mediaRoutes(engine));
28
+ return app;
29
+ }
30
+ describe("media routes", () => {
31
+ it("GET /api/media — lists media", async () => {
32
+ const media = createMockMedia();
33
+ const app = createApp(media);
34
+ const res = await app.request("/api/media");
35
+ expect(res.status).toBe(200);
36
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
37
+ const body = (await res.json());
38
+ expect(body.items).toHaveLength(1);
39
+ expect(body.items[0].path).toBe("assets/hero.webp");
40
+ });
41
+ it("GET /api/media/:path — returns metadata", async () => {
42
+ const media = createMockMedia();
43
+ const app = createApp(media);
44
+ const res = await app.request("/api/media/assets/hero.webp");
45
+ expect(res.status).toBe(200);
46
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
47
+ const body = (await res.json());
48
+ expect(body.path).toBe("assets/hero.webp");
49
+ expect(body.alt).toBe("Hero image");
50
+ });
51
+ it("GET /api/media/:path — 404 for missing file", async () => {
52
+ const media = createMockMedia();
53
+ media.getMeta.mockResolvedValueOnce(null);
54
+ const app = createApp(media);
55
+ const res = await app.request("/api/media/assets/missing.webp");
56
+ expect(res.status).toBe(404);
57
+ });
58
+ it("PUT /api/media/:path — updates metadata", async () => {
59
+ const media = createMockMedia();
60
+ const app = createApp(media);
61
+ const res = await app.request("/api/media/assets/hero.webp", {
62
+ method: "PUT",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({ alt: "Updated" }),
65
+ });
66
+ expect(res.status).toBe(200);
67
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
68
+ const body = (await res.json());
69
+ expect(body.alt).toBe("Updated");
70
+ });
71
+ it("DELETE /api/media/:path — deletes file", async () => {
72
+ const media = createMockMedia();
73
+ const app = createApp(media);
74
+ const res = await app.request("/api/media/assets/hero.webp", {
75
+ method: "DELETE",
76
+ });
77
+ expect(res.status).toBe(200);
78
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
79
+ const body = (await res.json());
80
+ expect(body.deleted).toBe(true);
81
+ });
82
+ it("returns 501 when media is not configured", async () => {
83
+ const app = createApp(undefined);
84
+ const res = await app.request("/api/media");
85
+ expect(res.status).toBe(501);
86
+ });
87
+ });
88
+ //# sourceMappingURL=media-routes.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media-routes.test.js","sourceRoot":"","sources":["../../src/__tests__/media-routes.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/schema.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ import { Hono } from "hono";
2
+ import { beforeEach, describe, expect, it, vi } from "vitest";
3
+ import { errorHandler } from "../middleware/error-handler.js";
4
+ import { schemaRoutes } from "../routes/schema.js";
5
+ const mockCollections = {
6
+ posts: {
7
+ name: "Blog Posts",
8
+ path: "content/posts",
9
+ format: "mdx",
10
+ fields: {
11
+ title: { type: "string", required: true },
12
+ draft: { type: "boolean", default: true },
13
+ },
14
+ },
15
+ team: {
16
+ name: "Team",
17
+ path: "content/team",
18
+ format: "yaml",
19
+ fields: {
20
+ name: { type: "string", required: true },
21
+ role: { type: "string" },
22
+ },
23
+ },
24
+ };
25
+ function createMockEngine() {
26
+ return {
27
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
28
+ config: {},
29
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
30
+ github: {},
31
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
32
+ knowledge: {},
33
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
34
+ knowledgeStore: {},
35
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
36
+ cache: {},
37
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
38
+ budget: {},
39
+ // biome-ignore lint/suspicious/noExplicitAny: partial mock of EngineContext
40
+ provider: {},
41
+ listContent: vi.fn().mockResolvedValue([]),
42
+ getContent: vi.fn().mockResolvedValue(null),
43
+ getCollectionDef: vi.fn().mockImplementation((name) => {
44
+ // biome-ignore lint/suspicious/noExplicitAny: index access on typed const object
45
+ return mockCollections[name] ?? null;
46
+ }),
47
+ listCollections: vi.fn().mockReturnValue(["posts", "team"]),
48
+ };
49
+ }
50
+ function createTestApp(engine) {
51
+ const app = new Hono().basePath("/api");
52
+ app.use("*", errorHandler());
53
+ app.route("/", schemaRoutes(engine));
54
+ return app;
55
+ }
56
+ describe("Schema routes", () => {
57
+ let engine;
58
+ let app;
59
+ beforeEach(() => {
60
+ engine = createMockEngine();
61
+ app = createTestApp(engine);
62
+ });
63
+ describe("GET /api/schema", () => {
64
+ it("returns all collection schemas", async () => {
65
+ const res = await app.request("/api/schema");
66
+ expect(res.status).toBe(200);
67
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
68
+ const body = (await res.json());
69
+ expect(body.total).toBe(2);
70
+ expect(body.collections.posts.name).toBe("Blog Posts");
71
+ expect(body.collections.team.name).toBe("Team");
72
+ });
73
+ });
74
+ describe("GET /api/schema/:collection", () => {
75
+ it("returns schema for a valid collection", async () => {
76
+ const res = await app.request("/api/schema/posts");
77
+ expect(res.status).toBe(200);
78
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
79
+ const body = (await res.json());
80
+ expect(body.name).toBe("Blog Posts");
81
+ expect(body.fields.title.type).toBe("string");
82
+ });
83
+ it("returns 404 for unknown collection", async () => {
84
+ const res = await app.request("/api/schema/unknown");
85
+ expect(res.status).toBe(404);
86
+ // biome-ignore lint/suspicious/noExplicitAny: typed JSON response parsing in tests
87
+ const body = (await res.json());
88
+ expect(body.code).toBe("COLLECTION_NOT_FOUND");
89
+ });
90
+ });
91
+ });
92
+ //# sourceMappingURL=schema.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../../src/__tests__/schema.test.ts"],"names":[],"mappings":"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"}
package/dist/app.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { EngineContext } from "./engine.js";
2
+ /**
3
+ * Create a fully wired SourcePress API app.
4
+ * If no engine is provided, only health endpoint is available.
5
+ */
6
+ export declare function createApp(engine?: EngineContext, apiKeys?: string[]): import("hono/hono-base").HonoBase<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/api", "/api">;
7
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAejD;;;GAGG;AACH,wBAAgB,SAAS,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,sHAsEnE"}
package/dist/app.js ADDED
@@ -0,0 +1,85 @@
1
+ import { Hono } from "hono";
2
+ import { secureHeaders } from "hono/secure-headers";
3
+ import { authMiddleware, corsMiddleware, errorHandler, requireAuth } from "./middleware/index.js";
4
+ import { aiRateLimit, generalRateLimit } from "./middleware/rate-limit.js";
5
+ import { approvalRoutes } from "./routes/approval.js";
6
+ import { contentRoutes } from "./routes/content.js";
7
+ import { evalRoutes } from "./routes/eval.js";
8
+ import { graphRoutes } from "./routes/graph.js";
9
+ import { healthRoutes } from "./routes/health.js";
10
+ import { importRoutes } from "./routes/import.js";
11
+ import { intentRoutes } from "./routes/intent.js";
12
+ import { jobRoutes } from "./routes/jobs.js";
13
+ import { knowledgeRoutes } from "./routes/knowledge.js";
14
+ import { mediaRoutes } from "./routes/media.js";
15
+ import { schemaRoutes } from "./routes/schema.js";
16
+ /**
17
+ * Create a fully wired SourcePress API app.
18
+ * If no engine is provided, only health endpoint is available.
19
+ */
20
+ export function createApp(engine, apiKeys) {
21
+ const app = new Hono().basePath("/api");
22
+ // Global middleware
23
+ app.use("*", secureHeaders());
24
+ app.use("*", corsMiddleware());
25
+ app.use("*", errorHandler());
26
+ app.use("*", authMiddleware(apiKeys));
27
+ app.use("*", generalRateLimit());
28
+ // Tighter rate limits for AI-consuming endpoints
29
+ app.use("/eval/*", aiRateLimit());
30
+ app.use("/knowledge", aiRateLimit());
31
+ app.use("/knowledge/import/*", aiRateLimit());
32
+ app.use("/knowledge/import", aiRateLimit());
33
+ app.use("/graph/rebuild", aiRateLimit());
34
+ // Protect all write endpoints
35
+ app.use("/content/*", async (c, next) => {
36
+ if (c.req.method === "POST" || c.req.method === "PUT" || c.req.method === "DELETE") {
37
+ return requireAuth()(c, next);
38
+ }
39
+ await next();
40
+ });
41
+ app.use("/knowledge", async (c, next) => {
42
+ if (c.req.method === "POST") {
43
+ return requireAuth()(c, next);
44
+ }
45
+ await next();
46
+ });
47
+ app.use("/knowledge/import/*", requireAuth());
48
+ app.use("/knowledge/import", requireAuth());
49
+ app.use("/graph/rebuild", requireAuth());
50
+ app.use("/eval/*", async (c, next) => {
51
+ if (c.req.method === "POST" || c.req.method === "PUT") {
52
+ return requireAuth()(c, next);
53
+ }
54
+ await next();
55
+ });
56
+ app.use("/approval/*", async (c, next) => {
57
+ if (c.req.method === "POST" || c.req.method === "PUT" || c.req.method === "DELETE") {
58
+ return requireAuth()(c, next);
59
+ }
60
+ await next();
61
+ });
62
+ app.use("/media/*", async (c, next) => {
63
+ if (c.req.method === "POST" || c.req.method === "PUT" || c.req.method === "DELETE") {
64
+ return requireAuth()(c, next);
65
+ }
66
+ await next();
67
+ });
68
+ // Health is always available
69
+ app.route("/", healthRoutes());
70
+ // Engine-dependent routes
71
+ if (engine) {
72
+ app.route("/", contentRoutes(engine));
73
+ app.route("/", knowledgeRoutes(engine));
74
+ app.route("/", graphRoutes(engine));
75
+ app.route("/", schemaRoutes(engine));
76
+ app.route("/", intentRoutes(engine));
77
+ app.route("/", evalRoutes(engine));
78
+ app.route("/", mediaRoutes(engine));
79
+ app.route("/", jobRoutes(engine));
80
+ app.route("/", importRoutes(engine));
81
+ app.route("/", approvalRoutes(engine));
82
+ }
83
+ return app;
84
+ }
85
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { BudgetTracker } from "@sourcepress/ai";
2
+ import type { ResolvedProvider } from "@sourcepress/ai";
3
+ import type { CacheProvider } from "@sourcepress/cache";
4
+ import type { ApprovalProvider, CollectionDefinition, ContentFile, SourcePressConfig } from "@sourcepress/core";
5
+ import { GitHubClient } from "@sourcepress/github";
6
+ import type { JobProvider } from "@sourcepress/jobs";
7
+ import { KnowledgeEngine } from "@sourcepress/knowledge";
8
+ import type { KnowledgeStoreBackend } from "@sourcepress/knowledge";
9
+ import type { MediaStorage } from "@sourcepress/media";
10
+ export interface EngineContext {
11
+ config: SourcePressConfig;
12
+ github: GitHubClient;
13
+ knowledge: KnowledgeEngine;
14
+ knowledgeStore: KnowledgeStoreBackend;
15
+ cache: CacheProvider;
16
+ budget: BudgetTracker;
17
+ provider: ResolvedProvider;
18
+ media?: MediaStorage;
19
+ jobs?: JobProvider;
20
+ approval?: ApprovalProvider;
21
+ listContent(collection: string): Promise<ContentFile[]>;
22
+ getContent(collection: string, slug: string): Promise<ContentFile | null>;
23
+ getCollectionDef(collection: string): CollectionDefinition | null;
24
+ listCollections(): string[];
25
+ }
26
+ export declare function resolveApprovalRule(config: SourcePressConfig, collection: string, path: string): "pr" | "direct";
27
+ export interface CreateEngineOptions {
28
+ config: SourcePressConfig;
29
+ githubToken: string;
30
+ aiApiKey?: string;
31
+ apiKeys?: string[];
32
+ knowledgeStore?: KnowledgeStoreBackend;
33
+ cache?: CacheProvider;
34
+ media?: MediaStorage;
35
+ jobs?: JobProvider;
36
+ }
37
+ export declare function createEngine(options: CreateEngineOptions): Promise<EngineContext>;
38
+ //# sourceMappingURL=engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAmB,MAAM,iBAAiB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EACX,gBAAgB,EAChB,oBAAoB,EACpB,WAAW,EACX,iBAAiB,EACjB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACN,YAAY,EAKZ,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAyC,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAChG,OAAO,KAAK,EAAkB,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAEpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC7B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;IAC3B,cAAc,EAAE,qBAAqB,CAAC;IACtC,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,WAAW,CAAC;IACnB,QAAQ,CAAC,EAAE,gBAAgB,CAAC;IAG5B,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACxD,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1E,gBAAgB,CAAC,UAAU,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CAAC;IAClE,eAAe,IAAI,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,mBAAmB,CAClC,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,GACV,IAAI,GAAG,QAAQ,CAQjB;AAED,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,iBAAiB,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,IAAI,CAAC,EAAE,WAAW,CAAC;CACnB;AAED,wBAAsB,YAAY,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,aAAa,CAAC,CAkGvF"}
package/dist/engine.js ADDED
@@ -0,0 +1,106 @@
1
+ import { join } from "node:path";
2
+ import { BudgetTracker, resolveProvider } from "@sourcepress/ai";
3
+ import { MemoryCache } from "@sourcepress/cache";
4
+ import { GitHubClient, GitHubPRApprovalProvider, getContentFile, listContentFiles, } from "@sourcepress/github";
5
+ import { InProcessJobProvider } from "@sourcepress/jobs";
6
+ import { InMemoryKnowledgeStore, JsonFileStore, KnowledgeEngine } from "@sourcepress/knowledge";
7
+ import { GitMediaStorage } from "@sourcepress/media";
8
+ export function resolveApprovalRule(config, collection, path) {
9
+ if (!config.approval?.rules)
10
+ return "direct";
11
+ for (const [pattern, rule] of Object.entries(config.approval.rules)) {
12
+ if (path.startsWith(pattern.replace("/*", "/")) || path === pattern) {
13
+ return rule;
14
+ }
15
+ }
16
+ return "direct";
17
+ }
18
+ export async function createEngine(options) {
19
+ const { config, githubToken, aiApiKey } = options;
20
+ // GitHub client
21
+ const github = new GitHubClient({
22
+ owner: config.repository.owner,
23
+ repo: config.repository.repo,
24
+ branch: config.repository.branch,
25
+ token: githubToken,
26
+ });
27
+ // AI provider + budget
28
+ const provider = resolveProvider({
29
+ provider: config.ai.provider,
30
+ model: config.ai.model,
31
+ apiKey: aiApiKey,
32
+ });
33
+ const budget = new BudgetTracker({
34
+ daily_limit_usd: config.ai.daily_limit_usd ?? 5.0,
35
+ warn_at_usd: config.ai.warn_at_usd ?? 3.0,
36
+ });
37
+ // Knowledge store + engine
38
+ const knowledgeStore = options.knowledgeStore ??
39
+ (config.knowledge.graph.backend === "local"
40
+ ? new JsonFileStore(join(process.cwd(), ".sourcepress"))
41
+ : new InMemoryKnowledgeStore());
42
+ const knowledge = new KnowledgeEngine(knowledgeStore, provider, budget);
43
+ await knowledge.initialize();
44
+ // Cache
45
+ const cache = options.cache ?? new MemoryCache();
46
+ // Media storage (optional — only if configured)
47
+ let media;
48
+ if (config.media) {
49
+ media = options.media ?? new GitMediaStorage(github, config.media);
50
+ }
51
+ // Job provider (always available, default is in-process)
52
+ const jobs = options.jobs ?? new InProcessJobProvider();
53
+ // Approval provider (optional — only if configured)
54
+ let approval;
55
+ if (config.approval?.provider === "github-pr") {
56
+ approval = new GitHubPRApprovalProvider(github);
57
+ }
58
+ // Convenience methods
59
+ async function listContent(collection) {
60
+ const collDef = config.collections[collection];
61
+ if (!collDef)
62
+ return [];
63
+ const paths = await listContentFiles(github, collDef.path);
64
+ const files = [];
65
+ for (const path of paths) {
66
+ const file = await getContentFile(github, path, collection);
67
+ if (file)
68
+ files.push(file);
69
+ }
70
+ return files;
71
+ }
72
+ async function getContent(collection, slug) {
73
+ const collDef = config.collections[collection];
74
+ if (!collDef)
75
+ return null;
76
+ if (!/^[a-z0-9-]+$/.test(slug))
77
+ return null;
78
+ const ext = collDef.format === "yaml" ? "yaml" : collDef.format === "json" ? "json" : collDef.format;
79
+ const basePath = collDef.path.replace(/\/+$/, "");
80
+ const path = `${basePath}/${slug}.${ext}`;
81
+ return getContentFile(github, path, collection);
82
+ }
83
+ function getCollectionDef(collection) {
84
+ return config.collections[collection] ?? null;
85
+ }
86
+ function listCollections() {
87
+ return Object.keys(config.collections);
88
+ }
89
+ return {
90
+ config,
91
+ github,
92
+ knowledge,
93
+ knowledgeStore,
94
+ cache,
95
+ budget,
96
+ provider,
97
+ media,
98
+ jobs,
99
+ approval,
100
+ listContent,
101
+ getContent,
102
+ getCollectionDef,
103
+ listCollections,
104
+ };
105
+ }
106
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export { createApp } from "./app.js";
2
+ export { createEngine, resolveApprovalRule } from "./engine.js";
3
+ export type { EngineContext, CreateEngineOptions } from "./engine.js";
4
+ export { approvalRoutes, healthRoutes, contentRoutes, knowledgeRoutes, graphRoutes, schemaRoutes, intentRoutes, evalRoutes, mediaRoutes, jobRoutes, importRoutes, } from "./routes/index.js";
5
+ export type { HealthStatus } from "./routes/health.js";
6
+ export { corsMiddleware, errorHandler, authMiddleware, SourcePressError, } from "./middleware/index.js";
7
+ export type { ApiError, AuthContext } from "./middleware/index.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAChE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGtE,OAAO,EACN,cAAc,EACd,YAAY,EACZ,aAAa,EACb,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,GACZ,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,EACN,cAAc,EACd,YAAY,EACZ,cAAc,EACd,gBAAgB,GAChB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // App factory
2
+ export { createApp } from "./app.js";
3
+ // Engine
4
+ export { createEngine, resolveApprovalRule } from "./engine.js";
5
+ // Routes
6
+ export { approvalRoutes, healthRoutes, contentRoutes, knowledgeRoutes, graphRoutes, schemaRoutes, intentRoutes, evalRoutes, mediaRoutes, jobRoutes, importRoutes, } from "./routes/index.js";
7
+ // Middleware
8
+ export { corsMiddleware, errorHandler, authMiddleware, SourcePressError, } from "./middleware/index.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc;AACd,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGhE,SAAS;AACT,OAAO,EACN,cAAc,EACd,YAAY,EACZ,aAAa,EACb,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,YAAY,GACZ,MAAM,mBAAmB,CAAC;AAG3B,aAAa;AACb,OAAO,EACN,cAAc,EACd,YAAY,EACZ,cAAc,EACd,gBAAgB,GAChB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Context, Next } from "hono";
2
+ export interface AuthContext {
3
+ authenticated: boolean;
4
+ user?: string;
5
+ method?: "api-key" | "bearer" | "none";
6
+ }
7
+ export declare function authMiddleware(apiKeys?: string[]): (c: Context, next: Next) => Promise<void>;
8
+ /**
9
+ * Middleware that rejects unauthenticated requests with 401.
10
+ * Apply to write endpoints (POST, PUT, DELETE).
11
+ */
12
+ export declare function requireAuth(): (c: Context, next: Next) => Promise<(Response & import("hono").TypedResponse<{
13
+ status: number;
14
+ message: string;
15
+ code: string;
16
+ }, 401, "json">) | undefined>;
17
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,MAAM,WAAW,WAAW;IAC3B,aAAa,EAAE,OAAO,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;CACvC;AAaD,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,IAClC,GAAG,OAAO,EAAE,MAAM,IAAI,mBA8BpC;AAED;;;GAGG;AACH,wBAAgB,WAAW,KACZ,GAAG,OAAO,EAAE,MAAM,IAAI;;;;8BAOpC"}
@@ -0,0 +1,54 @@
1
+ import { timingSafeEqual } from "node:crypto";
2
+ function safeCompare(a, b) {
3
+ const aBuf = Buffer.from(a, "utf-8");
4
+ const bBuf = Buffer.from(b, "utf-8");
5
+ if (aBuf.length !== bBuf.length) {
6
+ // Still run comparison on equal-length buffers to avoid timing leak on length
7
+ timingSafeEqual(aBuf, aBuf);
8
+ return false;
9
+ }
10
+ return timingSafeEqual(aBuf, bBuf);
11
+ }
12
+ export function authMiddleware(apiKeys) {
13
+ return async (c, next) => {
14
+ const authHeader = c.req.header("Authorization");
15
+ const auth = {
16
+ authenticated: false,
17
+ method: "none",
18
+ };
19
+ if (authHeader?.startsWith("Bearer ") || authHeader?.startsWith("ApiKey ")) {
20
+ const scheme = authHeader.startsWith("Bearer ") ? "bearer" : "api-key";
21
+ const token = authHeader.slice(scheme === "bearer" ? 7 : 7);
22
+ if (!apiKeys || apiKeys.length === 0) {
23
+ // No keys configured — accept any token (warn once is gone; engine should configure keys)
24
+ auth.authenticated = true;
25
+ auth.method = scheme;
26
+ auth.user = "anonymous";
27
+ }
28
+ else {
29
+ const matched = apiKeys.some((key) => safeCompare(token, key));
30
+ if (matched) {
31
+ auth.authenticated = true;
32
+ auth.method = scheme;
33
+ auth.user = "api-client";
34
+ }
35
+ }
36
+ }
37
+ c.set("auth", auth);
38
+ await next();
39
+ };
40
+ }
41
+ /**
42
+ * Middleware that rejects unauthenticated requests with 401.
43
+ * Apply to write endpoints (POST, PUT, DELETE).
44
+ */
45
+ export function requireAuth() {
46
+ return async (c, next) => {
47
+ const auth = c.get("auth");
48
+ if (!auth?.authenticated) {
49
+ return c.json({ status: 401, message: "Unauthorized", code: "UNAUTHORIZED" }, 401);
50
+ }
51
+ await next();
52
+ };
53
+ }
54
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/middleware/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAS9C,SAAS,WAAW,CAAC,CAAS,EAAE,CAAS;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;QACjC,8EAA8E;QAC9E,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAkB;IAChD,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAAE,EAAE;QACvC,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QAEjD,MAAM,IAAI,GAAgB;YACzB,aAAa,EAAE,KAAK;YACpB,MAAM,EAAE,MAAM;SACd,CAAC;QAEF,IAAI,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,IAAI,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAC5E,MAAM,MAAM,GAAG,UAAU,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;YACvE,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAE5D,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACtC,0FAA0F;gBAC1F,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;gBAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;gBACrB,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACP,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;gBAC/D,IAAI,OAAO,EAAE,CAAC;oBACb,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;oBAC1B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;oBACrB,IAAI,CAAC,IAAI,GAAG,YAAY,CAAC;gBAC1B,CAAC;YACF,CAAC;QACF,CAAC;QAED,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpB,MAAM,IAAI,EAAE,CAAC;IACd,CAAC,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW;IAC1B,OAAO,KAAK,EAAE,CAAU,EAAE,IAAU,EAAE,EAAE;QACvC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAA4B,CAAC;QACtD,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC;YAC1B,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,GAAG,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,IAAI,EAAE,CAAC;IACd,CAAC,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function corsMiddleware(origins?: string | string[]): import("hono").MiddlewareHandler;
2
+ //# sourceMappingURL=cors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAKA,wBAAgB,cAAc,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,oCASzD"}
@@ -0,0 +1,13 @@
1
+ import { cors } from "hono/cors";
2
+ // Default to localhost only when no origins are configured (deny-by-default in production)
3
+ const DEFAULT_ORIGINS = ["http://localhost:3000", "http://localhost:4321", "http://localhost:5173"];
4
+ export function corsMiddleware(origins) {
5
+ const origin = origins ?? DEFAULT_ORIGINS;
6
+ return cors({
7
+ origin,
8
+ allowMethods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"],
9
+ allowHeaders: ["Content-Type", "Authorization"],
10
+ maxAge: 86400,
11
+ });
12
+ }
13
+ //# sourceMappingURL=cors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/middleware/cors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,2FAA2F;AAC3F,MAAM,eAAe,GAAG,CAAC,uBAAuB,EAAE,uBAAuB,EAAE,uBAAuB,CAAC,CAAC;AAEpG,MAAM,UAAU,cAAc,CAAC,OAA2B;IACzD,MAAM,MAAM,GAAG,OAAO,IAAI,eAAe,CAAC;IAE1C,OAAO,IAAI,CAAC;QACX,MAAM;QACN,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC;QACzD,YAAY,EAAE,CAAC,cAAc,EAAE,eAAe,CAAC;QAC/C,MAAM,EAAE,KAAK;KACb,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Context, Next } from "hono";
2
+ export interface ApiError {
3
+ status: number;
4
+ message: string;
5
+ code: string;
6
+ details?: unknown;
7
+ }
8
+ export declare class SourcePressError extends Error {
9
+ status: number;
10
+ code: string;
11
+ details?: unknown;
12
+ constructor(status: number, code: string, message: string, details?: unknown);
13
+ }
14
+ export declare function errorHandler(): (c: Context, next: Next) => Promise<(Response & import("hono").TypedResponse<{
15
+ status: number;
16
+ message: string;
17
+ code: string;
18
+ }, 500, "json">) | (Response & import("hono").TypedResponse<{
19
+ status: number;
20
+ message: string;
21
+ code: string;
22
+ details?: import("hono/utils/types").JSONValue | undefined;
23
+ }, import("hono/utils/http-status").ContentfulStatusCode, "json">) | undefined>;
24
+ //# sourceMappingURL=error-handler.d.ts.map