@niama/loops 0.2.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 (74) hide show
  1. package/README.md +506 -0
  2. package/dist/client/index.d.ts +510 -0
  3. package/dist/client/index.d.ts.map +1 -0
  4. package/dist/client/index.js +464 -0
  5. package/dist/component/_generated/api.d.ts +232 -0
  6. package/dist/component/_generated/api.d.ts.map +1 -0
  7. package/dist/component/_generated/api.js +30 -0
  8. package/dist/component/_generated/component.d.ts +245 -0
  9. package/dist/component/_generated/component.d.ts.map +1 -0
  10. package/dist/component/_generated/component.js +9 -0
  11. package/dist/component/_generated/dataModel.d.ts +46 -0
  12. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  13. package/dist/component/_generated/dataModel.js +10 -0
  14. package/dist/component/_generated/server.d.ts +121 -0
  15. package/dist/component/_generated/server.d.ts.map +1 -0
  16. package/dist/component/_generated/server.js +77 -0
  17. package/dist/component/actions.d.ts +159 -0
  18. package/dist/component/actions.d.ts.map +1 -0
  19. package/dist/component/actions.js +468 -0
  20. package/dist/component/aggregates.d.ts +42 -0
  21. package/dist/component/aggregates.d.ts.map +1 -0
  22. package/dist/component/aggregates.js +54 -0
  23. package/dist/component/convex.config.d.ts +3 -0
  24. package/dist/component/convex.config.d.ts.map +1 -0
  25. package/dist/component/convex.config.js +5 -0
  26. package/dist/component/helpers.d.ts +16 -0
  27. package/dist/component/helpers.d.ts.map +1 -0
  28. package/dist/component/helpers.js +98 -0
  29. package/dist/component/http.d.ts +3 -0
  30. package/dist/component/http.d.ts.map +1 -0
  31. package/dist/component/http.js +208 -0
  32. package/dist/component/mutations.d.ts +55 -0
  33. package/dist/component/mutations.d.ts.map +1 -0
  34. package/dist/component/mutations.js +167 -0
  35. package/dist/component/queries.d.ts +171 -0
  36. package/dist/component/queries.d.ts.map +1 -0
  37. package/dist/component/queries.js +516 -0
  38. package/dist/component/schema.d.ts +63 -0
  39. package/dist/component/schema.d.ts.map +1 -0
  40. package/dist/component/schema.js +16 -0
  41. package/dist/component/tables/contacts.d.ts +16 -0
  42. package/dist/component/tables/contacts.d.ts.map +1 -0
  43. package/dist/component/tables/contacts.js +16 -0
  44. package/dist/component/tables/emailOperations.d.ts +17 -0
  45. package/dist/component/tables/emailOperations.d.ts.map +1 -0
  46. package/dist/component/tables/emailOperations.js +17 -0
  47. package/dist/component/validators.d.ts +338 -0
  48. package/dist/component/validators.d.ts.map +1 -0
  49. package/dist/component/validators.js +167 -0
  50. package/dist/test.d.ts +78 -0
  51. package/dist/test.d.ts.map +1 -0
  52. package/dist/test.js +16 -0
  53. package/dist/types.d.ts +39 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +0 -0
  56. package/package.json +112 -0
  57. package/src/client/index.ts +618 -0
  58. package/src/component/_generated/api.ts +253 -0
  59. package/src/component/_generated/component.ts +291 -0
  60. package/src/component/_generated/dataModel.ts +60 -0
  61. package/src/component/_generated/server.ts +161 -0
  62. package/src/component/actions.ts +556 -0
  63. package/src/component/aggregates.ts +89 -0
  64. package/src/component/convex.config.ts +8 -0
  65. package/src/component/helpers.ts +130 -0
  66. package/src/component/http.ts +236 -0
  67. package/src/component/mutations.ts +192 -0
  68. package/src/component/queries.ts +604 -0
  69. package/src/component/schema.ts +17 -0
  70. package/src/component/tables/contacts.ts +17 -0
  71. package/src/component/tables/emailOperations.ts +23 -0
  72. package/src/component/validators.ts +197 -0
  73. package/src/test.ts +27 -0
  74. package/src/types.ts +62 -0
