@sudobility/shapeshyft_service 1.0.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 (127) hide show
  1. package/CLAUDE.md +35 -0
  2. package/README.md +17 -0
  3. package/dist/context.d.ts +62 -0
  4. package/dist/context.d.ts.map +1 -0
  5. package/dist/context.js +55 -0
  6. package/dist/context.js.map +1 -0
  7. package/dist/contracts.d.ts +110 -0
  8. package/dist/contracts.d.ts.map +1 -0
  9. package/dist/contracts.js +7 -0
  10. package/dist/contracts.js.map +1 -0
  11. package/dist/index.d.ts +17 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +16 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/lib/api-key.d.ts +22 -0
  16. package/dist/lib/api-key.d.ts.map +1 -0
  17. package/dist/lib/api-key.js +87 -0
  18. package/dist/lib/api-key.js.map +1 -0
  19. package/dist/lib/encryption.d.ts +22 -0
  20. package/dist/lib/encryption.d.ts.map +1 -0
  21. package/dist/lib/encryption.js +41 -0
  22. package/dist/lib/encryption.js.map +1 -0
  23. package/dist/lib/entity-api-key.d.ts +21 -0
  24. package/dist/lib/entity-api-key.d.ts.map +1 -0
  25. package/dist/lib/entity-api-key.js +54 -0
  26. package/dist/lib/entity-api-key.js.map +1 -0
  27. package/dist/lib/entity-helpers.d.ts +90 -0
  28. package/dist/lib/entity-helpers.d.ts.map +1 -0
  29. package/dist/lib/entity-helpers.js +136 -0
  30. package/dist/lib/entity-helpers.js.map +1 -0
  31. package/dist/lib/money.d.ts +7 -0
  32. package/dist/lib/money.d.ts.map +1 -0
  33. package/dist/lib/money.js +9 -0
  34. package/dist/lib/money.js.map +1 -0
  35. package/dist/lib/public-project.d.ts +14 -0
  36. package/dist/lib/public-project.d.ts.map +1 -0
  37. package/dist/lib/public-project.js +17 -0
  38. package/dist/lib/public-project.js.map +1 -0
  39. package/dist/lib/user-api-key-cache.d.ts +35 -0
  40. package/dist/lib/user-api-key-cache.d.ts.map +1 -0
  41. package/dist/lib/user-api-key-cache.js +99 -0
  42. package/dist/lib/user-api-key-cache.js.map +1 -0
  43. package/dist/lib/user-api-key.d.ts +46 -0
  44. package/dist/lib/user-api-key.d.ts.map +1 -0
  45. package/dist/lib/user-api-key.js +102 -0
  46. package/dist/lib/user-api-key.js.map +1 -0
  47. package/dist/middleware/firebaseAuth.d.ts +34 -0
  48. package/dist/middleware/firebaseAuth.d.ts.map +1 -0
  49. package/dist/middleware/firebaseAuth.js +133 -0
  50. package/dist/middleware/firebaseAuth.js.map +1 -0
  51. package/dist/middleware/rateLimit.d.ts +29 -0
  52. package/dist/middleware/rateLimit.d.ts.map +1 -0
  53. package/dist/middleware/rateLimit.js +85 -0
  54. package/dist/middleware/rateLimit.js.map +1 -0
  55. package/dist/middleware/subscription.d.ts +8 -0
  56. package/dist/middleware/subscription.d.ts.map +1 -0
  57. package/dist/middleware/subscription.js +19 -0
  58. package/dist/middleware/subscription.js.map +1 -0
  59. package/dist/routes/ai.d.ts +10 -0
  60. package/dist/routes/ai.d.ts.map +1 -0
  61. package/dist/routes/ai.js +698 -0
  62. package/dist/routes/ai.js.map +1 -0
  63. package/dist/routes/analytics.d.ts +9 -0
  64. package/dist/routes/analytics.d.ts.map +1 -0
  65. package/dist/routes/analytics.js +192 -0
  66. package/dist/routes/analytics.js.map +1 -0
  67. package/dist/routes/endpoints.d.ts +10 -0
  68. package/dist/routes/endpoints.d.ts.map +1 -0
  69. package/dist/routes/endpoints.js +255 -0
  70. package/dist/routes/endpoints.js.map +1 -0
  71. package/dist/routes/entities.d.ts +15 -0
  72. package/dist/routes/entities.d.ts.map +1 -0
  73. package/dist/routes/entities.js +332 -0
  74. package/dist/routes/entities.js.map +1 -0
  75. package/dist/routes/entity-api-keys.d.ts +17 -0
  76. package/dist/routes/entity-api-keys.d.ts.map +1 -0
  77. package/dist/routes/entity-api-keys.js +142 -0
  78. package/dist/routes/entity-api-keys.js.map +1 -0
  79. package/dist/routes/invitations.d.ts +15 -0
  80. package/dist/routes/invitations.d.ts.map +1 -0
  81. package/dist/routes/invitations.js +58 -0
  82. package/dist/routes/invitations.js.map +1 -0
  83. package/dist/routes/projects.d.ts +9 -0
  84. package/dist/routes/projects.d.ts.map +1 -0
  85. package/dist/routes/projects.js +241 -0
  86. package/dist/routes/projects.js.map +1 -0
  87. package/dist/routes/providers.d.ts +9 -0
  88. package/dist/routes/providers.d.ts.map +1 -0
  89. package/dist/routes/providers.js +89 -0
  90. package/dist/routes/providers.js.map +1 -0
  91. package/dist/routes/ratelimits.d.ts +9 -0
  92. package/dist/routes/ratelimits.d.ts.map +1 -0
  93. package/dist/routes/ratelimits.js +171 -0
  94. package/dist/routes/ratelimits.js.map +1 -0
  95. package/dist/routes/settings.d.ts +9 -0
  96. package/dist/routes/settings.d.ts.map +1 -0
  97. package/dist/routes/settings.js +138 -0
  98. package/dist/routes/settings.js.map +1 -0
  99. package/dist/routes/storage.d.ts +9 -0
  100. package/dist/routes/storage.d.ts.map +1 -0
  101. package/dist/routes/storage.js +180 -0
  102. package/dist/routes/storage.js.map +1 -0
  103. package/dist/routes/user-api-keys.d.ts +14 -0
  104. package/dist/routes/user-api-keys.d.ts.map +1 -0
  105. package/dist/routes/user-api-keys.js +237 -0
  106. package/dist/routes/user-api-keys.js.map +1 -0
  107. package/dist/routes/users.d.ts +7 -0
  108. package/dist/routes/users.d.ts.map +1 -0
  109. package/dist/routes/users.js +102 -0
  110. package/dist/routes/users.js.map +1 -0
  111. package/dist/schema/init.d.ts +12 -0
  112. package/dist/schema/init.d.ts.map +1 -0
  113. package/dist/schema/init.js +404 -0
  114. package/dist/schema/init.js.map +1 -0
  115. package/dist/schema/tables.d.ts +2110 -0
  116. package/dist/schema/tables.d.ts.map +1 -0
  117. package/dist/schema/tables.js +251 -0
  118. package/dist/schema/tables.js.map +1 -0
  119. package/dist/schemas/index.d.ts +671 -0
  120. package/dist/schemas/index.d.ts.map +1 -0
  121. package/dist/schemas/index.js +299 -0
  122. package/dist/schemas/index.js.map +1 -0
  123. package/dist/service.d.ts +41 -0
  124. package/dist/service.d.ts.map +1 -0
  125. package/dist/service.js +70 -0
  126. package/dist/service.js.map +1 -0
  127. package/package.json +85 -0
