@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,167 @@
1
+ import { v } from "convex/values";
2
+ /**
3
+ * Validators for Loops API requests and component operations
4
+ */
5
+ /**
6
+ * Validator for contact data
7
+ * Used for creating and updating contacts
8
+ */
9
+ export const contactValidator = v.object({
10
+ email: v.string(),
11
+ firstName: v.optional(v.string()),
12
+ lastName: v.optional(v.string()),
13
+ userId: v.optional(v.string()),
14
+ source: v.optional(v.string()),
15
+ subscribed: v.optional(v.boolean()),
16
+ userGroup: v.optional(v.string()),
17
+ });
18
+ /**
19
+ * Validator for transactional email requests
20
+ */
21
+ export const transactionalEmailValidator = v.object({
22
+ transactionalId: v.optional(v.string()),
23
+ email: v.string(),
24
+ dataVariables: v.optional(v.record(v.string(), v.any())),
25
+ idempotencyKey: v.optional(v.string()),
26
+ });
27
+ /**
28
+ * Validator for event requests
29
+ * Used for sending events that trigger email workflows
30
+ */
31
+ export const eventValidator = v.object({
32
+ email: v.string(),
33
+ eventName: v.string(),
34
+ eventProperties: v.optional(v.record(v.string(), v.any())),
35
+ });
36
+ /**
37
+ * Validator for operation type enum
38
+ */
39
+ export const operationTypeValidator = v.union(v.literal("transactional"), v.literal("event"), v.literal("campaign"), v.literal("loop"));
40
+ /**
41
+ * Common return validators used across functions
42
+ */
43
+ export const successResponseValidator = v.object({
44
+ success: v.boolean(),
45
+ });
46
+ export const successWithIdResponseValidator = v.object({
47
+ success: v.boolean(),
48
+ id: v.optional(v.string()),
49
+ });
50
+ export const successWithMessageIdResponseValidator = v.object({
51
+ success: v.boolean(),
52
+ messageId: v.optional(v.string()),
53
+ });
54
+ export const successWithWarningResponseValidator = v.object({
55
+ success: v.boolean(),
56
+ warning: v.optional(v.string()),
57
+ });
58
+ /**
59
+ * Contact document validator for query returns
60
+ */
61
+ export const contactDocValidator = v.object({
62
+ _id: v.string(),
63
+ email: v.string(),
64
+ firstName: v.optional(v.string()),
65
+ lastName: v.optional(v.string()),
66
+ userId: v.optional(v.string()),
67
+ source: v.optional(v.string()),
68
+ subscribed: v.boolean(),
69
+ userGroup: v.optional(v.string()),
70
+ loopsContactId: v.optional(v.string()),
71
+ createdAt: v.number(),
72
+ updatedAt: v.number(),
73
+ });
74
+ /**
75
+ * Paginated contacts response validator
76
+ */
77
+ export const paginatedContactsResponseValidator = v.object({
78
+ contacts: v.array(contactDocValidator),
79
+ continueCursor: v.union(v.string(), v.null()),
80
+ isDone: v.boolean(),
81
+ });
82
+ /**
83
+ * Rate limit response validator
84
+ */
85
+ export const rateLimitResponseValidator = v.object({
86
+ allowed: v.boolean(),
87
+ count: v.number(),
88
+ limit: v.number(),
89
+ timeWindowMs: v.number(),
90
+ retryAfter: v.optional(v.number()),
91
+ });
92
+ /**
93
+ * Email stats response validator
94
+ */
95
+ export const emailStatsResponseValidator = v.object({
96
+ totalOperations: v.number(),
97
+ successfulOperations: v.number(),
98
+ failedOperations: v.number(),
99
+ operationsByType: v.record(v.string(), v.number()),
100
+ uniqueRecipients: v.number(),
101
+ uniqueActors: v.number(),
102
+ });
103
+ /**
104
+ * Spam detection validators
105
+ */
106
+ export const recipientSpamValidator = v.object({
107
+ email: v.string(),
108
+ count: v.number(),
109
+ timeWindowMs: v.number(),
110
+ });
111
+ export const actorSpamValidator = v.object({
112
+ actorId: v.string(),
113
+ count: v.number(),
114
+ timeWindowMs: v.number(),
115
+ });
116
+ export const rapidFirePatternValidator = v.object({
117
+ email: v.optional(v.string()),
118
+ actorId: v.optional(v.string()),
119
+ count: v.number(),
120
+ timeWindowMs: v.number(),
121
+ firstTimestamp: v.number(),
122
+ lastTimestamp: v.number(),
123
+ });
124
+ /**
125
+ * Batch create response validator
126
+ */
127
+ export const batchCreateResponseValidator = v.object({
128
+ success: v.boolean(),
129
+ created: v.optional(v.number()),
130
+ failed: v.optional(v.number()),
131
+ results: v.optional(v.array(v.object({
132
+ email: v.string(),
133
+ success: v.boolean(),
134
+ error: v.optional(v.string()),
135
+ }))),
136
+ });
137
+ /**
138
+ * Find contact response validator
139
+ * Note: Loops API returns additional fields beyond our contact model
140
+ */
141
+ export const findContactResponseValidator = v.object({
142
+ success: v.boolean(),
143
+ contact: v.optional(v.object({
144
+ id: v.optional(v.union(v.string(), v.null())),
145
+ email: v.optional(v.union(v.string(), v.null())),
146
+ firstName: v.optional(v.union(v.string(), v.null())),
147
+ lastName: v.optional(v.union(v.string(), v.null())),
148
+ source: v.optional(v.union(v.string(), v.null())),
149
+ subscribed: v.optional(v.union(v.boolean(), v.null())),
150
+ userGroup: v.optional(v.union(v.string(), v.null())),
151
+ userId: v.optional(v.union(v.string(), v.null())),
152
+ createdAt: v.optional(v.union(v.string(), v.null())),
153
+ // Additional fields from Loops API
154
+ audienceId: v.optional(v.union(v.string(), v.null())),
155
+ timestamp: v.optional(v.union(v.string(), v.null())),
156
+ dataVariables: v.optional(v.any()),
157
+ mailingLists: v.optional(v.any()),
158
+ })),
159
+ });
160
+ /**
161
+ * Backfill response validator
162
+ */
163
+ export const backfillResponseValidator = v.object({
164
+ processed: v.number(),
165
+ cursor: v.union(v.string(), v.null()),
166
+ isDone: v.boolean(),
167
+ });
package/dist/test.d.ts ADDED
@@ -0,0 +1,78 @@
1
+ import type { TestConvex } from "convex-test";
2
+ import type { GenericSchema, SchemaDefinition } from "convex/server";
3
+ import schema from "./component/schema.js";
4
+ /**
5
+ * Register the Loops component with the test convex instance.
6
+ *
7
+ * @param t - The test convex instance from convexTest().
8
+ * @param name - The name of the component as registered in convex.config.ts.
9
+ * @param modules - The modules object from import.meta.glob. Required.
10
+ */
11
+ export declare function register(t: TestConvex<SchemaDefinition<GenericSchema, boolean>>, name?: string, modules?: Record<string, () => Promise<unknown>>): void;
12
+ export { schema };
13
+ declare const _default: {
14
+ register: typeof register;
15
+ schema: SchemaDefinition<{
16
+ contacts: import("convex/server").TableDefinition<import("convex/values").VObject<{
17
+ firstName?: string | undefined;
18
+ lastName?: string | undefined;
19
+ userId?: string | undefined;
20
+ source?: string | undefined;
21
+ subscribed?: boolean | undefined;
22
+ userGroup?: string | undefined;
23
+ loopsContactId?: string | undefined;
24
+ email: string;
25
+ createdAt: number;
26
+ updatedAt: number;
27
+ }, {
28
+ email: import("convex/values").VString<string, "required">;
29
+ firstName: import("convex/values").VString<string | undefined, "optional">;
30
+ lastName: import("convex/values").VString<string | undefined, "optional">;
31
+ userId: import("convex/values").VString<string | undefined, "optional">;
32
+ source: import("convex/values").VString<string | undefined, "optional">;
33
+ subscribed: import("convex/values").VBoolean<boolean | undefined, "optional">;
34
+ userGroup: import("convex/values").VString<string | undefined, "optional">;
35
+ loopsContactId: import("convex/values").VString<string | undefined, "optional">;
36
+ createdAt: import("convex/values").VFloat64<number, "required">;
37
+ updatedAt: import("convex/values").VFloat64<number, "required">;
38
+ }, "required", "email" | "firstName" | "lastName" | "userId" | "source" | "subscribed" | "userGroup" | "loopsContactId" | "createdAt" | "updatedAt">, {
39
+ email: ["email", "_creationTime"];
40
+ userId: ["userId", "_creationTime"];
41
+ userGroup: ["userGroup", "_creationTime"];
42
+ source: ["source", "_creationTime"];
43
+ subscribed: ["subscribed", "_creationTime"];
44
+ }, {}, {}>;
45
+ emailOperations: import("convex/server").TableDefinition<import("convex/values").VObject<{
46
+ actorId?: string | undefined;
47
+ transactionalId?: string | undefined;
48
+ campaignId?: string | undefined;
49
+ loopId?: string | undefined;
50
+ eventName?: string | undefined;
51
+ messageId?: string | undefined;
52
+ metadata?: Record<string, any> | undefined;
53
+ email: string;
54
+ operationType: "transactional" | "event" | "campaign" | "loop";
55
+ timestamp: number;
56
+ success: boolean;
57
+ }, {
58
+ operationType: import("convex/values").VUnion<"transactional" | "event" | "campaign" | "loop", [import("convex/values").VLiteral<"transactional", "required">, import("convex/values").VLiteral<"event", "required">, import("convex/values").VLiteral<"campaign", "required">, import("convex/values").VLiteral<"loop", "required">], "required", never>;
59
+ email: import("convex/values").VString<string, "required">;
60
+ actorId: import("convex/values").VString<string | undefined, "optional">;
61
+ transactionalId: import("convex/values").VString<string | undefined, "optional">;
62
+ campaignId: import("convex/values").VString<string | undefined, "optional">;
63
+ loopId: import("convex/values").VString<string | undefined, "optional">;
64
+ eventName: import("convex/values").VString<string | undefined, "optional">;
65
+ timestamp: import("convex/values").VFloat64<number, "required">;
66
+ success: import("convex/values").VBoolean<boolean, "required">;
67
+ messageId: import("convex/values").VString<string | undefined, "optional">;
68
+ metadata: import("convex/values").VRecord<Record<string, any> | undefined, import("convex/values").VString<string, "required">, import("convex/values").VAny<any, "required", string>, "optional", string>;
69
+ }, "required", "email" | "operationType" | "actorId" | "transactionalId" | "campaignId" | "loopId" | "eventName" | "timestamp" | "success" | "messageId" | "metadata" | `metadata.${string}`>, {
70
+ email: ["email", "timestamp", "_creationTime"];
71
+ actorId: ["actorId", "timestamp", "_creationTime"];
72
+ operationType: ["operationType", "timestamp", "_creationTime"];
73
+ timestamp: ["timestamp", "_creationTime"];
74
+ }, {}, {}>;
75
+ }, true>;
76
+ };
77
+ export default _default;
78
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,MAAM,MAAM,uBAAuB,CAAC;AAE3C;;;;;;GAMG;AACH,wBAAgB,QAAQ,CACvB,CAAC,EAAE,UAAU,CAAC,gBAAgB,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,EACvD,IAAI,GAAE,MAAgB,EACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,QAQhD;AAED,OAAO,EAAE,MAAM,EAAE,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAElB,wBAAoC"}
package/dist/test.js ADDED
@@ -0,0 +1,16 @@
1
+ import schema from "./component/schema.js";
2
+ /**
3
+ * Register the Loops component with the test convex instance.
4
+ *
5
+ * @param t - The test convex instance from convexTest().
6
+ * @param name - The name of the component as registered in convex.config.ts.
7
+ * @param modules - The modules object from import.meta.glob. Required.
8
+ */
9
+ export function register(t, name = "loops", modules) {
10
+ if (!modules) {
11
+ throw new Error("modules parameter is required. Pass import.meta.glob from your test file.");
12
+ }
13
+ t.registerComponent(name, schema, modules);
14
+ }
15
+ export { schema };
16
+ export default { register, schema };
@@ -0,0 +1,39 @@
1
+ import type { GenericActionCtx, GenericDataModel, GenericMutationCtx, GenericQueryCtx } from "convex/server";
2
+ export type RunQueryCtx = Pick<GenericQueryCtx<GenericDataModel>, "runQuery">;
3
+ export type RunMutationCtx = Pick<GenericMutationCtx<GenericDataModel>, "runQuery" | "runMutation">;
4
+ export type RunActionCtx = Pick<GenericActionCtx<GenericDataModel>, "runQuery" | "runMutation" | "runAction">;
5
+ export type HeadersInitParam = ConstructorParameters<typeof Headers>[0];
6
+ export interface ContactPayload {
7
+ email: string;
8
+ firstName?: string;
9
+ lastName?: string;
10
+ userId?: string;
11
+ source?: string;
12
+ subscribed?: boolean;
13
+ userGroup?: string;
14
+ }
15
+ export interface UpdateContactPayload extends Partial<ContactPayload> {
16
+ email: string;
17
+ dataVariables?: Record<string, unknown>;
18
+ }
19
+ export interface DeleteContactPayload {
20
+ email?: string;
21
+ }
22
+ export interface TransactionalPayload {
23
+ transactionalId?: string;
24
+ email?: string;
25
+ dataVariables?: Record<string, unknown>;
26
+ idempotencyKey?: string;
27
+ }
28
+ export interface EventPayload {
29
+ email?: string;
30
+ eventName?: string;
31
+ eventProperties?: Record<string, unknown>;
32
+ }
33
+ export interface TriggerPayload {
34
+ loopId?: string;
35
+ email?: string;
36
+ dataVariables?: Record<string, unknown>;
37
+ eventName?: string;
38
+ }
39
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,gBAAgB,EAChB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,MAAM,eAAe,CAAC;AAGvB,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,EAAE,UAAU,CAAC,CAAC;AAE9E,MAAM,MAAM,cAAc,GAAG,IAAI,CAChC,kBAAkB,CAAC,gBAAgB,CAAC,EACpC,UAAU,GAAG,aAAa,CAC1B,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,IAAI,CAC9B,gBAAgB,CAAC,gBAAgB,CAAC,EAClC,UAAU,GAAG,aAAa,GAAG,WAAW,CACxC,CAAC;AAGF,MAAM,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAGxE,MAAM,WAAW,cAAc;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAqB,SAAQ,OAAO,CAAC,cAAc,CAAC;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,oBAAoB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,oBAAoB;IACpC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,cAAc;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB"}
package/dist/types.js ADDED
File without changes
package/package.json ADDED
@@ -0,0 +1,112 @@
1
+ {
2
+ "name": "@niama/loops",
3
+ "version": "0.2.0",
4
+ "description": "Convex component for integrating with Loops.so email marketing platform",
5
+ "license": "Apache-2.0",
6
+ "type": "module",
7
+ "main": "dist/client/index.js",
8
+ "types": "dist/client/index.d.ts",
9
+ "keywords": [
10
+ "convex",
11
+ "component",
12
+ "loops",
13
+ "loops.so",
14
+ "email",
15
+ "email-marketing",
16
+ "transactional-email",
17
+ "newsletter",
18
+ "typescript"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/robertalv/loops.git"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/robertalv/loops/issues"
26
+ },
27
+ "homepage": "https://github.com/robertalv/loops#readme",
28
+ "files": [
29
+ "dist",
30
+ "src",
31
+ "README.md",
32
+ "LICENSE"
33
+ ],
34
+ "exports": {
35
+ "./package.json": "./package.json",
36
+ ".": {
37
+ "types": "./dist/client/index.d.ts",
38
+ "default": "./dist/client/index.js"
39
+ },
40
+ "./convex.config": {
41
+ "types": "./dist/component/convex.config.d.ts",
42
+ "default": "./dist/component/convex.config.js"
43
+ },
44
+ "./convex.config.js": {
45
+ "types": "./dist/component/convex.config.d.ts",
46
+ "default": "./dist/component/convex.config.js"
47
+ },
48
+ "./_generated/component": {
49
+ "types": "./dist/component/_generated/component.d.ts"
50
+ },
51
+ "./_generated/component.js": {
52
+ "types": "./dist/component/_generated/component.d.ts"
53
+ },
54
+ "./test": "./src/test.ts"
55
+ },
56
+ "scripts": {
57
+ "dev": "run-p -r 'dev:backend' 'dev:frontend' 'build:watch'",
58
+ "dev:backend": "convex dev --live-component-sources --typecheck-components",
59
+ "dev:frontend": "bun --hot example/src/index.tsx",
60
+ "build": "tsc --project tsconfig.build.json",
61
+ "build:watch": "chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.*' -i '**/test-setup.ts' -c 'bun run build' --initial",
62
+ "clean": "rm -rf dist node_modules",
63
+ "test": "bun test",
64
+ "test:watch": "bun test --watch",
65
+ "test:coverage": "bun test --coverage",
66
+ "test:bail": "bun test --bail",
67
+ "lint": "biome lint .",
68
+ "lint:fix": "biome lint --write .",
69
+ "format": "biome format --write .",
70
+ "check": "biome check .",
71
+ "check:fix": "biome check --write .",
72
+ "typecheck": "tsc --noEmit",
73
+ "attw": "attw $(npm pack -s) --exclude-entrypoints ./convex.config ./test --profile esm-only --ignore-rules internal-resolution-error",
74
+ "prepare": "npm run build || true",
75
+ "changeset": "changeset",
76
+ "ci:version": "changeset version && bun update",
77
+ "ci:publish": "changeset publish",
78
+ "preversion": "bun run clean && bun install && run-p test lint typecheck attw",
79
+ "version": "pbcopy <<<$npm_package_version; vim CHANGELOG.md && biome format --write CHANGELOG.md && git add CHANGELOG.md",
80
+ "postversion": "git push --follow-tags",
81
+ "alpha": "bun run preversion && npm version prerelease --preid alpha && npm publish --tag alpha",
82
+ "release": "bun run preversion && npm version patch && npm publish"
83
+ },
84
+ "dependencies": {
85
+ "@convex-dev/aggregate": "^0.2.1"
86
+ },
87
+ "peerDependencies": {
88
+ "convex": "^1.0.0"
89
+ },
90
+ "devDependencies": {
91
+ "@arethetypeswrong/cli": "^0.18.2",
92
+ "@biomejs/biome": "2.3.0",
93
+ "@changesets/changelog-github": "^0.5.1",
94
+ "@changesets/cli": "^2.29.7",
95
+ "@commitlint/cli": "^20.1.0",
96
+ "@commitlint/types": "^20.0.0",
97
+ "@types/bun": "^1.3.1",
98
+ "@types/react": "^19.2.2",
99
+ "@types/react-dom": "^19.2.2",
100
+ "bun-plugin-tailwind": "^0.1.2",
101
+ "chokidar-cli": "^3.0.0",
102
+ "commitlint-config-gitmoji": "^2.3.1",
103
+ "convex": "^1.28.0",
104
+ "convex-helpers": "^0.1.104",
105
+ "convex-test": "^0.0.38",
106
+ "npm-run-all": "^4.1.5",
107
+ "pkg-pr-new": "^0.0.60",
108
+ "react": "^19.2.0",
109
+ "react-dom": "^19.2.0",
110
+ "tailwindcss": "^4.1.16"
111
+ }
112
+ }