@reaatech/prompt-version-control-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 (136) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/LICENSE +21 -0
  3. package/README.md +261 -0
  4. package/dist/api/routes/deployments.d.ts +4 -0
  5. package/dist/api/routes/deployments.d.ts.map +1 -0
  6. package/dist/api/routes/deployments.js +48 -0
  7. package/dist/api/routes/deployments.js.map +1 -0
  8. package/dist/api/routes/docs.d.ts +4 -0
  9. package/dist/api/routes/docs.d.ts.map +1 -0
  10. package/dist/api/routes/docs.js +75 -0
  11. package/dist/api/routes/docs.js.map +1 -0
  12. package/dist/api/routes/evaluations.d.ts +4 -0
  13. package/dist/api/routes/evaluations.d.ts.map +1 -0
  14. package/dist/api/routes/evaluations.js +63 -0
  15. package/dist/api/routes/evaluations.js.map +1 -0
  16. package/dist/api/routes/metrics.d.ts +4 -0
  17. package/dist/api/routes/metrics.d.ts.map +1 -0
  18. package/dist/api/routes/metrics.js +38 -0
  19. package/dist/api/routes/metrics.js.map +1 -0
  20. package/dist/api/routes/promotions.d.ts +4 -0
  21. package/dist/api/routes/promotions.d.ts.map +1 -0
  22. package/dist/api/routes/promotions.js +95 -0
  23. package/dist/api/routes/promotions.js.map +1 -0
  24. package/dist/api/routes/prompts.d.ts +4 -0
  25. package/dist/api/routes/prompts.d.ts.map +1 -0
  26. package/dist/api/routes/prompts.js +80 -0
  27. package/dist/api/routes/prompts.js.map +1 -0
  28. package/dist/api/routes/render.d.ts +4 -0
  29. package/dist/api/routes/render.d.ts.map +1 -0
  30. package/dist/api/routes/render.js +44 -0
  31. package/dist/api/routes/render.js.map +1 -0
  32. package/dist/api/routes/tags.d.ts +4 -0
  33. package/dist/api/routes/tags.d.ts.map +1 -0
  34. package/dist/api/routes/tags.js +41 -0
  35. package/dist/api/routes/tags.js.map +1 -0
  36. package/dist/api/routes/webhooks.d.ts +4 -0
  37. package/dist/api/routes/webhooks.d.ts.map +1 -0
  38. package/dist/api/routes/webhooks.js +49 -0
  39. package/dist/api/routes/webhooks.js.map +1 -0
  40. package/dist/db/client.d.ts +3 -0
  41. package/dist/db/client.d.ts.map +1 -0
  42. package/dist/db/client.js +21 -0
  43. package/dist/db/client.js.map +1 -0
  44. package/dist/db/redis.d.ts +3 -0
  45. package/dist/db/redis.d.ts.map +1 -0
  46. package/dist/db/redis.js +18 -0
  47. package/dist/db/redis.js.map +1 -0
  48. package/dist/errors.d.ts +22 -0
  49. package/dist/errors.d.ts.map +1 -0
  50. package/dist/errors.js +39 -0
  51. package/dist/errors.js.map +1 -0
  52. package/dist/index.d.ts +4 -0
  53. package/dist/index.d.ts.map +1 -0
  54. package/dist/index.js +83 -0
  55. package/dist/index.js.map +1 -0
  56. package/dist/middleware/audit.d.ts +3 -0
  57. package/dist/middleware/audit.d.ts.map +1 -0
  58. package/dist/middleware/audit.js +39 -0
  59. package/dist/middleware/audit.js.map +1 -0
  60. package/dist/middleware/auth.d.ts +3 -0
  61. package/dist/middleware/auth.d.ts.map +1 -0
  62. package/dist/middleware/auth.js +49 -0
  63. package/dist/middleware/auth.js.map +1 -0
  64. package/dist/middleware/error-handler.d.ts +3 -0
  65. package/dist/middleware/error-handler.d.ts.map +1 -0
  66. package/dist/middleware/error-handler.js +36 -0
  67. package/dist/middleware/error-handler.js.map +1 -0
  68. package/dist/middleware/metrics.d.ts +3 -0
  69. package/dist/middleware/metrics.d.ts.map +1 -0
  70. package/dist/middleware/metrics.js +13 -0
  71. package/dist/middleware/metrics.js.map +1 -0
  72. package/dist/middleware/rate-limit.d.ts +8 -0
  73. package/dist/middleware/rate-limit.d.ts.map +1 -0
  74. package/dist/middleware/rate-limit.js +89 -0
  75. package/dist/middleware/rate-limit.js.map +1 -0
  76. package/dist/middleware/request-id.d.ts +3 -0
  77. package/dist/middleware/request-id.d.ts.map +1 -0
  78. package/dist/middleware/request-id.js +10 -0
  79. package/dist/middleware/request-id.js.map +1 -0
  80. package/dist/services/audit.service.d.ts +6 -0
  81. package/dist/services/audit.service.d.ts.map +1 -0
  82. package/dist/services/audit.service.js +26 -0
  83. package/dist/services/audit.service.js.map +1 -0
  84. package/dist/services/deployment.service.d.ts +101 -0
  85. package/dist/services/deployment.service.d.ts.map +1 -0
  86. package/dist/services/deployment.service.js +127 -0
  87. package/dist/services/deployment.service.js.map +1 -0
  88. package/dist/services/diff.engine.d.ts +13 -0
  89. package/dist/services/diff.engine.d.ts.map +1 -0
  90. package/dist/services/diff.engine.js +101 -0
  91. package/dist/services/diff.engine.js.map +1 -0
  92. package/dist/services/eval.service.d.ts +55 -0
  93. package/dist/services/eval.service.d.ts.map +1 -0
  94. package/dist/services/eval.service.js +151 -0
  95. package/dist/services/eval.service.js.map +1 -0
  96. package/dist/services/event.bus.d.ts +18 -0
  97. package/dist/services/event.bus.d.ts.map +1 -0
  98. package/dist/services/event.bus.js +35 -0
  99. package/dist/services/event.bus.js.map +1 -0
  100. package/dist/services/metric.service.d.ts +33 -0
  101. package/dist/services/metric.service.d.ts.map +1 -0
  102. package/dist/services/metric.service.js +64 -0
  103. package/dist/services/metric.service.js.map +1 -0
  104. package/dist/services/prometheus.service.d.ts +7 -0
  105. package/dist/services/prometheus.service.d.ts.map +1 -0
  106. package/dist/services/prometheus.service.js +27 -0
  107. package/dist/services/prometheus.service.js.map +1 -0
  108. package/dist/services/prompt.service.d.ts +59 -0
  109. package/dist/services/prompt.service.d.ts.map +1 -0
  110. package/dist/services/prompt.service.js +144 -0
  111. package/dist/services/prompt.service.js.map +1 -0
  112. package/dist/services/tag.service.d.ts +46 -0
  113. package/dist/services/tag.service.d.ts.map +1 -0
  114. package/dist/services/tag.service.js +84 -0
  115. package/dist/services/tag.service.js.map +1 -0
  116. package/dist/services/webhook.service.d.ts +50 -0
  117. package/dist/services/webhook.service.d.ts.map +1 -0
  118. package/dist/services/webhook.service.js +196 -0
  119. package/dist/services/webhook.service.js.map +1 -0
  120. package/dist/types/hono.d.ts +10 -0
  121. package/dist/types/hono.d.ts.map +1 -0
  122. package/dist/types/hono.js +2 -0
  123. package/dist/types/hono.js.map +1 -0
  124. package/dist/utils/context.d.ts +3 -0
  125. package/dist/utils/context.d.ts.map +1 -0
  126. package/dist/utils/context.js +9 -0
  127. package/dist/utils/context.js.map +1 -0
  128. package/dist/utils/logger.d.ts +3 -0
  129. package/dist/utils/logger.d.ts.map +1 -0
  130. package/dist/utils/logger.js +20 -0
  131. package/dist/utils/logger.js.map +1 -0
  132. package/dist/utils/pagination.d.ts +10 -0
  133. package/dist/utils/pagination.d.ts.map +1 -0
  134. package/dist/utils/pagination.js +10 -0
  135. package/dist/utils/pagination.js.map +1 -0
  136. package/package.json +74 -0