@@ -0,0 +1,241 @@
1
+ /**
2
+ * @fileoverview Project management routes
3
+ * @description CRUD operations for projects. Each project gets an auto-generated
4
+ * API key on creation. Includes API key retrieval and refresh endpoints.
5
+ */
6
+ import { Hono } from "hono";
7
+ import { zValidator } from "@hono/zod-validator";
8
+ import { eq, and } from "drizzle-orm";
9
+ import { projectCreateSchema, projectUpdateSchema, projectIdParamSchema, entitySlugParamSchema, } from "../schemas/index.js";
10
+ import { successResponse, errorResponse, } from "@sudobility/shapeshyft_engine/types";
11
+ import { publicProject } from "../lib/public-project.js";
12
+ export function createProjectsRouter(ctx) {
13
+ const { db } = ctx;
14
+ const { projects } = ctx.tables;
15
+ const { generateProjectApiKey, encryptProjectApiKey, decryptProjectApiKey } = ctx.projectApiKeys;
16
+ const { getActor, getEntityWithPermission, getPermissionErrorStatus } = ctx.entityAccess;
17
+ const projectsRouter = new Hono();
18
+ // GET all projects for entity
19
+ projectsRouter.get("/", zValidator("param", entitySlugParamSchema), async (c) => {
20
+ try {
21
+ const { entitySlug } = c.req.valid("param");
22
+ const result = await getEntityWithPermission(entitySlug, getActor(c));
23
+ if (result.error !== undefined) {
24
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
25
+ }
26
+ const rows = await db
27
+ .select()
28
+ .from(projects)
29
+ .where(eq(projects.entity_id, result.entity.id));
30
+ return c.json(successResponse(rows.map(publicProject)));
31
+ }
32
+ catch (error) {
33
+ console.error("Error getting projects:", error);
34
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
35
+ }
36
+ });
37
+ // GET single project
38
+ projectsRouter.get("/:projectId", zValidator("param", projectIdParamSchema), async (c) => {
39
+ try {
40
+ const { entitySlug, projectId } = c.req.valid("param");
41
+ const result = await getEntityWithPermission(entitySlug, getActor(c));
42
+ if (result.error !== undefined) {
43
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
44
+ }
45
+ const rows = await db
46
+ .select()
47
+ .from(projects)
48
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.uuid, projectId)));
49
+ if (rows.length === 0) {
50
+ return c.json(errorResponse("Project not found"), 404);
51
+ }
52
+ return c.json(successResponse(publicProject(rows[0])));
53
+ }
54
+ catch (error) {
55
+ console.error("Error getting project:", error);
56
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
57
+ }
58
+ });
59
+ // POST create project
60
+ projectsRouter.post("/", zValidator("param", entitySlugParamSchema), zValidator("json", projectCreateSchema), async (c) => {
61
+ try {
62
+ const { entitySlug } = c.req.valid("param");
63
+ const body = c.req.valid("json");
64
+ const result = await getEntityWithPermission(entitySlug, getActor(c), true);
65
+ if (result.error !== undefined) {
66
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
67
+ }
68
+ // Check for duplicate project name
69
+ const existing = await db
70
+ .select()
71
+ .from(projects)
72
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.project_name, body.project_name)));
73
+ if (existing.length > 0) {
74
+ return c.json(errorResponse("Project name already exists"), 409);
75
+ }
76
+ // Generate API key for the project
77
+ const { key, prefix } = generateProjectApiKey();
78
+ const { encrypted, iv } = encryptProjectApiKey(key);
79
+ const rows = await db
80
+ .insert(projects)
81
+ .values({
82
+ entity_id: result.entity.id,
83
+ project_name: body.project_name,
84
+ display_name: body.display_name,
85
+ description: body.description ?? null,
86
+ encrypted_api_key: encrypted,
87
+ api_key_iv: iv,
88
+ api_key_prefix: prefix,
89
+ api_key_created_at: new Date(),
90
+ })
91
+ .returning();
92
+ return c.json(successResponse(rows[0]), 201);
93
+ }
94
+ catch (error) {
95
+ console.error("Error creating project:", error);
96
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
97
+ }
98
+ });
99
+ // PUT update project
100
+ projectsRouter.put("/:projectId", zValidator("param", projectIdParamSchema), zValidator("json", projectUpdateSchema), async (c) => {
101
+ try {
102
+ const { entitySlug, projectId } = c.req.valid("param");
103
+ const body = c.req.valid("json");
104
+ const result = await getEntityWithPermission(entitySlug, getActor(c), true);
105
+ if (result.error !== undefined) {
106
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
107
+ }
108
+ // Check if project exists
109
+ const existing = await db
110
+ .select()
111
+ .from(projects)
112
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.uuid, projectId)));
113
+ if (existing.length === 0) {
114
+ return c.json(errorResponse("Project not found"), 404);
115
+ }
116
+ const current = existing[0];
117
+ // Check for duplicate project name if changing
118
+ if (body.project_name && body.project_name !== current.project_name) {
119
+ const duplicate = await db
120
+ .select()
121
+ .from(projects)
122
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.project_name, body.project_name)));
123
+ if (duplicate.length > 0) {
124
+ return c.json(errorResponse("Project name already exists"), 409);
125
+ }
126
+ }
127
+ const rows = await db
128
+ .update(projects)
129
+ .set({
130
+ project_name: body.project_name ?? current.project_name,
131
+ display_name: body.display_name ?? current.display_name,
132
+ description: body.description ?? current.description,
133
+ is_active: body.is_active ?? current.is_active,
134
+ updated_at: new Date(),
135
+ })
136
+ .where(eq(projects.uuid, projectId))
137
+ .returning();
138
+ return c.json(successResponse(rows[0]));
139
+ }
140
+ catch (error) {
141
+ console.error("Error updating project:", error);
142
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
143
+ }
144
+ });
145
+ // DELETE project
146
+ projectsRouter.delete("/:projectId", zValidator("param", projectIdParamSchema), async (c) => {
147
+ try {
148
+ const { entitySlug, projectId } = c.req.valid("param");
149
+ const result = await getEntityWithPermission(entitySlug, getActor(c), true);
150
+ if (result.error !== undefined) {
151
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
152
+ }
153
+ const rows = await db
154
+ .delete(projects)
155
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.uuid, projectId)))
156
+ .returning();
157
+ if (rows.length === 0) {
158
+ return c.json(errorResponse("Project not found"), 404);
159
+ }
160
+ return c.json(successResponse(rows[0]));
161
+ }
162
+ catch (error) {
163
+ console.error("Error deleting project:", error);
164
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
165
+ }
166
+ });
167
+ // GET project API key (full key - authenticated)
168
+ projectsRouter.get("/:projectId/api-key", zValidator("param", projectIdParamSchema), async (c) => {
169
+ try {
170
+ const { entitySlug, projectId } = c.req.valid("param");
171
+ const result = await getEntityWithPermission(entitySlug, getActor(c));
172
+ if (result.error !== undefined) {
173
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
174
+ }
175
+ const rows = await db
176
+ .select()
177
+ .from(projects)
178
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.uuid, projectId)));
179
+ if (rows.length === 0) {
180
+ return c.json(errorResponse("Project not found"), 404);
181
+ }
182
+ const project = rows[0];
183
+ if (!project.encrypted_api_key || !project.api_key_iv) {
184
+ return c.json(errorResponse("API key not found for this project"), 404);
185
+ }
186
+ const apiKey = decryptProjectApiKey(project.encrypted_api_key, project.api_key_iv);
187
+ const response = {
188
+ api_key: apiKey,
189
+ };
190
+ return c.json(successResponse(response));
191
+ }
192
+ catch (error) {
193
+ console.error("Error getting project API key:", error);
194
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
195
+ }
196
+ });
197
+ // POST refresh project API key
198
+ projectsRouter.post("/:projectId/api-key/refresh", zValidator("param", projectIdParamSchema), async (c) => {
199
+ try {
200
+ const { entitySlug, projectId } = c.req.valid("param");
201
+ const result = await getEntityWithPermission(entitySlug, getActor(c), true);
202
+ if (result.error !== undefined) {
203
+ return c.json(errorResponse(result.error), getPermissionErrorStatus(result.errorCode));
204
+ }
205
+ // Check if project exists
206
+ const existing = await db
207
+ .select()
208
+ .from(projects)
209
+ .where(and(eq(projects.entity_id, result.entity.id), eq(projects.uuid, projectId)));
210
+ if (existing.length === 0) {
211
+ return c.json(errorResponse("Project not found"), 404);
212
+ }
213
+ // Generate new API key
214
+ const { key, prefix } = generateProjectApiKey();
215
+ const { encrypted, iv } = encryptProjectApiKey(key);
216
+ const createdAt = new Date();
217
+ await db
218
+ .update(projects)
219
+ .set({
220
+ encrypted_api_key: encrypted,
221
+ api_key_iv: iv,
222
+ api_key_prefix: prefix,
223
+ api_key_created_at: createdAt,
224
+ updated_at: createdAt,
225
+ })
226
+ .where(eq(projects.uuid, projectId));
227
+ const response = {
228
+ api_key: key,
229
+ api_key_prefix: prefix,
230
+ api_key_created_at: createdAt.toISOString(),
231
+ };
232
+ return c.json(successResponse(response));
233
+ }
234
+ catch (error) {
235
+ console.error("Error refreshing project API key:", error);
236
+ return c.json(errorResponse(error.message || "Internal server error"), 500);
237
+ }
238
+ });
239
+ return projectsRouter;
240
+ }
241
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../src/routes/projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @fileoverview Public provider catalog routes
3
+ * @description Serves the LLM provider and model catalog. These are public
4
+ * routes (no auth required) so the frontend can fetch provider/model info
5
+ * without requiring server-side package updates.
6
+ */
7
+ import { Hono } from "hono";
8
+ export declare function createProvidersRouter(): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
9
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/routes/providers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAmB5B,wBAAgB,qBAAqB,+EAmGpC"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @fileoverview Public provider catalog routes
3
+ * @description Serves the LLM provider and model catalog. These are public
4
+ * routes (no auth required) so the frontend can fetch provider/model info
5
+ * without requiring server-side package updates.
6
+ */
7
+ import { Hono } from "hono";
8
+ import { zValidator } from "@hono/zod-validator";
9
+ import { z } from "zod";
10
+ import { successResponse, errorResponse, } from "@sudobility/shapeshyft_engine/types";
11
+ import { PROVIDERS, PROVIDER_MODELS, MODEL_CAPABILITIES, MODEL_PRICING, DEFAULT_MODEL_PRICING, getProviderById, } from "@sudobility/shapeshyft_engine";
12
+ export function createProvidersRouter() {
13
+ const providersRouter = new Hono();
14
+ // Schema for provider param validation
15
+ const providerParamSchema = z.object({
16
+ provider: z.string().min(1),
17
+ });
18
+ /**
19
+ * GET /providers
20
+ * Returns list of all available LLM providers with their configuration.
21
+ * Cached for 1 hour since provider data is static.
22
+ */
23
+ providersRouter.get("/", async (c) => {
24
+ try {
25
+ c.header("Cache-Control", "public, max-age=3600, s-maxage=3600");
26
+ return c.json(successResponse(PROVIDERS));
27
+ }
28
+ catch (error) {
29
+ console.error("Error getting providers:", error);
30
+ const message = error instanceof Error ? error.message : "Internal server error";
31
+ return c.json(errorResponse(message), 500);
32
+ }
33
+ });
34
+ /**
35
+ * GET /providers/:provider
36
+ * Returns configuration for a specific provider.
37
+ * Cached for 1 hour since provider data is static.
38
+ */
39
+ providersRouter.get("/:provider", zValidator("param", providerParamSchema), async (c) => {
40
+ try {
41
+ const { provider } = c.req.valid("param");
42
+ const providerConfig = getProviderById(provider);
43
+ if (!providerConfig) {
44
+ return c.json(errorResponse("Provider not found"), 404);
45
+ }
46
+ c.header("Cache-Control", "public, max-age=3600, s-maxage=3600");
47
+ return c.json(successResponse(providerConfig));
48
+ }
49
+ catch (error) {
50
+ console.error("Error getting provider:", error);
51
+ const message = error instanceof Error ? error.message : "Internal server error";
52
+ return c.json(errorResponse(message), 500);
53
+ }
54
+ });
55
+ /**
56
+ * GET /providers/:provider/models
57
+ * Returns list of models for a provider with their capabilities and pricing.
58
+ * Cached for 1 hour since model data is static.
59
+ */
60
+ providersRouter.get("/:provider/models", zValidator("param", providerParamSchema), async (c) => {
61
+ try {
62
+ const { provider } = c.req.valid("param");
63
+ const providerConfig = getProviderById(provider);
64
+ if (!providerConfig) {
65
+ return c.json(errorResponse("Provider not found"), 404);
66
+ }
67
+ const modelIds = PROVIDER_MODELS[provider] ?? [];
68
+ // Build response with model details
69
+ const models = modelIds.map(modelId => ({
70
+ id: modelId,
71
+ capabilities: MODEL_CAPABILITIES[modelId] ?? {},
72
+ pricing: MODEL_PRICING[modelId] ?? DEFAULT_MODEL_PRICING,
73
+ }));
74
+ c.header("Cache-Control", "public, max-age=3600, s-maxage=3600");
75
+ const response = {
76
+ provider: providerConfig,
77
+ models,
78
+ };
79
+ return c.json(successResponse(response));
80
+ }
81
+ catch (error) {
82
+ console.error("Error getting provider models:", error);
83
+ const message = error instanceof Error ? error.message : "Internal server error";
84
+ return c.json(errorResponse(message), 500);
85
+ }
86
+ });
87
+ return providersRouter;
88
+ }
89
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/routes/providers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,eAAe,EACf,aAAa,GAId,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,SAAS,EACT,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,qBAAqB,EACrB,eAAe,GAChB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,UAAU,qBAAqB;IACnC,MAAM,eAAe,GAAG,IAAI,IAAI,EAAE,CAAC;IAEnC,uCAAuC;IACvC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;QACnC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;KAC5B,CAAC,CAAC;IAEH;;;;OAIG;IACH,eAAe,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAC,CAAC,EAAC,EAAE;QACjC,IAAI,CAAC;YACH,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;YACjE,OAAO,CAAC,CAAC,IAAI,CACX,eAAe,CAAmB,SAA6B,CAAC,CACjE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;YACnE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH;;;;OAIG;IACH,eAAe,CAAC,GAAG,CACjB,YAAY,EACZ,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,EACxC,KAAK,EAAC,CAAC,EAAC,EAAE;QACR,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,cAAc,GAAG,eAAe,CAAC,QAAuB,CAAC,CAAC;YAEhE,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC;YAED,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;YACjE,OAAO,CAAC,CAAC,IAAI,CACX,eAAe,CAAiB,cAAgC,CAAC,CAClE,CAAC;QACJ,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;YAChD,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;YACnE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CACF,CAAC;IAEF;;;;OAIG;IACH,eAAe,CAAC,GAAG,CACjB,mBAAmB,EACnB,UAAU,CAAC,OAAO,EAAE,mBAAmB,CAAC,EACxC,KAAK,EAAC,CAAC,EAAC,EAAE;QACR,IAAI,CAAC;YACH,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC1C,MAAM,cAAc,GAAG,eAAe,CAAC,QAAuB,CAAC,CAAC;YAEhE,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,oBAAoB,CAAC,EAAE,GAAG,CAAC,CAAC;YAC1D,CAAC;YAED,MAAM,QAAQ,GAAG,eAAe,CAAC,QAAuB,CAAC,IAAI,EAAE,CAAC;YAEhE,oCAAoC;YACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACtC,EAAE,EAAE,OAAO;gBACX,YAAY,EAAE,kBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE;gBAC/C,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,IAAI,qBAAqB;aACzD,CAAC,CAAC,CAAC;YAEJ,CAAC,CAAC,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC,CAAC;YACjE,MAAM,QAAQ,GAA2B;gBACvC,QAAQ,EAAE,cAAgC;gBAC1C,MAAM;aACP,CAAC;YACF,OAAO,CAAC,CAAC,IAAI,CAAC,eAAe,CAAyB,QAAQ,CAAC,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,KAAK,CAAC,CAAC;YACvD,MAAM,OAAO,GACX,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC;YACnE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,GAAG,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC,CACF,CAAC;IAEF,OAAO,eAAe,CAAC;AACzB,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @fileoverview Rate limit configuration and usage history routes
3
+ * @description Provides rate limit config (tiers, current usage) and
4
+ * usage history per entity. Rate limits are tied to RevenueCat subscriptions.
5
+ */
6
+ import { Hono } from "hono";
7
+ import type { ServiceContext } from "../context.js";
8
+ export declare function createRatelimitsRouter(ctx: ServiceContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
9
+ //# sourceMappingURL=ratelimits.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratelimits.d.ts","sourceRoot":"","sources":["../../src/routes/ratelimits.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAW5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,cAAc,8EAyNzD"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * @fileoverview Rate limit configuration and usage history routes
3
+ * @description Provides rate limit config (tiers, current usage) and
4
+ * usage history per entity. Rate limits are tied to RevenueCat subscriptions.
5
+ */
6
+ import { Hono } from "hono";
7
+ import { eq } from "drizzle-orm";
8
+ import { successResponse, errorResponse, } from "@sudobility/shapeshyft_engine/types";
9
+ export function createRatelimitsRouter(ctx) {
10
+ const { db } = ctx;
11
+ const { entities, entityMembers } = ctx.tables;
12
+ const { getRateLimitRouteHandler, rateLimitsConfig, entitlementDisplayNames, } = ctx.rateLimiting;
13
+ const ratelimitsRouter = new Hono();
14
+ /**
15
+ * Extract testMode from URL query parameter
16
+ */
17
+ function getTestMode(c) {
18
+ const url = new URL(c.req.url);
19
+ const testMode = url.searchParams.get("testMode");
20
+ return testMode === "true";
21
+ }
22
+ /**
23
+ * Check if RevenueCat is configured
24
+ */
25
+ function isRevenueCatConfigured() {
26
+ const key = ctx.revenueCatApiKey;
27
+ return !!key && key.length > 0;
28
+ }
29
+ /**
30
+ * Verify user has access to entity and return its ID.
31
+ * rateLimitUserId is taken from path parameter (an entity slug).
32
+ */
33
+ async function getEntityIdForRateLimits(c, firebaseUid) {
34
+ // rateLimitUserId is the entity slug
35
+ const rateLimitUserId = c.req.param("rateLimitUserId");
36
+ if (!rateLimitUserId) {
37
+ return { entityId: null, error: "rateLimitUserId is required" };
38
+ }
39
+ // Look up entity by slug (rateLimitUserId is the entity slug)
40
+ const entityRows = await db
41
+ .select()
42
+ .from(entities)
43
+ .where(eq(entities.entity_slug, rateLimitUserId));
44
+ if (entityRows.length === 0) {
45
+ return { entityId: null, error: "Entity not found" };
46
+ }
47
+ const entity = entityRows[0];
48
+ // Verify user has access to this entity
49
+ const memberRows = await db
50
+ .select()
51
+ .from(entityMembers)
52
+ .where(eq(entityMembers.entity_id, entity.id));
53
+ const isMember = memberRows.some(m => m.user_id === firebaseUid && m.is_active);
54
+ if (!isMember) {
55
+ return { entityId: null, error: "Access denied to entity" };
56
+ }
57
+ return { entityId: entity.id, error: null };
58
+ }
59
+ /**
60
+ * GET /ratelimits/:rateLimitUserId
61
+ * Returns rate limit configurations for all entitlement tiers
62
+ * and the current entity's usage.
63
+ * rateLimitUserId is the entity slug.
64
+ * Query params:
65
+ * - testMode: Optional, set to "true" for sandbox mode.
66
+ * Note: Firebase auth is applied at the admin routes level.
67
+ */
68
+ ratelimitsRouter.get("/", async (c) => {
69
+ try {
70
+ const testMode = getTestMode(c);
71
+ // If RevenueCat is not configured, return static config without usage data
72
+ if (!isRevenueCatConfigured()) {
73
+ const noneLimits = rateLimitsConfig.none;
74
+ // Convert flat config to tiers array format
75
+ const tiers = Object.entries(rateLimitsConfig).map(([entitlement, limits]) => ({
76
+ entitlement,
77
+ displayName: entitlementDisplayNames[entitlement] || entitlement,
78
+ limits: {
79
+ hourly: limits.hourly ?? null,
80
+ daily: limits.daily ?? null,
81
+ monthly: limits.monthly ?? null,
82
+ },
83
+ }));
84
+ const fallback = {
85
+ tiers,
86
+ currentEntitlement: "none",
87
+ currentLimits: {
88
+ hourly: noneLimits.hourly ?? null,
89
+ daily: noneLimits.daily ?? null,
90
+ monthly: noneLimits.monthly ?? null,
91
+ },
92
+ currentUsage: {
93
+ hourly: 0,
94
+ daily: 0,
95
+ monthly: 0,
96
+ },
97
+ };
98
+ return c.json(successResponse(fallback));
99
+ }
100
+ const userId = c.get("userId");
101
+ // Get entity ID for rate limit lookup
102
+ const { entityId, error: entityError } = await getEntityIdForRateLimits(c, userId);
103
+ if (entityError || !entityId) {
104
+ const status = entityError === "rateLimitUserId is required"
105
+ ? 400
106
+ : entityError === "Access denied to entity"
107
+ ? 403
108
+ : 404;
109
+ return c.json(errorResponse(entityError || "Entity not found"), status);
110
+ }
111
+ // Use entity ID for rate limits (subscriptions are per-entity)
112
+ // testMode is passed to the method to filter sandbox purchases
113
+ const data = await getRateLimitRouteHandler().getRateLimitsConfigData(entityId, testMode);
114
+ return c.json(successResponse(data));
115
+ }
116
+ catch (error) {
117
+ console.error("Error fetching rate limits config:", error);
118
+ return c.json(errorResponse("Failed to fetch rate limits"), 500);
119
+ }
120
+ });
121
+ /**
122
+ * GET /ratelimits/:rateLimitUserId/history/:periodType
123
+ * Returns usage history for a specific period type.
124
+ * rateLimitUserId is the entity slug.
125
+ * periodType can be: hour, day, or month
126
+ * Query params:
127
+ * - testMode: Optional, set to "true" for sandbox mode.
128
+ */
129
+ ratelimitsRouter.get("/history/:periodType", async (c) => {
130
+ try {
131
+ const testMode = getTestMode(c);
132
+ const periodTypeParam = c.req.param("periodType");
133
+ // Validate period type
134
+ if (!["hour", "day", "month"].includes(periodTypeParam)) {
135
+ return c.json(errorResponse("Invalid period type. Must be one of: hour, day, month"), 400);
136
+ }
137
+ // If RevenueCat is not configured, return empty history
138
+ if (!isRevenueCatConfigured()) {
139
+ const emptyHistory = {
140
+ periodType: periodTypeParam,
141
+ entries: [],
142
+ totalEntries: 0,
143
+ };
144
+ return c.json(successResponse(emptyHistory));
145
+ }
146
+ const periodType = periodTypeParam;
147
+ const userId = c.get("userId");
148
+ // Get entity ID for rate limit lookup
149
+ const { entityId, error: entityError } = await getEntityIdForRateLimits(c, userId);
150
+ if (entityError || !entityId) {
151
+ const status = entityError === "rateLimitUserId is required"
152
+ ? 400
153
+ : entityError === "Access denied to entity"
154
+ ? 403
155
+ : 404;
156
+ return c.json(errorResponse(entityError || "Entity not found"), status);
157
+ }
158
+ // Use entity ID for rate limits (subscriptions are per-entity)
159
+ // testMode is passed to the method to filter sandbox purchases
160
+ const data = await getRateLimitRouteHandler().getRateLimitHistoryData(entityId, periodType, 100, // default limit
161
+ testMode);
162
+ return c.json(successResponse(data));
163
+ }
164
+ catch (error) {
165
+ console.error("Error fetching rate limit history:", error);
166
+ return c.json(errorResponse("Failed to fetch rate limit history"), 500);
167
+ }
168
+ });
169
+ return ratelimitsRouter;
170
+ }
171
+ //# sourceMappingURL=ratelimits.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ratelimits.js","sourceRoot":"","sources":["../../src/routes/ratelimits.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @fileoverview User settings routes
3
+ * @description Manages per-user settings including organization name and path.
4
+ * Uses upsert pattern -- settings are created on first PUT if they don't exist.
5
+ */
6
+ import { Hono } from "hono";
7
+ import type { ServiceContext } from "../context.js";
8
+ export declare function createSettingsRouter(ctx: ServiceContext): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
9
+ //# sourceMappingURL=settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/routes/settings.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAS5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,cAAc,8EAsKvD"}