@@ -0,0 +1,464 @@
1
+ import { actionGeneric, mutationGeneric, queryGeneric } from "convex/server";
2
+ import { v } from "convex/values";
3
+ export class Loops {
4
+ options;
5
+ actions;
6
+ queries;
7
+ mutations;
8
+ _apiKey;
9
+ constructor(component, options) {
10
+ if (!component) {
11
+ throw new Error("Loops component reference is required. " +
12
+ "Make sure the component is mounted in your convex.config.ts and use: " +
13
+ "new Loops(components.loops)");
14
+ }
15
+ if (!component.actions || !component.queries || !component.mutations) {
16
+ throw new Error("Invalid component reference. " +
17
+ "The component may not be properly mounted. " +
18
+ "Ensure the component is correctly mounted in convex.config.ts: " +
19
+ "app.use(loops);");
20
+ }
21
+ this.actions = component.actions;
22
+ this.queries = component.queries;
23
+ this.mutations = component.mutations;
24
+ this.options = options;
25
+ this._apiKey = options?.apiKey;
26
+ if (options?.apiKey) {
27
+ console.warn("API key passed directly via options. " +
28
+ "For security, use LOOPS_API_KEY environment variable instead. " +
29
+ "See README.md for details.");
30
+ }
31
+ }
32
+ /**
33
+ * Get the API key, checking environment at call time (not constructor time).
34
+ * This allows the Loops client to be instantiated at module load time.
35
+ */
36
+ get apiKey() {
37
+ const key = this._apiKey ?? process.env.LOOPS_API_KEY;
38
+ if (!key) {
39
+ throw new Error("Loops API key is required. Set LOOPS_API_KEY in your Convex environment variables.");
40
+ }
41
+ return key;
42
+ }
43
+ /**
44
+ * Add or update a contact in Loops
45
+ */
46
+ async addContact(ctx, contact) {
47
+ return ctx.runAction(this.actions.addContact, {
48
+ apiKey: this.apiKey,
49
+ contact,
50
+ });
51
+ }
52
+ /**
53
+ * Update an existing contact in Loops
54
+ */
55
+ async updateContact(ctx, email, updates) {
56
+ return ctx.runAction(this.actions.updateContact, {
57
+ apiKey: this.apiKey,
58
+ email,
59
+ ...updates,
60
+ });
61
+ }
62
+ /**
63
+ * Send a transactional email using a transactional ID
64
+ */
65
+ async sendTransactional(ctx, options) {
66
+ return ctx.runAction(this.actions.sendTransactional, {
67
+ apiKey: this.apiKey,
68
+ ...options,
69
+ });
70
+ }
71
+ /**
72
+ * Send an event to Loops to trigger email workflows
73
+ */
74
+ async sendEvent(ctx, options) {
75
+ return ctx.runAction(this.actions.sendEvent, {
76
+ apiKey: this.apiKey,
77
+ ...options,
78
+ });
79
+ }
80
+ /**
81
+ * Find a contact by email
82
+ * Retrieves contact information from Loops
83
+ */
84
+ async findContact(ctx, email) {
85
+ return ctx.runAction(this.actions.findContact, {
86
+ apiKey: this.apiKey,
87
+ email,
88
+ });
89
+ }
90
+ /**
91
+ * Batch create contacts
92
+ * Create multiple contacts in a single API call
93
+ */
94
+ async batchCreateContacts(ctx, contacts) {
95
+ return ctx.runAction(this.actions.batchCreateContacts, {
96
+ apiKey: this.apiKey,
97
+ contacts,
98
+ });
99
+ }
100
+ /**
101
+ * Unsubscribe a contact
102
+ * Unsubscribes a contact from receiving emails (they remain in the system)
103
+ */
104
+ async unsubscribeContact(ctx, email) {
105
+ return ctx.runAction(this.actions.unsubscribeContact, {
106
+ apiKey: this.apiKey,
107
+ email,
108
+ });
109
+ }
110
+ /**
111
+ * Resubscribe a contact
112
+ * Resubscribes a previously unsubscribed contact
113
+ */
114
+ async resubscribeContact(ctx, email) {
115
+ return ctx.runAction(this.actions.resubscribeContact, {
116
+ apiKey: this.apiKey,
117
+ email,
118
+ });
119
+ }
120
+ /**
121
+ * Count contacts in the database
122
+ * Can filter by audience criteria (userGroup, source, subscribed status)
123
+ * This queries the component's local database, not Loops API
124
+ */
125
+ async countContacts(ctx, options) {
126
+ return ctx.runQuery(this.queries.countContacts, options ?? {});
127
+ }
128
+ /**
129
+ * List contacts with cursor-based pagination and optional filters
130
+ * Returns actual contact data, not just a count
131
+ * This queries the component's local database, not Loops API
132
+ *
133
+ * Uses cursor-based pagination for efficiency. Pass the `continueCursor`
134
+ * from the previous response as `cursor` to get the next page.
135
+ */
136
+ async listContacts(ctx, options) {
137
+ return ctx.runQuery(this.queries.listContacts, {
138
+ userGroup: options?.userGroup,
139
+ source: options?.source,
140
+ subscribed: options?.subscribed,
141
+ limit: options?.limit ?? 100,
142
+ cursor: options?.cursor ?? null,
143
+ });
144
+ }
145
+ /**
146
+ * Detect spam patterns: emails sent to the same recipient too frequently
147
+ */
148
+ async detectRecipientSpam(ctx, options) {
149
+ return ctx.runQuery(this.queries.detectRecipientSpam, {
150
+ timeWindowMs: options?.timeWindowMs ?? 3600000,
151
+ maxEmailsPerRecipient: options?.maxEmailsPerRecipient ?? 10,
152
+ });
153
+ }
154
+ /**
155
+ * Detect spam patterns: emails sent by the same actor/user too frequently
156
+ */
157
+ async detectActorSpam(ctx, options) {
158
+ return ctx.runQuery(this.queries.detectActorSpam, {
159
+ timeWindowMs: options?.timeWindowMs ?? 3600000,
160
+ maxEmailsPerActor: options?.maxEmailsPerActor ?? 100,
161
+ });
162
+ }
163
+ /**
164
+ * Get email operation statistics for monitoring
165
+ */
166
+ async getEmailStats(ctx, options) {
167
+ return ctx.runQuery(this.queries.getEmailStats, {
168
+ timeWindowMs: options?.timeWindowMs ?? 86400000,
169
+ });
170
+ }
171
+ /**
172
+ * Detect rapid-fire email sending patterns
173
+ */
174
+ async detectRapidFirePatterns(ctx, options) {
175
+ return ctx.runQuery(this.queries.detectRapidFirePatterns, {
176
+ timeWindowMs: options?.timeWindowMs ?? 60000,
177
+ minEmailsInWindow: options?.minEmailsInWindow ?? 5,
178
+ });
179
+ }
180
+ /**
181
+ * Check if an email can be sent to a recipient based on rate limits
182
+ */
183
+ async checkRecipientRateLimit(ctx, options) {
184
+ return ctx.runQuery(this.queries.checkRecipientRateLimit, options);
185
+ }
186
+ /**
187
+ * Check if an actor/user can send more emails based on rate limits
188
+ */
189
+ async checkActorRateLimit(ctx, options) {
190
+ return ctx.runQuery(this.queries.checkActorRateLimit, options);
191
+ }
192
+ /**
193
+ * Check global email sending rate limit
194
+ */
195
+ async checkGlobalRateLimit(ctx, options) {
196
+ return ctx.runQuery(this.queries.checkGlobalRateLimit, options);
197
+ }
198
+ /**
199
+ * Delete a contact from Loops
200
+ */
201
+ async deleteContact(ctx, email) {
202
+ return ctx.runAction(this.actions.deleteContact, {
203
+ apiKey: this.apiKey,
204
+ email,
205
+ });
206
+ }
207
+ /**
208
+ * Trigger a loop for a contact
209
+ * Loops are automated email sequences that can be triggered by events
210
+ *
211
+ * Note: Loops.so doesn't have a direct loop trigger endpoint.
212
+ * Loops are triggered through events. Make sure your loop is configured
213
+ * in the Loops dashboard to listen for events.
214
+ *
215
+ * @param options.eventName - Optional event name. If not provided, uses `loop_{loopId}`
216
+ */
217
+ async triggerLoop(ctx, options) {
218
+ return ctx.runAction(this.actions.triggerLoop, {
219
+ apiKey: this.apiKey,
220
+ ...options,
221
+ });
222
+ }
223
+ /**
224
+ * Backfill the contact aggregate with existing contacts.
225
+ * Run this after upgrading to a version with aggregate support.
226
+ *
227
+ * This processes contacts in batches to avoid timeout issues with large datasets.
228
+ * Call repeatedly with the returned cursor until isDone is true.
229
+ *
230
+ * Usage:
231
+ * ```ts
232
+ * // First call - clear existing aggregate and start backfill
233
+ * let result = await loops.backfillContactAggregate(ctx, { clear: true });
234
+ *
235
+ * // Continue until done
236
+ * while (!result.isDone) {
237
+ * result = await loops.backfillContactAggregate(ctx, { cursor: result.cursor });
238
+ * }
239
+ * ```
240
+ */
241
+ async backfillContactAggregate(ctx, options) {
242
+ return ctx.runMutation(this.mutations.backfillContactAggregate, {
243
+ cursor: options?.cursor ?? null,
244
+ batchSize: options?.batchSize ?? 100,
245
+ clear: options?.clear,
246
+ });
247
+ }
248
+ /**
249
+ * For easy re-exporting.
250
+ * Apps can do
251
+ * ```ts
252
+ * export const { addContact, sendTransactional, sendEvent, triggerLoop } = loops.api();
253
+ * ```
254
+ */
255
+ api() {
256
+ return {
257
+ addContact: actionGeneric({
258
+ args: {
259
+ email: v.string(),
260
+ firstName: v.optional(v.string()),
261
+ lastName: v.optional(v.string()),
262
+ userId: v.optional(v.string()),
263
+ source: v.optional(v.string()),
264
+ subscribed: v.optional(v.boolean()),
265
+ userGroup: v.optional(v.string()),
266
+ },
267
+ handler: async (ctx, args) => {
268
+ return await this.addContact(ctx, args);
269
+ },
270
+ }),
271
+ updateContact: actionGeneric({
272
+ args: {
273
+ email: v.string(),
274
+ firstName: v.optional(v.string()),
275
+ lastName: v.optional(v.string()),
276
+ userId: v.optional(v.string()),
277
+ source: v.optional(v.string()),
278
+ subscribed: v.optional(v.boolean()),
279
+ userGroup: v.optional(v.string()),
280
+ dataVariables: v.optional(v.any()),
281
+ },
282
+ handler: async (ctx, args) => {
283
+ const { email, ...updates } = args;
284
+ return await this.updateContact(ctx, email, updates);
285
+ },
286
+ }),
287
+ sendTransactional: actionGeneric({
288
+ args: {
289
+ transactionalId: v.string(),
290
+ email: v.string(),
291
+ dataVariables: v.optional(v.any()),
292
+ idempotencyKey: v.optional(v.string()),
293
+ },
294
+ handler: async (ctx, args) => {
295
+ return await this.sendTransactional(ctx, args);
296
+ },
297
+ }),
298
+ sendEvent: actionGeneric({
299
+ args: {
300
+ email: v.string(),
301
+ eventName: v.string(),
302
+ eventProperties: v.optional(v.any()),
303
+ },
304
+ handler: async (ctx, args) => {
305
+ return await this.sendEvent(ctx, args);
306
+ },
307
+ }),
308
+ deleteContact: actionGeneric({
309
+ args: {
310
+ email: v.string(),
311
+ },
312
+ handler: async (ctx, args) => {
313
+ return await this.deleteContact(ctx, args.email);
314
+ },
315
+ }),
316
+ triggerLoop: actionGeneric({
317
+ args: {
318
+ loopId: v.string(),
319
+ email: v.string(),
320
+ dataVariables: v.optional(v.any()),
321
+ },
322
+ handler: async (ctx, args) => {
323
+ return await this.triggerLoop(ctx, args);
324
+ },
325
+ }),
326
+ findContact: actionGeneric({
327
+ args: {
328
+ email: v.string(),
329
+ },
330
+ handler: async (ctx, args) => {
331
+ return await this.findContact(ctx, args.email);
332
+ },
333
+ }),
334
+ batchCreateContacts: actionGeneric({
335
+ args: {
336
+ contacts: v.array(v.object({
337
+ email: v.string(),
338
+ firstName: v.optional(v.string()),
339
+ lastName: v.optional(v.string()),
340
+ userId: v.optional(v.string()),
341
+ source: v.optional(v.string()),
342
+ subscribed: v.optional(v.boolean()),
343
+ userGroup: v.optional(v.string()),
344
+ })),
345
+ },
346
+ handler: async (ctx, args) => {
347
+ return await this.batchCreateContacts(ctx, args.contacts);
348
+ },
349
+ }),
350
+ unsubscribeContact: actionGeneric({
351
+ args: {
352
+ email: v.string(),
353
+ },
354
+ handler: async (ctx, args) => {
355
+ return await this.unsubscribeContact(ctx, args.email);
356
+ },
357
+ }),
358
+ resubscribeContact: actionGeneric({
359
+ args: {
360
+ email: v.string(),
361
+ },
362
+ handler: async (ctx, args) => {
363
+ return await this.resubscribeContact(ctx, args.email);
364
+ },
365
+ }),
366
+ countContacts: queryGeneric({
367
+ args: {
368
+ userGroup: v.optional(v.string()),
369
+ source: v.optional(v.string()),
370
+ subscribed: v.optional(v.boolean()),
371
+ },
372
+ handler: async (ctx, args) => {
373
+ return await this.countContacts(ctx, args);
374
+ },
375
+ }),
376
+ listContacts: queryGeneric({
377
+ args: {
378
+ userGroup: v.optional(v.string()),
379
+ source: v.optional(v.string()),
380
+ subscribed: v.optional(v.boolean()),
381
+ limit: v.optional(v.number()),
382
+ cursor: v.optional(v.union(v.string(), v.null())),
383
+ },
384
+ handler: async (ctx, args) => {
385
+ return await this.listContacts(ctx, args);
386
+ },
387
+ }),
388
+ detectRecipientSpam: queryGeneric({
389
+ args: {
390
+ timeWindowMs: v.optional(v.number()),
391
+ maxEmailsPerRecipient: v.optional(v.number()),
392
+ },
393
+ handler: async (ctx, args) => {
394
+ return await this.detectRecipientSpam(ctx, args);
395
+ },
396
+ }),
397
+ detectActorSpam: queryGeneric({
398
+ args: {
399
+ timeWindowMs: v.optional(v.number()),
400
+ maxEmailsPerActor: v.optional(v.number()),
401
+ },
402
+ handler: async (ctx, args) => {
403
+ return await this.detectActorSpam(ctx, args);
404
+ },
405
+ }),
406
+ getEmailStats: queryGeneric({
407
+ args: {
408
+ timeWindowMs: v.optional(v.number()),
409
+ },
410
+ handler: async (ctx, args) => {
411
+ return await this.getEmailStats(ctx, args);
412
+ },
413
+ }),
414
+ detectRapidFirePatterns: queryGeneric({
415
+ args: {
416
+ timeWindowMs: v.optional(v.number()),
417
+ minEmailsInWindow: v.optional(v.number()),
418
+ },
419
+ handler: async (ctx, args) => {
420
+ return await this.detectRapidFirePatterns(ctx, args);
421
+ },
422
+ }),
423
+ checkRecipientRateLimit: queryGeneric({
424
+ args: {
425
+ email: v.string(),
426
+ timeWindowMs: v.number(),
427
+ maxEmails: v.number(),
428
+ },
429
+ handler: async (ctx, args) => {
430
+ return await this.checkRecipientRateLimit(ctx, args);
431
+ },
432
+ }),
433
+ checkActorRateLimit: queryGeneric({
434
+ args: {
435
+ actorId: v.string(),
436
+ timeWindowMs: v.number(),
437
+ maxEmails: v.number(),
438
+ },
439
+ handler: async (ctx, args) => {
440
+ return await this.checkActorRateLimit(ctx, args);
441
+ },
442
+ }),
443
+ checkGlobalRateLimit: queryGeneric({
444
+ args: {
445
+ timeWindowMs: v.number(),
446
+ maxEmails: v.number(),
447
+ },
448
+ handler: async (ctx, args) => {
449
+ return await this.checkGlobalRateLimit(ctx, args);
450
+ },
451
+ }),
452
+ backfillContactAggregate: mutationGeneric({
453
+ args: {
454
+ cursor: v.optional(v.union(v.string(), v.null())),
455
+ batchSize: v.optional(v.number()),
456
+ clear: v.optional(v.boolean()),
457
+ },
458
+ handler: async (ctx, args) => {
459
+ return await this.backfillContactAggregate(ctx, args);
460
+ },
461
+ }),
462
+ };
463
+ }
464
+ }
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Generated `api` utility.
3
+ *
4
+ * THIS CODE IS AUTOMATICALLY GENERATED.
5
+ *
6
+ * To regenerate, run `npx convex dev`.
7
+ * @module
8
+ */
9
+ import type * as actions from "../actions.js";
10
+ import type * as aggregates from "../aggregates.js";
11
+ import type * as helpers from "../helpers.js";
12
+ import type * as http from "../http.js";
13
+ import type * as mutations from "../mutations.js";
14
+ import type * as queries from "../queries.js";
15
+ import type * as tables_contacts from "../tables/contacts.js";
16
+ import type * as tables_emailOperations from "../tables/emailOperations.js";
17
+ import type * as validators from "../validators.js";
18
+ import type { ApiFromModules, FilterApi, FunctionReference } from "convex/server";
19
+ declare const fullApi: ApiFromModules<{
20
+ actions: typeof actions;
21
+ aggregates: typeof aggregates;
22
+ helpers: typeof helpers;
23
+ http: typeof http;
24
+ mutations: typeof mutations;
25
+ queries: typeof queries;
26
+ "tables/contacts": typeof tables_contacts;
27
+ "tables/emailOperations": typeof tables_emailOperations;
28
+ validators: typeof validators;
29
+ }>;
30
+ /**
31
+ * A utility for referencing Convex functions in your app's public API.
32
+ *
33
+ * Usage:
34
+ * ```js
35
+ * const myFunctionReference = api.myModule.myFunction;
36
+ * ```
37
+ */
38
+ export declare const api: FilterApi<typeof fullApi, FunctionReference<any, "public">>;
39
+ /**
40
+ * A utility for referencing Convex functions in your app's internal API.
41
+ *
42
+ * Usage:
43
+ * ```js
44
+ * const myFunctionReference = internal.myModule.myFunction;
45
+ * ```
46
+ */
47
+ export declare const internal: FilterApi<typeof fullApi, FunctionReference<any, "internal">>;
48
+ export declare const components: {
49
+ contactAggregate: {
50
+ btree: {
51
+ aggregateBetween: FunctionReference<"query", "internal", {
52
+ k1?: any;
53
+ k2?: any;
54
+ namespace?: any;
55
+ }, {
56
+ count: number;
57
+ sum: number;
58
+ }>;
59
+ aggregateBetweenBatch: FunctionReference<"query", "internal", {
60
+ queries: Array<{
61
+ k1?: any;
62
+ k2?: any;
63
+ namespace?: any;
64
+ }>;
65
+ }, Array<{
66
+ count: number;
67
+ sum: number;
68
+ }>>;
69
+ atNegativeOffset: FunctionReference<"query", "internal", {
70
+ k1?: any;
71
+ k2?: any;
72
+ namespace?: any;
73
+ offset: number;
74
+ }, {
75
+ k: any;
76
+ s: number;
77
+ v: any;
78
+ }>;
79
+ atOffset: FunctionReference<"query", "internal", {
80
+ k1?: any;
81
+ k2?: any;
82
+ namespace?: any;
83
+ offset: number;
84
+ }, {
85
+ k: any;
86
+ s: number;
87
+ v: any;
88
+ }>;
89
+ atOffsetBatch: FunctionReference<"query", "internal", {
90
+ queries: Array<{
91
+ k1?: any;
92
+ k2?: any;
93
+ namespace?: any;
94
+ offset: number;
95
+ }>;
96
+ }, Array<{
97
+ k: any;
98
+ s: number;
99
+ v: any;
100
+ }>>;
101
+ get: FunctionReference<"query", "internal", {
102
+ key: any;
103
+ namespace?: any;
104
+ }, null | {
105
+ k: any;
106
+ s: number;
107
+ v: any;
108
+ }>;
109
+ offset: FunctionReference<"query", "internal", {
110
+ k1?: any;
111
+ key: any;
112
+ namespace?: any;
113
+ }, number>;
114
+ offsetUntil: FunctionReference<"query", "internal", {
115
+ k2?: any;
116
+ key: any;
117
+ namespace?: any;
118
+ }, number>;
119
+ paginate: FunctionReference<"query", "internal", {
120
+ cursor?: string;
121
+ k1?: any;
122
+ k2?: any;
123
+ limit: number;
124
+ namespace?: any;
125
+ order: "asc" | "desc";
126
+ }, {
127
+ cursor: string;
128
+ isDone: boolean;
129
+ page: Array<{
130
+ k: any;
131
+ s: number;
132
+ v: any;
133
+ }>;
134
+ }>;
135
+ paginateNamespaces: FunctionReference<"query", "internal", {
136
+ cursor?: string;
137
+ limit: number;
138
+ }, {
139
+ cursor: string;
140
+ isDone: boolean;
141
+ page: Array<any>;
142
+ }>;
143
+ validate: FunctionReference<"query", "internal", {
144
+ namespace?: any;
145
+ }, any>;
146
+ };
147
+ inspect: {
148
+ display: FunctionReference<"query", "internal", {
149
+ namespace?: any;
150
+ }, any>;
151
+ dump: FunctionReference<"query", "internal", {
152
+ namespace?: any;
153
+ }, string>;
154
+ inspectNode: FunctionReference<"query", "internal", {
155
+ namespace?: any;
156
+ node?: string;
157
+ }, null>;
158
+ listTreeNodes: FunctionReference<"query", "internal", {
159
+ take?: number;
160
+ }, Array<{
161
+ _creationTime: number;
162
+ _id: string;
163
+ aggregate?: {
164
+ count: number;
165
+ sum: number;
166
+ };
167
+ items: Array<{
168
+ k: any;
169
+ s: number;
170
+ v: any;
171
+ }>;
172
+ subtrees: Array<string>;
173
+ }>>;
174
+ listTrees: FunctionReference<"query", "internal", {
175
+ take?: number;
176
+ }, Array<{
177
+ _creationTime: number;
178
+ _id: string;
179
+ maxNodeSize: number;
180
+ namespace?: any;
181
+ root: string;
182
+ }>>;
183
+ };
184
+ public: {
185
+ clear: FunctionReference<"mutation", "internal", {
186
+ maxNodeSize?: number;
187
+ namespace?: any;
188
+ rootLazy?: boolean;
189
+ }, null>;
190
+ delete_: FunctionReference<"mutation", "internal", {
191
+ key: any;
192
+ namespace?: any;
193
+ }, null>;
194
+ deleteIfExists: FunctionReference<"mutation", "internal", {
195
+ key: any;
196
+ namespace?: any;
197
+ }, any>;
198
+ init: FunctionReference<"mutation", "internal", {
199
+ maxNodeSize?: number;
200
+ namespace?: any;
201
+ rootLazy?: boolean;
202
+ }, null>;
203
+ insert: FunctionReference<"mutation", "internal", {
204
+ key: any;
205
+ namespace?: any;
206
+ summand?: number;
207
+ value: any;
208
+ }, null>;
209
+ makeRootLazy: FunctionReference<"mutation", "internal", {
210
+ namespace?: any;
211
+ }, null>;
212
+ replace: FunctionReference<"mutation", "internal", {
213
+ currentKey: any;
214
+ namespace?: any;
215
+ newKey: any;
216
+ newNamespace?: any;
217
+ summand?: number;
218
+ value: any;
219
+ }, null>;
220
+ replaceOrInsert: FunctionReference<"mutation", "internal", {
221
+ currentKey: any;
222
+ namespace?: any;
223
+ newKey: any;
224
+ newNamespace?: any;
225
+ summand?: number;
226
+ value: any;
227
+ }, any>;
228
+ };
229
+ };
230
+ };
231
+ export {};
232
+ //# sourceMappingURL=api.d.ts.map