appflare 0.0.28 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/cli/commands/index.ts +140 -0
  2. package/cli/generate.ts +149 -0
  3. package/cli/index.ts +56 -447
  4. package/cli/load-config.ts +182 -0
  5. package/cli/schema-compiler.ts +657 -0
  6. package/cli/templates/auth/README.md +156 -0
  7. package/cli/templates/auth/config.ts +61 -0
  8. package/cli/templates/auth/route-config.ts +18 -0
  9. package/cli/templates/auth/route-handler.ts +18 -0
  10. package/cli/templates/auth/route-request-utils.ts +55 -0
  11. package/cli/templates/auth/route.ts +14 -0
  12. package/cli/templates/core/README.md +266 -0
  13. package/cli/templates/core/app-creation.ts +19 -0
  14. package/cli/templates/core/client/appflare.ts +37 -0
  15. package/cli/templates/core/client/index.ts +6 -0
  16. package/cli/templates/core/client/storage.ts +100 -0
  17. package/cli/templates/core/client/types.ts +54 -0
  18. package/cli/templates/core/client-modules/appflare.ts +112 -0
  19. package/cli/templates/core/client-modules/handlers/index.ts +740 -0
  20. package/cli/templates/core/client-modules/handlers.ts +1 -0
  21. package/cli/templates/core/client-modules/index.ts +7 -0
  22. package/cli/templates/core/client-modules/storage.ts +180 -0
  23. package/cli/templates/core/client-modules/types.ts +145 -0
  24. package/cli/templates/core/client.ts +39 -0
  25. package/cli/templates/core/drizzle.ts +15 -0
  26. package/cli/templates/core/export.ts +14 -0
  27. package/cli/templates/core/handlers-route.ts +23 -0
  28. package/cli/templates/core/handlers.ts +1 -0
  29. package/cli/templates/core/imports.ts +8 -0
  30. package/cli/templates/core/server.ts +38 -0
  31. package/cli/templates/core/types.ts +6 -0
  32. package/cli/templates/core/wrangler.ts +109 -0
  33. package/cli/templates/handlers/README.md +265 -0
  34. package/cli/templates/handlers/auth.ts +36 -0
  35. package/cli/templates/handlers/execution.ts +39 -0
  36. package/cli/templates/handlers/generators/context/context-creation.ts +80 -0
  37. package/cli/templates/handlers/generators/context/error-helpers.ts +11 -0
  38. package/cli/templates/handlers/generators/context/scheduler.ts +24 -0
  39. package/cli/templates/handlers/generators/context/storage-api.ts +112 -0
  40. package/cli/templates/handlers/generators/context/storage-helpers.ts +59 -0
  41. package/cli/templates/handlers/generators/context/types.ts +18 -0
  42. package/cli/templates/handlers/generators/context.ts +43 -0
  43. package/cli/templates/handlers/generators/execution.ts +15 -0
  44. package/cli/templates/handlers/generators/handlers.ts +13 -0
  45. package/cli/templates/handlers/index.ts +43 -0
  46. package/cli/templates/handlers/operations.ts +116 -0
  47. package/cli/templates/handlers/registration.ts +1114 -0
  48. package/cli/templates/handlers/types.ts +960 -0
  49. package/cli/templates/handlers/utils.ts +48 -0
  50. package/cli/types.ts +108 -0
  51. package/cli/utils/handler-discovery.ts +366 -0
  52. package/cli/utils/json-utils.ts +24 -0
  53. package/cli/utils/path-utils.ts +19 -0
  54. package/cli/utils/schema-discovery.ts +390 -0
  55. package/index.ts +27 -4
  56. package/package.json +23 -20
  57. package/react/index.ts +5 -3
  58. package/react/use-infinite-query.ts +190 -0
  59. package/react/use-mutation.ts +54 -0
  60. package/react/use-query.ts +158 -0
  61. package/schema.ts +262 -0
  62. package/tsconfig.json +2 -4
  63. package/cli/README.md +0 -108
  64. package/cli/core/build.ts +0 -187
  65. package/cli/core/config.ts +0 -92
  66. package/cli/core/discover-handlers.ts +0 -143
  67. package/cli/core/handlers.ts +0 -7
  68. package/cli/core/index.ts +0 -205
  69. package/cli/generators/generate-api-client/client.ts +0 -163
  70. package/cli/generators/generate-api-client/extract-configuration.ts +0 -121
  71. package/cli/generators/generate-api-client/index.ts +0 -973
  72. package/cli/generators/generate-api-client/types.ts +0 -164
  73. package/cli/generators/generate-api-client/utils.ts +0 -22
  74. package/cli/generators/generate-api-client.ts +0 -1
  75. package/cli/generators/generate-cloudflare-worker/helpers.ts +0 -24
  76. package/cli/generators/generate-cloudflare-worker/index.ts +0 -2
  77. package/cli/generators/generate-cloudflare-worker/worker.ts +0 -148
  78. package/cli/generators/generate-cloudflare-worker/wrangler.ts +0 -108
  79. package/cli/generators/generate-cloudflare-worker.ts +0 -4
  80. package/cli/generators/generate-cron-handlers/cron-handlers-block.ts +0 -2
  81. package/cli/generators/generate-cron-handlers/handler-entries.ts +0 -29
  82. package/cli/generators/generate-cron-handlers/index.ts +0 -61
  83. package/cli/generators/generate-cron-handlers/runtime-block.ts +0 -49
  84. package/cli/generators/generate-cron-handlers/type-helpers-block.ts +0 -60
  85. package/cli/generators/generate-db-handlers/index.ts +0 -33
  86. package/cli/generators/generate-db-handlers/prepare.ts +0 -24
  87. package/cli/generators/generate-db-handlers/templates.ts +0 -189
  88. package/cli/generators/generate-db-handlers.ts +0 -1
  89. package/cli/generators/generate-hono-server/auth.ts +0 -97
  90. package/cli/generators/generate-hono-server/imports.ts +0 -55
  91. package/cli/generators/generate-hono-server/index.ts +0 -52
  92. package/cli/generators/generate-hono-server/routes.ts +0 -115
  93. package/cli/generators/generate-hono-server/template.ts +0 -371
  94. package/cli/generators/generate-hono-server.ts +0 -1
  95. package/cli/generators/generate-scheduler-handlers/constants.ts +0 -8
  96. package/cli/generators/generate-scheduler-handlers/handler-entries.ts +0 -22
  97. package/cli/generators/generate-scheduler-handlers/index.ts +0 -51
  98. package/cli/generators/generate-scheduler-handlers/runtime-block.ts +0 -68
  99. package/cli/generators/generate-scheduler-handlers/scheduler-handlers-block.ts +0 -2
  100. package/cli/generators/generate-scheduler-handlers/type-helpers-block.ts +0 -68
  101. package/cli/generators/generate-scheduler-handlers.ts +0 -1
  102. package/cli/generators/generate-websocket-durable-object/auth.ts +0 -30
  103. package/cli/generators/generate-websocket-durable-object/imports.ts +0 -55
  104. package/cli/generators/generate-websocket-durable-object/index.ts +0 -41
  105. package/cli/generators/generate-websocket-durable-object/query-handlers.ts +0 -18
  106. package/cli/generators/generate-websocket-durable-object/template.ts +0 -714
  107. package/cli/generators/generate-websocket-durable-object.ts +0 -1
  108. package/cli/schema/schema-static-types.ts +0 -702
  109. package/cli/schema/schema.ts +0 -151
  110. package/cli/utils/tsc.ts +0 -54
  111. package/cli/utils/utils.ts +0 -190
  112. package/cli/utils/zod-utils.ts +0 -121
  113. package/lib/README.md +0 -50
  114. package/lib/db.ts +0 -19
  115. package/lib/location.ts +0 -110
  116. package/lib/values.ts +0 -27
  117. package/react/README.md +0 -67
  118. package/react/hooks/useMutation.ts +0 -89
  119. package/react/hooks/usePaginatedQuery.ts +0 -213
  120. package/react/hooks/useQuery.ts +0 -106
  121. package/react/shared/queryShared.ts +0 -174
  122. package/server/README.md +0 -218
  123. package/server/auth.ts +0 -107
  124. package/server/database/builders.ts +0 -83
  125. package/server/database/context.ts +0 -327
  126. package/server/database/populate.ts +0 -234
  127. package/server/database/query-builder.ts +0 -161
  128. package/server/database/query-utils.ts +0 -25
  129. package/server/db.ts +0 -2
  130. package/server/storage/auth.ts +0 -16
  131. package/server/storage/bucket.ts +0 -22
  132. package/server/storage/context.ts +0 -34
  133. package/server/storage/index.ts +0 -38
  134. package/server/storage/operations.ts +0 -149
  135. package/server/storage/route-handler.ts +0 -60
  136. package/server/storage/types.ts +0 -55
  137. package/server/storage/utils.ts +0 -47
  138. package/server/storage.ts +0 -6
  139. package/server/types/schema-refs.ts +0 -66
  140. package/server/types/types.ts +0 -633
  141. package/server/utils/id-utils.ts +0 -230
