@nordsym/apiclaw 1.8.7 → 1.8.9

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 (156) hide show
  1. package/README.md +58 -30
  2. package/convex/adminActivate.d.ts +3 -0
  3. package/convex/adminActivate.d.ts.map +1 -1
  4. package/convex/adminActivate.js +46 -0
  5. package/convex/adminActivate.js.map +1 -1
  6. package/convex/adminActivate.ts +1 -2
  7. package/convex/adminStats.d.ts +9 -0
  8. package/convex/adminStats.d.ts.map +1 -1
  9. package/convex/adminStats.js +282 -0
  10. package/convex/adminStats.js.map +1 -1
  11. package/convex/adminStats.ts +5 -3
  12. package/convex/agents.d.ts +84 -0
  13. package/convex/agents.js +809 -0
  14. package/convex/analytics.d.ts +5 -0
  15. package/convex/analytics.js +167 -0
  16. package/convex/apiKeys.d.ts +6 -0
  17. package/convex/apiKeys.d.ts.map +1 -0
  18. package/convex/apiKeys.js +186 -0
  19. package/convex/apiKeys.js.map +1 -0
  20. package/convex/backfillAnalytics.d.ts +2 -0
  21. package/convex/backfillAnalytics.js +20 -0
  22. package/convex/backfillSearchLogs.d.ts +2 -0
  23. package/convex/backfillSearchLogs.js +29 -0
  24. package/convex/billing.d.ts +88 -0
  25. package/convex/billing.d.ts.map +1 -1
  26. package/convex/billing.js +643 -0
  27. package/convex/billing.js.map +1 -1
  28. package/convex/billing.ts +2 -14
  29. package/convex/capabilities.d.ts +9 -0
  30. package/convex/capabilities.js +145 -0
  31. package/convex/chains.d.ts +68 -0
  32. package/convex/chains.js +1105 -0
  33. package/convex/credits.d.ts +25 -0
  34. package/convex/credits.js +186 -0
  35. package/convex/crons.d.ts +3 -0
  36. package/convex/crons.js +17 -0
  37. package/convex/debugFilestackLogs.d.ts +2 -0
  38. package/convex/debugFilestackLogs.js +17 -0
  39. package/convex/debugGetToken.d.ts +2 -0
  40. package/convex/debugGetToken.js +18 -0
  41. package/convex/directCall.d.ts +72 -0
  42. package/convex/directCall.d.ts.map +1 -1
  43. package/convex/directCall.js +663 -0
  44. package/convex/directCall.js.map +1 -1
  45. package/convex/earnProgress.d.ts +58 -0
  46. package/convex/earnProgress.js +649 -0
  47. package/convex/email.d.ts +14 -0
  48. package/convex/email.js +300 -0
  49. package/convex/email.js.map +1 -1
  50. package/convex/feedback.d.ts +7 -0
  51. package/convex/feedback.js +227 -0
  52. package/convex/http.d.ts +3 -0
  53. package/convex/http.d.ts.map +1 -1
  54. package/convex/http.js +2135 -0
  55. package/convex/http.js.map +1 -1
  56. package/convex/http.ts +275 -3
  57. package/convex/inbound.d.ts +2 -0
  58. package/convex/inbound.js +32 -0
  59. package/convex/logs.d.ts +48 -0
  60. package/convex/logs.d.ts.map +1 -1
  61. package/convex/logs.js +623 -0
  62. package/convex/logs.js.map +1 -1
  63. package/convex/migrateFilestack.d.ts +2 -0
  64. package/convex/migrateFilestack.js +74 -0
  65. package/convex/migratePartnersProd.d.ts +8 -0
  66. package/convex/migratePartnersProd.js +165 -0
  67. package/convex/migratePratham.d.ts +2 -0
  68. package/convex/migratePratham.js +121 -0
  69. package/convex/migrateProviderWorkspaces.d.ts +13 -0
  70. package/convex/migrateProviderWorkspaces.d.ts.map +1 -1
  71. package/convex/migrateProviderWorkspaces.js +141 -0
  72. package/convex/migrateProviderWorkspaces.js.map +1 -1
  73. package/convex/mou.d.ts +6 -0
  74. package/convex/mou.js +82 -0
  75. package/convex/providerKeys.d.ts +31 -0
  76. package/convex/providerKeys.js +257 -0
  77. package/convex/providers.d.ts +35 -0
  78. package/convex/providers.d.ts.map +1 -1
  79. package/convex/providers.js +1027 -0
  80. package/convex/providers.js.map +1 -1
  81. package/convex/purchases.d.ts +7 -0
  82. package/convex/purchases.js +157 -0
  83. package/convex/ratelimit.d.ts +4 -0
  84. package/convex/ratelimit.js +91 -0
  85. package/convex/schema.ts +4 -4
  86. package/convex/searchLogs.d.ts +13 -0
  87. package/convex/searchLogs.d.ts.map +1 -1
  88. package/convex/searchLogs.js +241 -0
  89. package/convex/searchLogs.js.map +1 -1
  90. package/convex/seedAPILayerAPIs.d.ts +7 -0
  91. package/convex/seedAPILayerAPIs.js +177 -0
  92. package/convex/seedDirectCallConfigs.d.ts +2 -0
  93. package/convex/seedDirectCallConfigs.js +324 -0
  94. package/convex/seedPratham.d.ts +6 -0
  95. package/convex/seedPratham.d.ts.map +1 -1
  96. package/convex/seedPratham.js +149 -0
  97. package/convex/seedPratham.js.map +1 -1
  98. package/convex/seedPratham.ts +1 -2
  99. package/convex/spendAlerts.d.ts +36 -0
  100. package/convex/spendAlerts.js +380 -0
  101. package/convex/spendAlerts.js.map +1 -1
  102. package/convex/stripeActions.d.ts +19 -0
  103. package/convex/stripeActions.d.ts.map +1 -1
  104. package/convex/stripeActions.js +432 -0
  105. package/convex/stripeActions.js.map +1 -1
  106. package/convex/stripeActions.ts +25 -3
  107. package/convex/teams.d.ts +21 -0
  108. package/convex/teams.js +215 -0
  109. package/convex/telemetry.d.ts +4 -0
  110. package/convex/telemetry.js +74 -0
  111. package/convex/updateAPIStatus.d.ts +6 -0
  112. package/convex/updateAPIStatus.d.ts.map +1 -1
  113. package/convex/updateAPIStatus.js +39 -0
  114. package/convex/updateAPIStatus.js.map +1 -1
  115. package/convex/usage.d.ts +27 -0
  116. package/convex/usage.js +229 -0
  117. package/convex/waitlist.d.ts +4 -0
  118. package/convex/waitlist.js +49 -0
  119. package/convex/webhooks.d.ts +12 -0
  120. package/convex/webhooks.js +410 -0
  121. package/convex/workspaceSettings.d.ts +7 -0
  122. package/convex/workspaceSettings.d.ts.map +1 -0
  123. package/convex/workspaceSettings.js +128 -0
  124. package/convex/workspaceSettings.js.map +1 -0
  125. package/convex/workspaces.d.ts +33 -0
  126. package/convex/workspaces.d.ts.map +1 -1
  127. package/convex/workspaces.js +989 -0
  128. package/convex/workspaces.js.map +1 -1
  129. package/convex/workspaces.ts +18 -20
  130. package/dist/bin.js +0 -0
  131. package/dist/cli/commands/demo.js +1 -1
  132. package/dist/cli/commands/demo.js.map +1 -1
  133. package/dist/cli/commands/doctor.js.map +1 -1
  134. package/dist/cli/commands/login.js.map +1 -1
  135. package/dist/cli/commands/setup.js.map +1 -1
  136. package/dist/credentials.d.ts.map +1 -1
  137. package/dist/credentials.js +15 -0
  138. package/dist/credentials.js.map +1 -1
  139. package/dist/discovery.js.map +1 -1
  140. package/dist/execute.js.map +1 -1
  141. package/dist/index.js +1 -1
  142. package/dist/index.js.map +1 -1
  143. package/dist/mcp-analytics.js +1 -1
  144. package/dist/mcp-analytics.js.map +1 -1
  145. package/dist/open-apis.d.ts.map +1 -1
  146. package/dist/open-apis.js +94 -2
  147. package/dist/open-apis.js.map +1 -1
  148. package/dist/ui/errors.js.map +1 -1
  149. package/dist/ui/prompts.js.map +1 -1
  150. package/package.json +1 -1
  151. package/src/cli/commands/demo.ts +1 -1
  152. package/src/credentials.ts +16 -0
  153. package/src/index.ts +1 -1
  154. package/src/mcp-analytics.ts +1 -1
  155. package/src/open-apis.ts +114 -4
  156. package/src/types/convex-api.d.ts +20 -0