@@ -0,0 +1,95 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { Hono } from 'hono';
3
+ import { z } from 'zod';
4
+ import { prisma } from '../../db/client.js';
5
+ import { AppError, NotFoundError } from '../../errors.js';
6
+ import { auditMiddleware } from '../../middleware/audit.js';
7
+ import { authMiddleware } from '../../middleware/auth.js';
8
+ import { evalService } from '../../services/eval.service.js';
9
+ import { tagService } from '../../services/tag.service.js';
10
+ import { getProjectId } from '../../utils/context.js';
11
+ const router = new Hono();
12
+ router.use('*', authMiddleware);
13
+ router.post('/prompts/:id/promote', auditMiddleware('prompt', 'promote'), async (c) => {
14
+ const projectId = getProjectId(c);
15
+ const promptId = c.req.param('id');
16
+ let stagingTag;
17
+ try {
18
+ stagingTag = await tagService.getTag(projectId, promptId, 'staging');
19
+ }
20
+ catch (err) {
21
+ if (err instanceof NotFoundError) {
22
+ stagingTag = null;
23
+ }
24
+ else {
25
+ throw err;
26
+ }
27
+ }
28
+ if (!stagingTag) {
29
+ throw new AppError('NO_STAGING', 400, 'No staging version found for this prompt');
30
+ }
31
+ const gate = await evalService.getPromotionGateStatus(projectId, stagingTag.versionId);
32
+ if (!gate.canPromote) {
33
+ throw new AppError('PROMOTION_BLOCKED', 409, gate.reason || 'Promotion blocked by eval gate');
34
+ }
35
+ await tagService.moveTag(projectId, promptId, 'production', stagingTag.versionId);
36
+ return c.json({
37
+ promoted: true,
38
+ fromVersion: stagingTag.version.number,
39
+ reason: 'Eval gate passed',
40
+ });
41
+ });
42
+ const OverrideSchema = z.object({
43
+ versionId: z.string(),
44
+ reason: z.string().min(1),
45
+ });
46
+ router.post('/prompts/:id/promote/override', auditMiddleware('prompt', 'promote'), zValidator('json', OverrideSchema), async (c) => {
47
+ const projectId = getProjectId(c);
48
+ const promptId = c.req.param('id');
49
+ const body = c.req.valid('json');
50
+ await tagService.moveTag(projectId, promptId, 'production', body.versionId);
51
+ return c.json({
52
+ promoted: true,
53
+ versionId: body.versionId,
54
+ reason: body.reason,
55
+ overridden: true,
56
+ });
57
+ });
58
+ router.post('/prompts/:id/rollback', auditMiddleware('prompt', 'rollback'), async (c) => {
59
+ const projectId = getProjectId(c);
60
+ const promptId = c.req.param('id');
61
+ let prodTag;
62
+ try {
63
+ prodTag = await tagService.getTag(projectId, promptId, 'production');
64
+ }
65
+ catch (err) {
66
+ if (err instanceof NotFoundError) {
67
+ prodTag = null;
68
+ }
69
+ else {
70
+ throw err;
71
+ }
72
+ }
73
+ if (!prodTag) {
74
+ throw new AppError('NO_PRODUCTION', 400, 'No production version found');
75
+ }
76
+ const previousVersion = await prisma.version.findFirst({
77
+ where: {
78
+ promptId,
79
+ number: { lt: prodTag.version.number },
80
+ prompt: { projectId },
81
+ },
82
+ orderBy: { number: 'desc' },
83
+ });
84
+ if (!previousVersion) {
85
+ throw new AppError('NO_PREVIOUS', 400, 'No previous version to rollback to');
86
+ }
87
+ await tagService.moveTag(projectId, promptId, 'production', previousVersion.id);
88
+ return c.json({
89
+ rolledBack: true,
90
+ fromVersion: prodTag.version.number,
91
+ toVersion: previousVersion.number,
92
+ });
93
+ });
94
+ export { router as promotionRoutes };
95
+ //# sourceMappingURL=promotions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promotions.js","sourceRoot":"","sources":["../../../src/api/routes/promotions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ declare const router: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export { router as promptRoutes };
4
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/api/routes/prompts.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,QAAA,MAAM,MAAM,4EAAa,CAAC;AAgG1B,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,80 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { CreatePromptSchema, CreateVersionSchema, DiffRequestSchema, PaginationSchema, UpdatePromptSchema, } from '@reaatech/prompt-version-control-shared';
3
+ import { Hono } from 'hono';
4
+ import { auditMiddleware } from '../../middleware/audit.js';
5
+ import { authMiddleware } from '../../middleware/auth.js';
6
+ import { diffEngine } from '../../services/diff.engine.js';
7
+ import { promptService } from '../../services/prompt.service.js';
8
+ import { tagService } from '../../services/tag.service.js';
9
+ import { getProjectId } from '../../utils/context.js';
10
+ import { tagRoutes } from './tags.js';
11
+ const router = new Hono();
12
+ router.use('*', authMiddleware);
13
+ router.route('/:id/tags', tagRoutes);
14
+ router.get('/', zValidator('query', PaginationSchema), async (c) => {
15
+ const projectId = getProjectId(c);
16
+ const query = c.req.valid('query');
17
+ const result = await promptService.listPrompts(projectId, query);
18
+ return c.json(result);
19
+ });
20
+ router.post('/', auditMiddleware('prompt', 'create'), zValidator('json', CreatePromptSchema), async (c) => {
21
+ const projectId = getProjectId(c);
22
+ const body = c.req.valid('json');
23
+ const prompt = await promptService.createPrompt(projectId, body);
24
+ return c.json(prompt, 201);
25
+ });
26
+ router.get('/:id', async (c) => {
27
+ const projectId = getProjectId(c);
28
+ const id = c.req.param('id');
29
+ const prompt = await promptService.getPrompt(projectId, id);
30
+ return c.json(prompt);
31
+ });
32
+ router.put('/:id', auditMiddleware('prompt', 'update'), zValidator('json', UpdatePromptSchema), async (c) => {
33
+ const projectId = getProjectId(c);
34
+ const id = c.req.param('id');
35
+ const body = c.req.valid('json');
36
+ const prompt = await promptService.updatePrompt(projectId, id, body);
37
+ return c.json(prompt);
38
+ });
39
+ router.delete('/:id', auditMiddleware('prompt', 'delete'), async (c) => {
40
+ const projectId = getProjectId(c);
41
+ const id = c.req.param('id');
42
+ const prompt = await promptService.archivePrompt(projectId, id);
43
+ return c.json(prompt);
44
+ });
45
+ router.get('/:id/versions', zValidator('query', PaginationSchema), async (c) => {
46
+ const projectId = getProjectId(c);
47
+ const id = c.req.param('id');
48
+ const query = c.req.valid('query');
49
+ const result = await promptService.listVersions(projectId, id, query);
50
+ return c.json(result);
51
+ });
52
+ router.post('/:id/versions', auditMiddleware('version', 'create'), zValidator('json', CreateVersionSchema), async (c) => {
53
+ const projectId = getProjectId(c);
54
+ const id = c.req.param('id');
55
+ const body = c.req.valid('json');
56
+ const version = await promptService.createVersion(projectId, id, body);
57
+ return c.json(version, 201);
58
+ });
59
+ router.get('/:id/production', async (c) => {
60
+ const projectId = getProjectId(c);
61
+ const promptId = c.req.param('id');
62
+ const version = await tagService.getProductionVersion(projectId, promptId);
63
+ return c.json(version);
64
+ });
65
+ router.get('/:id/versions/:vid', async (c) => {
66
+ const projectId = getProjectId(c);
67
+ const promptId = c.req.param('id');
68
+ const versionId = c.req.param('vid');
69
+ const version = await promptService.getVersion(projectId, promptId, versionId);
70
+ return c.json(version);
71
+ });
72
+ router.get('/:id/diff', zValidator('query', DiffRequestSchema), async (c) => {
73
+ const projectId = getProjectId(c);
74
+ const promptId = c.req.param('id');
75
+ const query = c.req.valid('query');
76
+ const diff = await diffEngine.diff(projectId, promptId, query.fromVersion, query.toVersion);
77
+ return c.json(diff);
78
+ });
79
+ export { router as promptRoutes };
80
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/api/routes/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;AAE1B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AAEhC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAErC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACjE,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CACT,GAAG,EACH,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACnC,UAAU,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACtC,KAAK,EAAE,CAAC,EAAE,EAAE;IACV,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC7B,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC7B,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CACR,MAAM,EACN,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACnC,UAAU,CAAC,MAAM,EAAE,kBAAkB,CAAC,EACtC,KAAK,EAAE,CAAC,EAAE,EAAE;IACV,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACrE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACrE,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,OAAO,EAAE,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC7E,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC;IACtE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CACT,eAAe,EACf,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,EACpC,UAAU,CAAC,MAAM,EAAE,mBAAmB,CAAC,EACvC,KAAK,EAAE,CAAC,EAAE,EAAE;IACV,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;IACvE,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;AAC9B,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACxC,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,oBAAoB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAC3E,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,oBAAoB,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC3C,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,SAAS,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC/E,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;AACzB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,EAAE,iBAAiB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC1E,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5F,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ declare const router: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export { router as renderRoutes };
4
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../src/api/routes/render.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,QAAA,MAAM,MAAM,4EAAa,CAAC;AA4C1B,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { renderTemplate } from '@reaatech/prompt-version-control-shared';
3
+ import { Hono } from 'hono';
4
+ import { z } from 'zod';
5
+ import { authMiddleware } from '../../middleware/auth.js';
6
+ import { promptService } from '../../services/prompt.service.js';
7
+ import { tagService } from '../../services/tag.service.js';
8
+ import { getProjectId } from '../../utils/context.js';
9
+ const router = new Hono();
10
+ router.use('*', authMiddleware);
11
+ const RenderSchema = z.object({
12
+ variables: z.record(z.string()).optional(),
13
+ });
14
+ router.post('/prompts/:id/versions/:number/render', zValidator('json', RenderSchema), async (c) => {
15
+ const projectId = getProjectId(c);
16
+ const promptId = c.req.param('id');
17
+ const number = Number(c.req.param('number'));
18
+ const body = c.req.valid('json');
19
+ const version = await promptService.getVersionByNumber(projectId, promptId, number);
20
+ const result = renderTemplate(version.template, body.variables ?? {});
21
+ return c.json({
22
+ version: version.number,
23
+ content: version.content,
24
+ rendered: result.rendered,
25
+ variablesUsed: result.variablesUsed,
26
+ missingVariables: result.missingVariables,
27
+ });
28
+ });
29
+ router.post('/prompts/:id/render', zValidator('json', RenderSchema), async (c) => {
30
+ const projectId = getProjectId(c);
31
+ const promptId = c.req.param('id');
32
+ const body = c.req.valid('json');
33
+ const version = await tagService.getProductionVersion(projectId, promptId);
34
+ const result = renderTemplate(version.template, body.variables ?? {});
35
+ return c.json({
36
+ version: version.number,
37
+ content: version.content,
38
+ rendered: result.rendered,
39
+ variablesUsed: result.variablesUsed,
40
+ missingVariables: result.missingVariables,
41
+ });
42
+ });
43
+ export { router as renderRoutes };
44
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/api/routes/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ declare const router: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export { router as tagRoutes };
4
+ //# sourceMappingURL=tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.d.ts","sourceRoot":"","sources":["../../../src/api/routes/tags.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAK5B,QAAA,MAAM,MAAM,4EAAa,CAAC;AAwC1B,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { MoveTagSchema, TagNameSchema } from '@reaatech/prompt-version-control-shared';
3
+ import { Hono } from 'hono';
4
+ import { authMiddleware } from '../../middleware/auth.js';
5
+ import { tagService } from '../../services/tag.service.js';
6
+ import { getProjectId } from '../../utils/context.js';
7
+ const router = new Hono();
8
+ router.use('*', authMiddleware);
9
+ router.get('/', async (c) => {
10
+ const projectId = getProjectId(c);
11
+ const promptId = c.req.param('id');
12
+ const tags = await tagService.listTags(projectId, promptId);
13
+ return c.json({ data: tags });
14
+ });
15
+ router.post('/:name', zValidator('json', MoveTagSchema), async (c) => {
16
+ const projectId = getProjectId(c);
17
+ const promptId = c.req.param('id');
18
+ const name = c.req.param('name');
19
+ const body = c.req.valid('json');
20
+ const parsedName = TagNameSchema.parse(name);
21
+ const tag = await tagService.moveTag(projectId, promptId, parsedName, body.versionId);
22
+ return c.json(tag, 200);
23
+ });
24
+ router.get('/:name', async (c) => {
25
+ const projectId = getProjectId(c);
26
+ const promptId = c.req.param('id');
27
+ const name = c.req.param('name');
28
+ const parsedName = TagNameSchema.parse(name);
29
+ const tag = await tagService.getTag(projectId, promptId, parsedName);
30
+ return c.json(tag);
31
+ });
32
+ router.delete('/:name', async (c) => {
33
+ const projectId = getProjectId(c);
34
+ const promptId = c.req.param('id');
35
+ const name = c.req.param('name');
36
+ const parsedName = TagNameSchema.parse(name);
37
+ await tagService.removeTag(projectId, promptId, parsedName);
38
+ return c.body(null, 204);
39
+ });
40
+ export { router as tagRoutes };
41
+ //# sourceMappingURL=tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tags.js","sourceRoot":"","sources":["../../../src/api/routes/tags.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ declare const router: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export { router as webhookRoutes };
4
+ //# sourceMappingURL=webhooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.d.ts","sourceRoot":"","sources":["../../../src/api/routes/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAM5B,QAAA,MAAM,MAAM,4EAAa,CAAC;AAkD1B,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,CAAC"}
@@ -0,0 +1,49 @@
1
+ import { zValidator } from '@hono/zod-validator';
2
+ import { Hono } from 'hono';
3
+ import { z } from 'zod';
4
+ import { authMiddleware } from '../../middleware/auth.js';
5
+ import { webhookService } from '../../services/webhook.service.js';
6
+ import { getProjectId } from '../../utils/context.js';
7
+ const router = new Hono();
8
+ router.use('*', authMiddleware);
9
+ // Create webhook subscription
10
+ const CreateWebhookSchema = z.object({
11
+ url: z.string().url(),
12
+ events: z.array(z.enum([
13
+ 'version.created',
14
+ 'tag.moved',
15
+ 'eval.completed',
16
+ 'promotion.requested',
17
+ 'promotion.approved',
18
+ 'promotion.rejected',
19
+ ])),
20
+ secret: z.string().min(16),
21
+ });
22
+ router.post('/', zValidator('json', CreateWebhookSchema), async (c) => {
23
+ const projectId = getProjectId(c);
24
+ const body = c.req.valid('json');
25
+ const sub = await webhookService.createSubscription(projectId, body);
26
+ return c.json(sub, 201);
27
+ });
28
+ // List subscriptions
29
+ router.get('/', async (c) => {
30
+ const projectId = getProjectId(c);
31
+ const subs = await webhookService.listSubscriptions(projectId);
32
+ return c.json({ data: subs });
33
+ });
34
+ // Delete subscription
35
+ router.delete('/:id', async (c) => {
36
+ const projectId = getProjectId(c);
37
+ const id = c.req.param('id');
38
+ await webhookService.deleteSubscription(projectId, id);
39
+ return c.body(null, 204);
40
+ });
41
+ // Test delivery
42
+ router.post('/:id/test', async (c) => {
43
+ const projectId = getProjectId(c);
44
+ const id = c.req.param('id');
45
+ const result = await webhookService.testDelivery(projectId, id);
46
+ return c.json(result);
47
+ });
48
+ export { router as webhookRoutes };
49
+ //# sourceMappingURL=webhooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../../src/api/routes/webhooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,MAAM,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;AAE1B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;AAEhC,8BAA8B;AAC9B,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACrB,MAAM,EAAE,CAAC,CAAC,KAAK,CACb,CAAC,CAAC,IAAI,CAAC;QACL,iBAAiB;QACjB,WAAW;QACX,gBAAgB;QAChB,qBAAqB;QACrB,oBAAoB;QACpB,oBAAoB;KACrB,CAAC,CACH;IACD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;CAC3B,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,MAAM,EAAE,mBAAmB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACpE,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,kBAAkB,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACrE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,qBAAqB;AACrB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC1B,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC/D,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,sBAAsB;AACtB,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAChC,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAW,CAAC;IACvC,MAAM,cAAc,CAAC,kBAAkB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACvD,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEH,gBAAgB;AAChB,MAAM,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IACnC,MAAM,SAAS,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;IAClC,MAAM,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAW,CAAC;IACvC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,YAAY,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACxB,CAAC,CAAC,CAAC;AAEH,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+ export declare const prisma: PrismaClient<import("@prisma/client").Prisma.PrismaClientOptions, never, import("@prisma/client/runtime/library").DefaultArgs>;
3
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO9C,eAAO,MAAM,MAAM,gIAWf,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { PrismaClient } from '@prisma/client';
2
+ import { logger } from '../utils/logger.js';
3
+ const globalForPrisma = globalThis;
4
+ export const prisma = globalForPrisma.prisma ??
5
+ new PrismaClient({
6
+ log: process.env.NODE_ENV === 'development'
7
+ ? [
8
+ { emit: 'event', level: 'query' },
9
+ { emit: 'stdout', level: 'error' },
10
+ { emit: 'stdout', level: 'warn' },
11
+ ]
12
+ : [{ emit: 'stdout', level: 'error' }],
13
+ });
14
+ if (process.env.NODE_ENV === 'development') {
15
+ // biome-ignore lint/suspicious/noExplicitAny: Prisma internal event type
16
+ prisma.$on('query', (e) => {
17
+ logger.debug({ query: e.query, duration: e.duration }, 'prisma query');
18
+ });
19
+ globalForPrisma.prisma = prisma;
20
+ }
21
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/db/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,eAAe,GAAG,UAEvB,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GACjB,eAAe,CAAC,MAAM;IACtB,IAAI,YAAY,CAAC;QACf,GAAG,EACD,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;YACpC,CAAC,CAAC;gBACE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;gBACjC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE;gBAClC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;aAClC;YACH,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;KAC3C,CAAC,CAAC;AAEL,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE,CAAC;IAC3C,yEAAyE;IACxE,MAAc,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAsC,EAAE,EAAE;QACtE,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,cAAc,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IACH,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC;AAClC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { Redis } from 'ioredis';
2
+ export declare const redis: Redis | null;
3
+ //# sourceMappingURL=redis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.d.ts","sourceRoot":"","sources":["../../src/db/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAKhC,eAAO,MAAM,KAAK,cAQV,CAAC"}
@@ -0,0 +1,18 @@
1
+ import { Redis } from 'ioredis';
2
+ import { logger } from '../utils/logger.js';
3
+ const redisUrl = process.env.REDIS_URL;
4
+ export const redis = redisUrl
5
+ ? new Redis(redisUrl, {
6
+ retryStrategy: (times) => Math.min(times * 50, 2000),
7
+ reconnectOnError: (err) => {
8
+ logger.warn({ err: err.message }, 'redis reconnect');
9
+ return true;
10
+ },
11
+ })
12
+ : null;
13
+ if (redis) {
14
+ redis.on('error', (err) => {
15
+ logger.error({ err: err.message }, 'redis error');
16
+ });
17
+ }
18
+ //# sourceMappingURL=redis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis.js","sourceRoot":"","sources":["../../src/db/redis.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;AAEvC,MAAM,CAAC,MAAM,KAAK,GAAG,QAAQ;IAC3B,CAAC,CAAC,IAAI,KAAK,CAAC,QAAQ,EAAE;QAClB,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,EAAE,IAAI,CAAC;QACpD,gBAAgB,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC;YACrD,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;IACJ,CAAC,CAAC,IAAI,CAAC;AAET,IAAI,KAAK,EAAE,CAAC;IACV,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACxB,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,22 @@
1
+ export declare class AppError extends Error {
2
+ code: string;
3
+ status: number;
4
+ details?: Record<string, unknown> | undefined;
5
+ constructor(code: string, status: number, message: string, details?: Record<string, unknown> | undefined);
6
+ }
7
+ export declare class ValidationError extends AppError {
8
+ constructor(details: Record<string, string[]>);
9
+ }
10
+ export declare class NotFoundError extends AppError {
11
+ constructor(resource: string, id: string);
12
+ }
13
+ export declare class ConflictError extends AppError {
14
+ constructor(message: string, details?: Record<string, unknown>);
15
+ }
16
+ export declare class UnauthorizedError extends AppError {
17
+ constructor(message?: string);
18
+ }
19
+ export declare class RateLimitError extends AppError {
20
+ constructor(retryAfter: number);
21
+ }
22
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAS,SAAQ,KAAK;IAExB,IAAI,EAAE,MAAM;IACZ,MAAM,EAAE,MAAM;IAEd,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;gBAHjC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACR,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,YAAA;CAM3C;AAED,qBAAa,eAAgB,SAAQ,QAAQ;gBAC/B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CAG9C;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;CAGzC;AAED,qBAAa,aAAc,SAAQ,QAAQ;gBAC7B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAG/D;AAED,qBAAa,iBAAkB,SAAQ,QAAQ;gBACjC,OAAO,SAAiB;CAGrC;AAED,qBAAa,cAAe,SAAQ,QAAQ;gBAC9B,UAAU,EAAE,MAAM;CAG/B"}
package/dist/errors.js ADDED
@@ -0,0 +1,39 @@
1
+ export class AppError extends Error {
2
+ code;
3
+ status;
4
+ details;
5
+ constructor(code, status, message, details) {
6
+ super(message);
7
+ this.code = code;
8
+ this.status = status;
9
+ this.details = details;
10
+ this.name = this.constructor.name;
11
+ Error.captureStackTrace(this, this.constructor);
12
+ }
13
+ }
14
+ export class ValidationError extends AppError {
15
+ constructor(details) {
16
+ super('VALIDATION_ERROR', 400, 'Request validation failed', { fields: details });
17
+ }
18
+ }
19
+ export class NotFoundError extends AppError {
20
+ constructor(resource, id) {
21
+ super('NOT_FOUND', 404, `${resource} with id ${id} not found`);
22
+ }
23
+ }
24
+ export class ConflictError extends AppError {
25
+ constructor(message, details) {
26
+ super('CONFLICT', 409, message, details);
27
+ }
28
+ }
29
+ export class UnauthorizedError extends AppError {
30
+ constructor(message = 'Unauthorized') {
31
+ super('UNAUTHORIZED', 401, message);
32
+ }
33
+ }
34
+ export class RateLimitError extends AppError {
35
+ constructor(retryAfter) {
36
+ super('RATE_LIMIT_EXCEEDED', 429, 'Rate limit exceeded', { retryAfter });
37
+ }
38
+ }
39
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IACA;IAEA;IAJT,YACS,IAAY,EACZ,MAAc,EACrB,OAAe,EACR,OAAiC;QAExC,KAAK,CAAC,OAAO,CAAC,CAAC;QALR,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAQ;QAEd,YAAO,GAAP,OAAO,CAA0B;QAGxC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;QAClC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;IAClD,CAAC;CACF;AAED,MAAM,OAAO,eAAgB,SAAQ,QAAQ;IAC3C,YAAY,OAAiC;QAC3C,KAAK,CAAC,kBAAkB,EAAE,GAAG,EAAE,2BAA2B,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC;IACnF,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,QAAgB,EAAE,EAAU;QACtC,KAAK,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,QAAQ,YAAY,EAAE,YAAY,CAAC,CAAC;IACjE,CAAC;CACF;AAED,MAAM,OAAO,aAAc,SAAQ,QAAQ;IACzC,YAAY,OAAe,EAAE,OAAiC;QAC5D,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;CACF;AAED,MAAM,OAAO,iBAAkB,SAAQ,QAAQ;IAC7C,YAAY,OAAO,GAAG,cAAc;QAClC,KAAK,CAAC,cAAc,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,QAAQ;IAC1C,YAAY,UAAkB;QAC5B,KAAK,CAAC,qBAAqB,EAAE,GAAG,EAAE,qBAAqB,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3E,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import { Hono } from 'hono';
2
+ declare const app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
3
+ export { app };
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAkB5B,QAAA,MAAM,GAAG,4EAAa,CAAC;AA8EvB,OAAO,EAAE,GAAG,EAAE,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { Hono } from 'hono';
3
+ import { compress } from 'hono/compress';
4
+ import { cors } from 'hono/cors';
5
+ import { deploymentRoutes } from './api/routes/deployments.js';
6
+ import { docsRoutes } from './api/routes/docs.js';
7
+ import { evaluationRoutes } from './api/routes/evaluations.js';
8
+ import { metricRoutes } from './api/routes/metrics.js';
9
+ import { promotionRoutes } from './api/routes/promotions.js';
10
+ import { promptRoutes } from './api/routes/prompts.js';
11
+ import { renderRoutes } from './api/routes/render.js';
12
+ import { webhookRoutes } from './api/routes/webhooks.js';
13
+ import { errorHandler } from './middleware/error-handler.js';
14
+ import { metricsMiddleware } from './middleware/metrics.js';
15
+ import { rateLimit } from './middleware/rate-limit.js';
16
+ import { requestIdMiddleware } from './middleware/request-id.js';
17
+ import { getMetrics } from './services/prometheus.service.js';
18
+ import { logger } from './utils/logger.js';
19
+ const app = new Hono();
20
+ // Build a strict CORS origin allow-list. Defaults to "no cross-origin" — set
21
+ // CORS_ALLOWED_ORIGINS to a comma-separated list (or "*" to allow any).
22
+ const corsOriginEnv = process.env.CORS_ALLOWED_ORIGINS?.trim();
23
+ const corsOrigin = (() => {
24
+ if (!corsOriginEnv)
25
+ return [];
26
+ if (corsOriginEnv === '*')
27
+ return '*';
28
+ const allowed = corsOriginEnv
29
+ .split(',')
30
+ .map((s) => s.trim())
31
+ .filter(Boolean);
32
+ return (origin) => (allowed.includes(origin) ? origin : null);
33
+ })();
34
+ app.use(requestIdMiddleware);
35
+ app.use(compress());
36
+ app.use(cors({ origin: corsOrigin }));
37
+ app.use(rateLimit({ windowMs: 60_000, max: 100 }));
38
+ app.use(metricsMiddleware);
39
+ app.get('/health', (c) => c.json({ status: 'ok', timestamp: new Date().toISOString() }));
40
+ app.get('/ready', (c) => c.json({ status: 'ready' }));
41
+ app.get('/metrics', async (c) => {
42
+ const metrics = await getMetrics();
43
+ return c.text(metrics);
44
+ });
45
+ app.route('/api/v1/prompts', promptRoutes);
46
+ app.route('/api/v1/evaluations', evaluationRoutes);
47
+ app.route('/api/v1/metrics', metricRoutes);
48
+ app.route('/api/v1/deployments', deploymentRoutes);
49
+ app.route('/api/v1/webhooks', webhookRoutes);
50
+ app.route('/api/v1', renderRoutes);
51
+ app.route('/api/v1', promotionRoutes);
52
+ app.route('/api/v1/docs', docsRoutes);
53
+ app.onError(errorHandler);
54
+ app.notFound((c) => {
55
+ return c.json({
56
+ error: { code: 'NOT_FOUND', message: `Route ${c.req.url} not found` },
57
+ requestId: c.get('requestId'),
58
+ timestamp: new Date().toISOString(),
59
+ }, 404);
60
+ });
61
+ if (!process.env.PUBLIC_API_URL && process.env.NODE_ENV !== 'development') {
62
+ logger.warn('PUBLIC_API_URL is not set — eval harness callbacks will use localhost');
63
+ }
64
+ if (!process.env.API_KEY_PEPPER && process.env.NODE_ENV !== 'development') {
65
+ logger.warn('API_KEY_PEPPER is not set — API keys will be hashed with unsalted SHA-256');
66
+ }
67
+ const port = Number(process.env.PORT) || 3000;
68
+ logger.info(`Server starting on port ${port}`);
69
+ const server = serve({
70
+ fetch: app.fetch,
71
+ port,
72
+ });
73
+ const shutdown = (signal) => {
74
+ logger.info({ signal }, 'shutting down gracefully');
75
+ server.close(() => {
76
+ logger.info('server closed');
77
+ process.exit(0);
78
+ });
79
+ };
80
+ process.on('SIGTERM', () => shutdown('SIGTERM'));
81
+ process.on('SIGINT', () => shutdown('SIGINT'));
82
+ export { app };
83
+ //# sourceMappingURL=index.js.map