package/server/README.md DELETED
@@ -1,218 +0,0 @@
1
- # Appflare Server (MongoDB) Module
2
-
3
- Appflare's server package provides a small MongoDB data layer with typed helpers for querying, writing, and populating referenced documents inferred from your schema. The entrypoint is `createMongoDbContext`, which builds per-table clients that expose a Prisma-like API (`findMany`, `create`, `update`, `delete`, etc.).
4
-
5
- ## Directory Map
6
-
7
- - `db.ts`: Public exports for the module (re-exports context and types).
8
- - `database/context.ts`: Builds the MongoDB context and per-table client facade.
9
- - `database/builders.ts`: Low-level delete/update/patch builders used by the context.
10
- - `database/query-builder.ts`: Chainable query API (`where`, `sort`, `limit`, `offset`, `select`, `populate`, `find`, `findOne`).
11
- - `database/query-utils.ts`: Projection and sort normalization helpers.
12
- - `database/populate.ts`: Populates referenced documents via forward or reverse lookups.
13
- - `types/`: Shared TypeScript types for docs, queries, and table clients. `schema-refs.ts` derives reference metadata from Zod schemas.
14
- - `utils/id-utils.ts`: Id normalization helpers (string/ObjectId) and ref field coercion.
15
-
16
- ## Quick Start
17
-
18
- ```ts
19
- import { MongoClient } from "mongodb";
20
- import { z } from "zod";
21
- import { createMongoDbContext } from "@appflare/server/db";
22
-
23
- const client = await MongoClient.connect(process.env.MONGO_URL!);
24
- const db = client.db("appflare-demo");
25
-
26
- const schema = {
27
- users: z.object({
28
- _id: z.string(),
29
- _creationTime: z.number(),
30
- email: z.string(),
31
- // ref:tickets tells the system this field references the tickets table
32
- tickets: z.array(z.string().describe("ref:tickets")).optional(),
33
- }),
34
- tickets: z.object({
35
- _id: z.string(),
36
- _creationTime: z.number(),
37
- title: z.string(),
38
- user: z.string().describe("ref:users"),
39
- }),
40
- } as const;
41
-
42
- const ctx = createMongoDbContext({ db, schema });
43
-
44
- // typed table clients
45
- const users = ctx.users;
46
- const tickets = ctx.tickets;
47
-
48
- // create
49
- const user = await users.create({ data: { email: "a@demo.com", tickets: [] } });
50
-
51
- // query with select + populate
52
- const withTickets = await users.findUnique({
53
- where: { _id: user._id },
54
- select: ["_id", "email"],
55
- include: ["tickets"],
56
- });
57
-
58
- // update many
59
- await tickets.updateMany({
60
- where: { user: user._id },
61
- data: { title: "Updated" },
62
- });
63
- ```
64
-
65
- ## R2 Storage Manager (Hono)
66
-
67
- Use `createR2StorageManager` to mount authenticated, rule-driven storage routes on Cloudflare Workers (R2). Each rule declares a route, allowed methods, authorization hook, and key derivation so you can map requests to bucket object keys however you like.
68
-
69
- ```ts
70
- import { Hono } from "hono";
71
- import { createR2StorageManager } from "@appflare/server/storage";
72
-
73
- const app = new Hono<{ Bindings: { BUCKET: R2Bucket } }>();
74
-
75
- app.route(
76
- "/storage",
77
- createR2StorageManager({
78
- basePath: "/storage", // optional prefix
79
- bucketBinding: "BUCKET", // or provide getBucket(c)
80
- rules: [
81
- {
82
- route: "/private/*",
83
- methods: ["GET", "PUT", "DELETE"],
84
- authorize: async ({ c }) => {
85
- const user = await verifySession(c.req); // your auth logic
86
- return user
87
- ? { allow: true, principal: user }
88
- : { allow: false, status: 401 };
89
- },
90
- deriveKey: ({ wildcard, principal }) => `${principal!.id}/${wildcard}`,
91
- maxSizeBytes: 5 * 1024 * 1024,
92
- cacheControl: "private, max-age=60",
93
- },
94
- {
95
- route: "/public/*",
96
- methods: ["GET", "HEAD", "PUT"],
97
- authorize: () => ({ allow: true }),
98
- deriveKey: ({ wildcard }) => `public/${wildcard}`,
99
- cacheControl: "public, max-age=3600",
100
- },
101
- ],
102
- })
103
- );
104
-
105
- export default app;
106
- ```
107
-
108
- Key behaviors:
109
-
110
- - `authorize` can attach a `principal` that flows into `deriveKey` for per-user folders.
111
- - `route` supports wildcards (`*`) to capture the remainder of the path; `defaultKey` mirrors the request path under the base path when `deriveKey` is omitted.
112
- - Supports `GET`/`HEAD` for reads, `PUT`/`POST` for writes, and `DELETE` for deletes. Size limits, cache control, and content type inference are configurable per rule.
113
-
114
- ## Better Auth (Hono)
115
-
116
- Use `initBetterAuth` with `createBetterAuthRouter` to forward requests to a Better Auth instance from a Hono server. The generated server can also mount this automatically when `auth` is defined in `appflare.config.ts`.
117
-
118
- ```ts
119
- import { Hono } from "hono";
120
- import { createBetterAuthRouter, initBetterAuth } from "appflare/server/auth";
121
-
122
- const app = new Hono();
123
- const auth = initBetterAuth({
124
- // Better Auth options (adapter, providers, cookies, etc.)
125
- });
126
-
127
- app.route("/auth", createBetterAuthRouter({ auth }));
128
- ```
129
-
130
- ## Core Concepts
131
-
132
- - **Context**: `createMongoDbContext` wires a MongoDB `Db`, a Zod schema map, and optional collection naming into typed table clients. Each table client wraps insert/update/delete/query logic and handles reference normalization.
133
- - **Reference inference**: `buildSchemaRefMap` inspects Zod field descriptions that start with `ref:` to discover forward references. This enables automatic population and reference normalization.
134
- - **Id normalization**: `normalizeIdValue` coerces valid string ids into `ObjectId` for filters and writes; `stringifyIdField` converts `_id` back to hex string on reads. Ref fields are normalized similarly via `normalizeRefFields`/`stringifyRefFields`.
135
- - **Populate**: `populate()` on a query triggers `applyPopulate`, which performs `$lookup` pipelines. Forward populate (table stores the ref) is preferred; if absent, reverse populate finds documents that reference the current table (e.g., `tickets.user -> users._id`).
136
- - **Typed chaining**: Query builders keep result types in sync when `select` or `populate` is used. Update/delete builders offer a fluent `where(...).set(...).exec()` style when called with one argument.
137
-
138
- ## API Reference
139
-
140
- ### Context Factory
141
-
142
- - `createMongoDbContext(options)`:
143
- - `db`: MongoDB `Db` instance.
144
- - `schema`: Record of Zod schemas for each table (must include `_id` and `_creationTime`).
145
- - `collectionName?`: Optional mapper `(tableName) => collectionName`.
146
- - Returns `MongoDbContext` — a map of table names to `AppflareTableClient`.
147
-
148
- ### Table Client (`AppflareTableClient`)
149
-
150
- Methods match Prisma-like signatures:
151
-
152
- - `findMany({ where?, orderBy?, skip?, take?, select?, include? })`
153
- - `findFirst({ ... })`
154
- - `findUnique({ where, select?, include? })`
155
- - `create({ data, select?, include? })`
156
- - `update({ where, data, select?, include? })`
157
- - `updateMany({ where?, data })`
158
- - `delete({ where, select?, include? })`
159
- - `deleteMany({ where? })`
160
- - `count({ where? })`
161
-
162
- `select` accepts an array or object of field keys; `include` accepts populatable relation keys. Both adjust the result type.
163
-
164
- ### Query Builder
165
-
166
- Produced via `ctx.<table>.findMany()` under the hood and exposed through `core.query()`:
167
-
168
- - `where(filter)`: chainable; multiple calls AND together.
169
- - `sort(sortSpec)`: accepts object or tuples; `desc` maps to `-1` for Mongo.
170
- - `limit(n)` / `offset(n)`
171
- - `select(...keys)`
172
- - `populate(key | keys[])`
173
- - `find()` returns an array; `findOne()` returns first or `null`.
174
-
175
- ### Update/Patch/Delete Builders
176
-
177
- When `update`, `patch`, or `delete` are called with only the table name, they return a builder:
178
-
179
- ```ts
180
- await ctx.users
181
- .update("users")
182
- .where({ email: /@demo/ })
183
- .set({ email: "x" })
184
- .exec();
185
- await ctx.users.delete("users").where("someId").exec();
186
- ```
187
-
188
- `patch` is an alias of `update`.
189
-
190
- ### Populate Behavior
191
-
192
- - Forward populate uses `$lookup` from the current collection to the referenced table (`localField` = ref field, `foreignField` = `_id`). Arrays are matched element-wise.
193
- - Reverse populate triggers when the current table lacks the ref but others point to it. It looks up documents in the referencing table and groups them by current `_id`.
194
- - Populate respects `select`: projection is expanded to include ref keys so lookups have ids even when omitted from the requested fields.
195
-
196
- ### Utilities
197
-
198
- - `buildProjection(keys)`: builds a Mongo projection, ensuring `_id` and `_creationTime` are excluded when not selected.
199
- - `normalizeSort(sort)`: converts sort objects/tuples to Mongo format.
200
- - `normalizeIdFilter`, `normalizeRefFields`, `stringifyIdField`: ensure consistent id types across reads/writes.
201
-
202
- ## Usage Notes
203
-
204
- - Always include `_id` and `_creationTime` in your Zod schema; they are used by the helpers and default projections.
205
- - Reference discovery relies on `describe("ref:<table>")` on string fields (optionally inside arrays/optional/nullable/default wrappers).
206
- - All writes normalize ids to `ObjectId` when valid; reads stringify `_id` for consumer-friendly output.
207
- - `findUnique` requires a `where` clause; `findFirst` defaults `take` to `1` when unset.
208
-
209
- ## Extending
210
-
211
- - Supply a custom `collectionName` to map logical table names to physical collections.
212
- - Customize partial normalization by passing `normalizePartial` to `createUpdateBuilder`/`createPatchBuilder` if you wrap the builders yourself.
213
-
214
- ## Related Files
215
-
216
- - Types: `types/types.ts`, `types/schema-refs.ts`
217
- - Database helpers: `database/context.ts`, `database/query-builder.ts`, `database/builders.ts`, `database/populate.ts`, `database/query-utils.ts`
218
- - Id helpers: `utils/id-utils.ts`
package/server/auth.ts DELETED
@@ -1,107 +0,0 @@
1
- import { betterAuth, type Auth, type BetterAuthOptions } from "better-auth";
2
- import type { Context } from "hono";
3
- import { Hono } from "hono";
4
-
5
- export type BetterAuthHandlerOptions<
6
- Options extends BetterAuthOptions = BetterAuthOptions,
7
- Env = unknown,
8
- > = {
9
- auth: Auth<Options>;
10
- onError?: (error: unknown, c: Context<Env>) => Response | Promise<Response>;
11
- };
12
-
13
- export function createBetterAuthHandler<
14
- Options extends BetterAuthOptions = BetterAuthOptions,
15
- Env = unknown,
16
- >(options: BetterAuthHandlerOptions<Options, Env>) {
17
- return async (c: Context<Env>) => {
18
- try {
19
- return await options.auth.handler(getSanitizedRequest(c.req.raw));
20
- } catch (error) {
21
- if (options.onError) return options.onError(error, c);
22
- console.error("BetterAuth handler error", error);
23
- return c.json({ error: "Authentication failed" }, 500);
24
- }
25
- };
26
- }
27
-
28
- import { mongodbAdapter } from "better-auth/adapters/mongodb";
29
- import { getDatabase } from "cloudflare-do-mongo";
30
- import { env } from "cloudflare:workers";
31
- export function createBetterAuthRouter<
32
- Options extends BetterAuthOptions = BetterAuthOptions,
33
- Env = unknown,
34
- >(options: BetterAuthHandlerOptions<Options, Env>): Hono<Env> {
35
- const app = new Hono<Env>();
36
- const handler = createBetterAuthHandler(options);
37
- app.all("/", handler);
38
- app.all("/*", handler);
39
- return app;
40
- }
41
-
42
- export function initBetterAuth<Options extends BetterAuthOptions>(
43
- options: Options,
44
- kvBinding?: string,
45
- ): Auth<Options> {
46
- const authConfig: BetterAuthOptions = {
47
- ...options,
48
- database: mongodbAdapter(getDatabase((env as any).MONGO_DB) as any),
49
- };
50
-
51
- // Add secondary storage if KV binding is provided
52
- if (kvBinding && (env as any)[kvBinding]) {
53
- (authConfig as any).secondaryStorage = {
54
- get: async (key: string) => {
55
- const kv = (env as any)[kvBinding];
56
- return await kv.get(key);
57
- },
58
- set: async (key: string, value: string, ttl?: number) => {
59
- const kv = (env as any)[kvBinding];
60
- await kv.put(key, value, ttl ? { expirationTtl: ttl } : undefined);
61
- },
62
- delete: async (key: string) => {
63
- const kv = (env as any)[kvBinding];
64
- await kv.delete(key);
65
- },
66
- };
67
- }
68
-
69
- return betterAuth(authConfig as Options);
70
- }
71
- export const getHeaders = (headers: Headers) => {
72
- const newHeaders = Object.fromEntries(headers as any);
73
- const headerObject: Record<string, any> = {};
74
- let hasCookie = false;
75
-
76
- for (const key in newHeaders) {
77
- if (key.toLowerCase() === "cookie") {
78
- hasCookie = true;
79
- break;
80
- }
81
- }
82
-
83
- for (const key in newHeaders) {
84
- const isAuthorization =
85
- key.toLowerCase() === "authorization" &&
86
- newHeaders[key]?.includes("Bearer");
87
-
88
- if (hasCookie && key.toLowerCase() === "authorization") {
89
- continue;
90
- }
91
-
92
- if (key.toLowerCase() === "authorization" && !isAuthorization) {
93
- continue;
94
- }
95
-
96
- headerObject[key] = newHeaders[key];
97
- }
98
-
99
- return headerObject as any as Headers;
100
- };
101
-
102
- export const getSanitizedRequest = (req: Request) => {
103
- const newRequest = new Request(req, {
104
- headers: getHeaders(req.headers),
105
- });
106
- return newRequest;
107
- };
@@ -1,83 +0,0 @@
1
- import type { Collection, Document } from "mongodb";
2
- import { isIdValue, normalizeIdFilter, toMongoFilter } from "../utils/id-utils";
3
- import type {
4
- MongoDbDeleteBuilder,
5
- MongoDbPatchBuilder,
6
- MongoDbUpdateBuilder,
7
- } from "../types/types";
8
-
9
- export function createDeleteBuilder(params: {
10
- table: string;
11
- getCollection: (table: string) => Collection<Document>;
12
- }): MongoDbDeleteBuilder<any, any> {
13
- return {
14
- where(where) {
15
- const filter = normalizeIdFilter(toMongoFilter(where));
16
- return {
17
- exec: async () => {
18
- const coll = params.getCollection(params.table);
19
- if (isIdValue(where)) {
20
- await coll.deleteOne(filter as any);
21
- } else {
22
- await coll.deleteMany(filter as any);
23
- }
24
- },
25
- };
26
- },
27
- };
28
- }
29
-
30
- export function createUpdateBuilder(params: {
31
- table: string;
32
- getCollection: (table: string) => Collection<Document>;
33
- normalizePartial?: (
34
- partial: Record<string, unknown>
35
- ) => Record<string, unknown>;
36
- }): MongoDbUpdateBuilder<any, any> {
37
- return {
38
- where(where) {
39
- const filter = normalizeIdFilter(toMongoFilter(where));
40
- return {
41
- set(partial) {
42
- const normalized = params.normalizePartial
43
- ? params.normalizePartial(partial as any)
44
- : partial;
45
- return {
46
- exec: async () => {
47
- const coll = params.getCollection(params.table);
48
- const update = { $set: normalized as any };
49
- if (isIdValue(where)) {
50
- await coll.updateOne(filter as any, update);
51
- } else {
52
- await coll.updateMany(filter as any, update);
53
- }
54
- },
55
- };
56
- },
57
- exec: async (partial) => {
58
- if (!partial) throw new Error("update requires a partial to set");
59
- const normalized = params.normalizePartial
60
- ? params.normalizePartial(partial as any)
61
- : partial;
62
- const coll = params.getCollection(params.table);
63
- const update = { $set: normalized as any };
64
- if (isIdValue(where)) {
65
- await coll.updateOne(filter as any, update);
66
- } else {
67
- await coll.updateMany(filter as any, update);
68
- }
69
- },
70
- };
71
- },
72
- };
73
- }
74
-
75
- export function createPatchBuilder(params: {
76
- table: string;
77
- getCollection: (table: string) => Collection<Document>;
78
- normalizePartial?: (
79
- partial: Record<string, unknown>
80
- ) => Record<string, unknown>;
81
- }): MongoDbPatchBuilder<any, any> {
82
- return createUpdateBuilder(params) as MongoDbPatchBuilder<any, any>;
83
- }