@@ -0,0 +1,5 @@
1
+ export declare const log: any;
2
+ export declare const getStats: any;
3
+ export declare const getRecent: any;
4
+ export declare const getProviderBreakdown: any;
5
+ //# sourceMappingURL=analytics.d.ts.map
@@ -0,0 +1,167 @@
1
+ import { mutation, query } from "./_generated/server";
2
+ import { v } from "convex/values";
3
+ // Log an analytics event
4
+ export const log = mutation({
5
+ args: {
6
+ event: v.string(),
7
+ provider: v.optional(v.string()),
8
+ query: v.optional(v.string()),
9
+ identifier: v.string(),
10
+ workspaceId: v.optional(v.id("workspaces")),
11
+ metadata: v.optional(v.any()),
12
+ },
13
+ handler: async (ctx, args) => {
14
+ return await ctx.db.insert("analytics", {
15
+ ...args,
16
+ timestamp: Date.now(),
17
+ });
18
+ },
19
+ });
20
+ // Get stats for dashboard
21
+ export const getStats = query({
22
+ args: {
23
+ hoursBack: v.optional(v.number()),
24
+ },
25
+ handler: async (ctx, args) => {
26
+ const hoursBack = args.hoursBack || 24;
27
+ const since = Date.now() - hoursBack * 3600000;
28
+ const events = await ctx.db
29
+ .query("analytics")
30
+ .withIndex("by_timestamp")
31
+ .filter((q) => q.gte(q.field("timestamp"), since))
32
+ .collect();
33
+ // Aggregate stats
34
+ const stats = {
35
+ totalEvents: events.length,
36
+ discoveries: events.filter((e) => e.event === "discovery").length,
37
+ instantCalls: events.filter((e) => e.event === "instant").length,
38
+ uniqueUsers: new Set(events.map((e) => e.identifier)).size,
39
+ byProvider: {},
40
+ topQueries: [],
41
+ hourly: [],
42
+ };
43
+ // By provider
44
+ for (const event of events.filter((e) => e.provider)) {
45
+ stats.byProvider[event.provider] = (stats.byProvider[event.provider] || 0) + 1;
46
+ }
47
+ // Top queries
48
+ const queryCounts = {};
49
+ for (const event of events.filter((e) => e.query)) {
50
+ queryCounts[event.query] = (queryCounts[event.query] || 0) + 1;
51
+ }
52
+ stats.topQueries = Object.entries(queryCounts)
53
+ .sort(([, a], [, b]) => b - a)
54
+ .slice(0, 10)
55
+ .map(([query, count]) => ({ query, count }));
56
+ // Hourly breakdown
57
+ const hourlyCounts = {};
58
+ for (const event of events) {
59
+ const hour = new Date(event.timestamp).toISOString().slice(0, 13);
60
+ hourlyCounts[hour] = (hourlyCounts[hour] || 0) + 1;
61
+ }
62
+ stats.hourly = Object.entries(hourlyCounts)
63
+ .sort(([a], [b]) => a.localeCompare(b))
64
+ .map(([hour, count]) => ({ hour, count }));
65
+ return stats;
66
+ },
67
+ });
68
+ // Get recent events for live feed
69
+ export const getRecent = query({
70
+ args: {
71
+ limit: v.optional(v.number()),
72
+ },
73
+ handler: async (ctx, args) => {
74
+ const limit = args.limit || 50;
75
+ return await ctx.db
76
+ .query("analytics")
77
+ .withIndex("by_timestamp")
78
+ .order("desc")
79
+ .take(limit);
80
+ },
81
+ });
82
+ // Get provider breakdown for Agent Analytics (workspace-specific)
83
+ export const getProviderBreakdown = query({
84
+ args: {
85
+ token: v.string(),
86
+ periodDays: v.optional(v.number()),
87
+ },
88
+ handler: async (ctx, args) => {
89
+ const periodDays = args.periodDays || 7;
90
+ const since = Date.now() - periodDays * 24 * 3600000;
91
+ // Verify session and get workspace
92
+ const session = await ctx.db
93
+ .query("agentSessions")
94
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", args.token))
95
+ .first();
96
+ if (!session) {
97
+ return null;
98
+ }
99
+ // Get all API logs for this workspace
100
+ const logs = await ctx.db
101
+ .query("apiLogs")
102
+ .withIndex("by_workspaceId_createdAt", (q) => q.eq("workspaceId", session.workspaceId))
103
+ .filter((q) => q.gte(q.field("createdAt"), since))
104
+ .collect();
105
+ if (logs.length === 0) {
106
+ return null; // Return null so frontend knows to show empty state, not preview
107
+ }
108
+ // Aggregate stats
109
+ const totalCalls = logs.length;
110
+ const successCount = logs.filter((l) => l.status === "success").length;
111
+ const failureCount = logs.filter((l) => l.status === "error").length;
112
+ const totalLatency = logs.reduce((sum, l) => sum + (l.latencyMs || 0), 0);
113
+ const avgLatency = totalCalls > 0 ? Math.round(totalLatency / totalCalls) : 0;
114
+ // Provider breakdown
115
+ const byProvider = {};
116
+ for (const log of logs) {
117
+ if (!byProvider[log.provider]) {
118
+ byProvider[log.provider] = { count: 0, latency: 0 };
119
+ }
120
+ byProvider[log.provider].count++;
121
+ byProvider[log.provider].latency += log.latencyMs || 0;
122
+ }
123
+ // Agent breakdown (by subagentId)
124
+ const byAgent = {};
125
+ for (const log of logs) {
126
+ const agent = log.subagentId || "main";
127
+ byAgent[agent] = (byAgent[agent] || 0) + 1;
128
+ }
129
+ // Action breakdown
130
+ const byAction = {};
131
+ for (const log of logs) {
132
+ const key = `${log.provider}:${log.action}`;
133
+ byAction[key] = (byAction[key] || 0) + 1;
134
+ }
135
+ // Time series (daily)
136
+ const dailyCounts = {};
137
+ for (const log of logs) {
138
+ const day = new Date(log.createdAt).toISOString().slice(0, 10);
139
+ dailyCounts[day] = (dailyCounts[day] || 0) + 1;
140
+ }
141
+ return {
142
+ totalCalls,
143
+ successCount,
144
+ failureCount,
145
+ successRate: totalCalls > 0 ? (successCount / totalCalls) * 100 : 0,
146
+ avgLatency,
147
+ byProvider: Object.entries(byProvider).map(([name, data]) => ({
148
+ name,
149
+ count: data.count,
150
+ avgLatency: data.count > 0 ? Math.round(data.latency / data.count) : 0,
151
+ })).sort((a, b) => b.count - a.count),
152
+ byAgent: Object.entries(byAgent).map(([name, count]) => ({
153
+ name,
154
+ count,
155
+ })).sort((a, b) => b.count - a.count),
156
+ byAction: Object.entries(byAction).map(([name, count]) => ({
157
+ name,
158
+ count,
159
+ })).sort((a, b) => b.count - a.count).slice(0, 10),
160
+ timeSeries: Object.entries(dailyCounts)
161
+ .sort(([a], [b]) => a.localeCompare(b))
162
+ .map(([date, count]) => ({ date, count })),
163
+ isPreview: false,
164
+ };
165
+ },
166
+ });
167
+ //# sourceMappingURL=analytics.js.map
@@ -0,0 +1,6 @@
1
+ export declare const generateKey: any;
2
+ export declare const listKeys: any;
3
+ export declare const revokeKey: any;
4
+ export declare const resolveKey: any;
5
+ export declare const touchKey: any;
6
+ //# sourceMappingURL=apiKeys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiKeys.d.ts","sourceRoot":"","sources":["apiKeys.ts"],"names":[],"mappings":"AA+CA,eAAO,MAAM,WAAW,KAwDtB,CAAC;AAMH,eAAO,MAAM,QAAQ,KAgCnB,CAAC;AAMH,eAAO,MAAM,SAAS,KA2BpB,CAAC;AAMH,eAAO,MAAM,UAAU,KA0BrB,CAAC;AAMH,eAAO,MAAM,QAAQ,KAOnB,CAAC"}
@@ -0,0 +1,186 @@
1
+ import { v } from "convex/values";
2
+ import { mutation, query, internalQuery } from "./_generated/server";
3
+ // ============================================
4
+ // WORKSPACE API KEYS
5
+ // Generate persistent API keys for programmatic access.
6
+ // Users generate keys in the dashboard, then use them
7
+ // in any agent config, automation, or script.
8
+ // ============================================
9
+ function generateRawKey() {
10
+ const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
11
+ let result = "";
12
+ for (let i = 0; i < 48; i++) {
13
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
14
+ }
15
+ return `sk-claw-${result}`;
16
+ }
17
+ // Simple hash for key lookup (SHA-256 not available in Convex runtime, use deterministic hash)
18
+ function hashKey(key) {
19
+ let hash = 0;
20
+ for (let i = 0; i < key.length; i++) {
21
+ const char = key.charCodeAt(i);
22
+ hash = ((hash << 5) - hash + char) | 0;
23
+ }
24
+ // Create a longer hash by running multiple rounds with offsets
25
+ let h1 = hash;
26
+ let h2 = 0;
27
+ for (let i = 0; i < key.length; i++) {
28
+ h2 = ((h2 << 7) - h2 + key.charCodeAt(i) * 31) | 0;
29
+ }
30
+ let h3 = 0;
31
+ for (let i = 0; i < key.length; i++) {
32
+ h3 = ((h3 << 11) - h3 + key.charCodeAt(i) * 127) | 0;
33
+ }
34
+ return `${(h1 >>> 0).toString(36)}-${(h2 >>> 0).toString(36)}-${(h3 >>> 0).toString(36)}`;
35
+ }
36
+ function getKeyPrefix(key) {
37
+ return `sk-claw-...${key.slice(-4)}`;
38
+ }
39
+ // ============================================
40
+ // GENERATE KEY
41
+ // ============================================
42
+ export const generateKey = mutation({
43
+ args: {
44
+ token: v.string(), // session token for auth
45
+ name: v.string(), // user label
46
+ },
47
+ handler: async (ctx, args) => {
48
+ // Auth via agentSession
49
+ const session = await ctx.db
50
+ .query("agentSessions")
51
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", args.token))
52
+ .first();
53
+ if (!session) {
54
+ throw new Error("Invalid session");
55
+ }
56
+ const workspaceId = session.workspaceId;
57
+ // Limit: max 5 active keys per workspace
58
+ const existingKeys = await ctx.db
59
+ .query("workspaceApiKeys")
60
+ .withIndex("by_workspaceId", (q) => q.eq("workspaceId", workspaceId))
61
+ .collect();
62
+ const activeKeys = existingKeys.filter((k) => !k.revokedAt);
63
+ if (activeKeys.length >= 5) {
64
+ throw new Error("Maximum 5 active keys per workspace. Revoke an existing key first.");
65
+ }
66
+ // Check for duplicate name
67
+ const nameExists = activeKeys.some((k) => k.name.toLowerCase() === args.name.toLowerCase());
68
+ if (nameExists) {
69
+ throw new Error(`A key named "${args.name}" already exists.`);
70
+ }
71
+ const rawKey = generateRawKey();
72
+ const now = Date.now();
73
+ await ctx.db.insert("workspaceApiKeys", {
74
+ workspaceId,
75
+ key: "", // We don't store the raw key
76
+ keyHash: hashKey(rawKey),
77
+ keyPrefix: getKeyPrefix(rawKey),
78
+ name: args.name,
79
+ createdAt: now,
80
+ });
81
+ // Return the raw key ONCE - it won't be retrievable again
82
+ return {
83
+ key: rawKey,
84
+ keyPrefix: getKeyPrefix(rawKey),
85
+ name: args.name,
86
+ };
87
+ },
88
+ });
89
+ // ============================================
90
+ // LIST KEYS
91
+ // ============================================
92
+ export const listKeys = query({
93
+ args: {
94
+ token: v.string(),
95
+ },
96
+ handler: async (ctx, args) => {
97
+ const session = await ctx.db
98
+ .query("agentSessions")
99
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", args.token))
100
+ .first();
101
+ if (!session) {
102
+ return { keys: [] };
103
+ }
104
+ const keys = await ctx.db
105
+ .query("workspaceApiKeys")
106
+ .withIndex("by_workspaceId", (q) => q.eq("workspaceId", session.workspaceId))
107
+ .collect();
108
+ return {
109
+ keys: keys
110
+ .filter((k) => !k.revokedAt)
111
+ .map((k) => ({
112
+ id: k._id,
113
+ name: k.name,
114
+ keyPrefix: k.keyPrefix,
115
+ lastUsedAt: k.lastUsedAt,
116
+ createdAt: k.createdAt,
117
+ }))
118
+ .sort((a, b) => b.createdAt - a.createdAt),
119
+ };
120
+ },
121
+ });
122
+ // ============================================
123
+ // REVOKE KEY
124
+ // ============================================
125
+ export const revokeKey = mutation({
126
+ args: {
127
+ token: v.string(),
128
+ keyId: v.id("workspaceApiKeys"),
129
+ },
130
+ handler: async (ctx, args) => {
131
+ const session = await ctx.db
132
+ .query("agentSessions")
133
+ .withIndex("by_sessionToken", (q) => q.eq("sessionToken", args.token))
134
+ .first();
135
+ if (!session) {
136
+ throw new Error("Invalid session");
137
+ }
138
+ const key = await ctx.db.get(args.keyId);
139
+ if (!key || key.workspaceId !== session.workspaceId) {
140
+ throw new Error("Key not found");
141
+ }
142
+ if (key.revokedAt) {
143
+ throw new Error("Key already revoked");
144
+ }
145
+ await ctx.db.patch(args.keyId, { revokedAt: Date.now() });
146
+ return { success: true };
147
+ },
148
+ });
149
+ // ============================================
150
+ // RESOLVE KEY (internal - used by gateway)
151
+ // ============================================
152
+ export const resolveKey = internalQuery({
153
+ args: {
154
+ rawKey: v.string(),
155
+ },
156
+ handler: async (ctx, args) => {
157
+ const keyHash = hashKey(args.rawKey);
158
+ const keyDoc = await ctx.db
159
+ .query("workspaceApiKeys")
160
+ .withIndex("by_keyHash", (q) => q.eq("keyHash", keyHash))
161
+ .first();
162
+ if (!keyDoc) {
163
+ return null;
164
+ }
165
+ if (keyDoc.revokedAt) {
166
+ return null;
167
+ }
168
+ return {
169
+ workspaceId: keyDoc.workspaceId,
170
+ keyId: keyDoc._id,
171
+ name: keyDoc.name,
172
+ };
173
+ },
174
+ });
175
+ // ============================================
176
+ // TOUCH KEY (internal - update lastUsedAt)
177
+ // ============================================
178
+ export const touchKey = mutation({
179
+ args: {
180
+ keyId: v.id("workspaceApiKeys"),
181
+ },
182
+ handler: async (ctx, args) => {
183
+ await ctx.db.patch(args.keyId, { lastUsedAt: Date.now() });
184
+ },
185
+ });
186
+ //# sourceMappingURL=apiKeys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiKeys.js","sourceRoot":"","sources":["apiKeys.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const run: any;
2
+ //# sourceMappingURL=backfillAnalytics.d.ts.map
@@ -0,0 +1,20 @@
1
+ import { mutation } from "./_generated/server";
2
+ export const run = mutation({
3
+ args: {},
4
+ handler: async (ctx) => {
5
+ const APILAYER_WORKSPACE_ID = "n17bf4raa01r0d4na0bsgg117x83y551";
6
+ const events = await ctx.db
7
+ .query("analytics")
8
+ .withIndex("by_provider", (q) => q.eq("provider", "apilayer"))
9
+ .collect();
10
+ let patched = 0;
11
+ for (const e of events) {
12
+ if (!e.workspaceId) {
13
+ await ctx.db.patch(e._id, { workspaceId: APILAYER_WORKSPACE_ID });
14
+ patched++;
15
+ }
16
+ }
17
+ return { patched };
18
+ },
19
+ });
20
+ //# sourceMappingURL=backfillAnalytics.js.map
@@ -0,0 +1,2 @@
1
+ export declare const run: any;
2
+ //# sourceMappingURL=backfillSearchLogs.d.ts.map
@@ -0,0 +1,29 @@
1
+ import { mutation } from "./_generated/server";
2
+ // Backfill searchLogs from apiLogs that have action starting with "discovery:"
3
+ export const run = mutation({
4
+ args: {},
5
+ handler: async (ctx) => {
6
+ const APILAYER_WORKSPACE_ID = "n17bf4raa01r0d4na0bsgg117x83y551";
7
+ const apiLogs = await ctx.db
8
+ .query("apiLogs")
9
+ .withIndex("by_workspaceId_createdAt", (q) => q.eq("workspaceId", APILAYER_WORKSPACE_ID))
10
+ .collect();
11
+ const discoveryLogs = apiLogs.filter((l) => typeof l.action === "string" && l.action.startsWith("discovery:"));
12
+ let inserted = 0;
13
+ for (const log of discoveryLogs) {
14
+ const query = log.action.replace("discovery:", "").trim();
15
+ await ctx.db.insert("searchLogs", {
16
+ workspaceId: APILAYER_WORKSPACE_ID,
17
+ query,
18
+ resultCount: 1,
19
+ hasResults: true,
20
+ matchedProviders: ["apilayer"],
21
+ responseTimeMs: log.latencyMs || 20,
22
+ timestamp: log.createdAt,
23
+ });
24
+ inserted++;
25
+ }
26
+ return { inserted, total: discoveryLogs.length };
27
+ },
28
+ });
29
+ //# sourceMappingURL=backfillSearchLogs.js.map
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Link a Stripe customer to a workspace
3
+ */
4
+ export declare const linkCustomer: any;
5
+ /**
6
+ * Update subscription status for a workspace
7
+ */
8
+ export declare const updateSubscription: any;
9
+ /**
10
+ * Record daily usage for billing
11
+ */
12
+ export declare const recordUsage: any;
13
+ /**
14
+ * Process a successful payment (from webhook)
15
+ */
16
+ export declare const processPayment: any;
17
+ /**
18
+ * Increment credit balance (for prepaid credits)
19
+ */
20
+ export declare const incrementCredits: any;
21
+ /**
22
+ * Decrement credit balance (when using prepaid credits)
23
+ */
24
+ export declare const decrementCredits: any;
25
+ /**
26
+ * Mark usage as reported to Stripe
27
+ */
28
+ export declare const markUsageReported: any;
29
+ /**
30
+ * Update invoice status (from webhook)
31
+ */
32
+ export declare const updateInvoiceStatus: any;
33
+ /**
34
+ * Reset usage count on subscription cancellation
35
+ * Gives user a clean slate when downgrading to free
36
+ */
37
+ export declare const resetUsageOnCancellation: any;
38
+ /**
39
+ * Update payment method info (from webhook)
40
+ */
41
+ export declare const updatePaymentMethodInfo: any;
42
+ /**
43
+ * Get billing info for a workspace
44
+ */
45
+ export declare const getInfo: any;
46
+ /**
47
+ * Get current period usage
48
+ */
49
+ export declare const getCurrentUsage: any;
50
+ /**
51
+ * Get invoices for a workspace
52
+ */
53
+ export declare const getInvoices: any;
54
+ /**
55
+ * Get unreported usage records (for cron job)
56
+ */
57
+ export declare const getUnreportedUsage: any;
58
+ /**
59
+ * Get workspace by Stripe customer ID
60
+ */
61
+ export declare const getByStripeCustomerId: any;
62
+ /**
63
+ * Get workspace by ID
64
+ */
65
+ export declare const getWorkspace: any;
66
+ /**
67
+ * Get all workspaces with active Stripe subscriptions (internal)
68
+ */
69
+ export declare const getActiveSubscriptions: any;
70
+ /**
71
+ * Get unreported usage records for a specific workspace (internal)
72
+ */
73
+ export declare const getUnreportedUsageForWorkspace: any;
74
+ /**
75
+ * Mark multiple usage records as reported (internal)
76
+ */
77
+ export declare const markUsageRecordsReported: any;
78
+ /**
79
+ * Report usage to Stripe for a single workspace
80
+ * Internal action - called by the daily cron
81
+ */
82
+ export declare const reportUsageToStripe: any;
83
+ /**
84
+ * Daily cron job: Report all unreported usage to Stripe
85
+ * Runs at 00:05 UTC
86
+ */
87
+ export declare const reportAllUsageToStripe: any;
88
+ //# sourceMappingURL=billing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["billing.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,eAAO,MAAM,YAAY,KAkBvB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAgD7B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,KAmCtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,KA6CzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,KAqB3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,KAyB3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAY5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB,KAuB9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,KAiBnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB,KAwBlC,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,OAAO,KAqElB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe,KA+C1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,KA6BtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAU7B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,qBAAqB,KAYhC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY,KAOvB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,sBAAsB,KAcjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,8BAA8B,KAWzC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB,KAenC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KAsG9B,CAAC;AAmBH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAwDjC,CAAC"}
1
+ {"version":3,"file":"billing.d.ts","sourceRoot":"","sources":["billing.ts"],"names":[],"mappings":"AAmBA;;GAEG;AACH,eAAO,MAAM,YAAY,KAkBvB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAoC7B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,KAmCtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,KA6CzB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,KAqB3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,gBAAgB,KAyB3B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,iBAAiB,KAY5B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,mBAAmB,KAuB9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,wBAAwB,KAiBnC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,uBAAuB,KAwBlC,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,OAAO,KAqElB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,eAAe,KA+C1B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,KA6BtB,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,kBAAkB,KAU7B,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,qBAAqB,KAYhC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,YAAY,KAOvB,CAAC;AAMH;;GAEG;AACH,eAAO,MAAM,sBAAsB,KAcjC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,8BAA8B,KAWzC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,wBAAwB,KAenC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,KAsG9B,CAAC;AAmBH;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAwDjC,CAAC"}