kitcn 0.0.1 → 0.12.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.
- package/bin/intent.js +3 -0
- package/dist/aggregate/index.d.ts +388 -0
- package/dist/aggregate/index.js +37 -0
- package/dist/api-entry-BckXqaLb.js +66 -0
- package/dist/auth/client/index.d.ts +37 -0
- package/dist/auth/client/index.js +217 -0
- package/dist/auth/config/index.d.ts +45 -0
- package/dist/auth/config/index.js +24 -0
- package/dist/auth/generated/index.d.ts +2 -0
- package/dist/auth/generated/index.js +3 -0
- package/dist/auth/http/index.d.ts +64 -0
- package/dist/auth/http/index.js +461 -0
- package/dist/auth/index.d.ts +221 -0
- package/dist/auth/index.js +1398 -0
- package/dist/auth/nextjs/index.d.ts +50 -0
- package/dist/auth/nextjs/index.js +81 -0
- package/dist/auth-store-Cljlmdmi.js +197 -0
- package/dist/builder-CBdG5W6A.js +1974 -0
- package/dist/caller-factory-cTXNvYdz.js +216 -0
- package/dist/cli.mjs +13255 -0
- package/dist/codegen-lF80HSWu.mjs +3416 -0
- package/dist/context-utils-HPC5nXzx.d.ts +17 -0
- package/dist/create-schema-odyF4kCy.js +156 -0
- package/dist/create-schema-orm-DOyiNDCx.js +246 -0
- package/dist/crpc/index.d.ts +105 -0
- package/dist/crpc/index.js +169 -0
- package/dist/customFunctions-C0voKmtx.js +144 -0
- package/dist/error-BZEnI7Sq.js +41 -0
- package/dist/generated-contract-disabled-Cih4eITO.js +50 -0
- package/dist/generated-contract-disabled-D-sOFy92.d.ts +354 -0
- package/dist/http-types-DqJubRPJ.d.ts +292 -0
- package/dist/meta-utils-0Pu0Nrap.js +117 -0
- package/dist/middleware-BUybuv9n.d.ts +34 -0
- package/dist/middleware-C2qTZ3V7.js +84 -0
- package/dist/orm/index.d.ts +17 -0
- package/dist/orm/index.js +10713 -0
- package/dist/plugins/index.d.ts +2 -0
- package/dist/plugins/index.js +3 -0
- package/dist/procedure-caller-DtxLmGwA.d.ts +1467 -0
- package/dist/procedure-caller-MWcxhQDv.js +349 -0
- package/dist/query-context-B8o6-8kC.js +1518 -0
- package/dist/query-context-CFZqIvD7.d.ts +42 -0
- package/dist/query-options-Dw7cOyXl.js +121 -0
- package/dist/ratelimit/index.d.ts +269 -0
- package/dist/ratelimit/index.js +856 -0
- package/dist/ratelimit/react/index.d.ts +76 -0
- package/dist/ratelimit/react/index.js +183 -0
- package/dist/react/index.d.ts +1284 -0
- package/dist/react/index.js +2526 -0
- package/dist/rsc/index.d.ts +276 -0
- package/dist/rsc/index.js +233 -0
- package/dist/runtime-CtvJPkur.js +2453 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.js +6 -0
- package/dist/solid/index.d.ts +1221 -0
- package/dist/solid/index.js +2940 -0
- package/dist/transformer-DtDhR3Lc.js +194 -0
- package/dist/types-BTb_4BaU.d.ts +42 -0
- package/dist/types-BiJE7qxR.d.ts +4 -0
- package/dist/types-DEJpkIhw.d.ts +88 -0
- package/dist/types-HhO_R6pd.d.ts +213 -0
- package/dist/validators-B7oIJCAp.js +279 -0
- package/dist/validators-vzRKjBJC.d.ts +88 -0
- package/dist/watcher.mjs +96 -0
- package/dist/where-clause-compiler-DdjN63Io.d.ts +4756 -0
- package/package.json +107 -35
- package/skills/convex/SKILL.md +486 -0
- package/skills/convex/references/features/aggregates.md +353 -0
- package/skills/convex/references/features/auth-admin.md +446 -0
- package/skills/convex/references/features/auth-organizations.md +1141 -0
- package/skills/convex/references/features/auth-polar.md +579 -0
- package/skills/convex/references/features/auth.md +470 -0
- package/skills/convex/references/features/create-plugins.md +153 -0
- package/skills/convex/references/features/http.md +676 -0
- package/skills/convex/references/features/migrations.md +162 -0
- package/skills/convex/references/features/orm.md +1166 -0
- package/skills/convex/references/features/react.md +657 -0
- package/skills/convex/references/features/scheduling.md +267 -0
- package/skills/convex/references/features/testing.md +209 -0
- package/skills/convex/references/setup/auth.md +501 -0
- package/skills/convex/references/setup/biome.md +190 -0
- package/skills/convex/references/setup/doc-guidelines.md +145 -0
- package/skills/convex/references/setup/index.md +759 -0
- package/skills/convex/references/setup/next.md +116 -0
- package/skills/convex/references/setup/react.md +175 -0
- package/skills/convex/references/setup/server.md +473 -0
- package/skills/convex/references/setup/start.md +67 -0
- package/LICENSE +0 -21
- package/README.md +0 -0
- package/dist/index.d.mts +0 -5
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -6
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import { asObjectValidator, v } from "convex/values";
|
|
2
|
+
|
|
3
|
+
//#region src/internal/upstream/index.ts
|
|
4
|
+
/** biome-ignore-all lint: vendored upstream helper source */
|
|
5
|
+
/**
|
|
6
|
+
* Vendored from upstream helper repository at commit c5e52c8.
|
|
7
|
+
* Source path: packages/convex_helpers/index.ts
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* asyncMap returns the results of applying an async function over an list.
|
|
11
|
+
*
|
|
12
|
+
* The list can even be a promise, or an iterable like a Set.
|
|
13
|
+
* @param list - Iterable object of items, e.g. an Array, Set, Object.keys
|
|
14
|
+
* @param asyncTransform
|
|
15
|
+
* @returns
|
|
16
|
+
*/
|
|
17
|
+
async function asyncMap(list, asyncTransform) {
|
|
18
|
+
const promises = [];
|
|
19
|
+
let index = 0;
|
|
20
|
+
list = await list;
|
|
21
|
+
for (const item of list) {
|
|
22
|
+
promises.push(asyncTransform(item, index));
|
|
23
|
+
index += 1;
|
|
24
|
+
}
|
|
25
|
+
return Promise.all(promises);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* pick helps you pick keys from an object more concisely.
|
|
29
|
+
*
|
|
30
|
+
* e.g. `pick({a: v.string(), b: v.number()}, ["a"])` is equivalent to
|
|
31
|
+
* `{a: v.string()}`
|
|
32
|
+
* The alternative could be something like:
|
|
33
|
+
* ```js
|
|
34
|
+
* const obj = { a: v.string(), b: v.number() };
|
|
35
|
+
* // pick does the following
|
|
36
|
+
* const { a } = obj;
|
|
37
|
+
* const onlyA = { a };
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @param obj The object to pick from. Often like { a: v.string() }
|
|
41
|
+
* @param keys The keys to pick from the object.
|
|
42
|
+
* @returns A new object with only the keys you picked and their values.
|
|
43
|
+
*/
|
|
44
|
+
function pick(obj, keys) {
|
|
45
|
+
return Object.fromEntries(Object.entries(obj).filter(([k]) => keys.includes(k)));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* omit helps you omit keys from an object more concisely.
|
|
49
|
+
*
|
|
50
|
+
* e.g. `omit({a: v.string(), b: v.number()}, ["a"])` is equivalent to
|
|
51
|
+
* `{b: v.number()}`
|
|
52
|
+
*
|
|
53
|
+
* The alternative could be something like:
|
|
54
|
+
* ```js
|
|
55
|
+
* const obj = { a: v.string(), b: v.number() };
|
|
56
|
+
* // omit does the following
|
|
57
|
+
* const { a, ...rest } = obj;
|
|
58
|
+
* const withoutA = rest;
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @param obj The object to return a copy of without the specified keys.
|
|
62
|
+
* @param keys The keys to omit from the object.
|
|
63
|
+
* @returns A new object with the keys you omitted removed.
|
|
64
|
+
*/
|
|
65
|
+
function omit(obj, keys) {
|
|
66
|
+
return Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k)));
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* A utility to validate truthiness at runtime, providing a type guard
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const x: string | null = getValue();
|
|
74
|
+
* assert(x);
|
|
75
|
+
* // x is now of type string
|
|
76
|
+
* ```
|
|
77
|
+
* You can also provide a function, to avoid doing expensive string templating.
|
|
78
|
+
* @param arg A value to assert the truthiness of.
|
|
79
|
+
* @param message An optional message to throw if the value is not truthy, or a function to generate the message.
|
|
80
|
+
*/
|
|
81
|
+
function assert(value, message) {
|
|
82
|
+
if (!value) throw new Error(typeof message === "function" ? message() : message);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/internal/upstream/validators.ts
|
|
87
|
+
function partial(fieldsOrObjOrUnion) {
|
|
88
|
+
if (fieldsOrObjOrUnion.isConvexValidator) {
|
|
89
|
+
if (fieldsOrObjOrUnion.kind === "object") return partialVObject(fieldsOrObjOrUnion);
|
|
90
|
+
if (fieldsOrObjOrUnion.kind === "union") return partialUnion(fieldsOrObjOrUnion);
|
|
91
|
+
throw new Error("partial only works with union or object Validators, or a Record<string, Validator> currently");
|
|
92
|
+
}
|
|
93
|
+
return partialFields(fieldsOrObjOrUnion);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* partialFields helps you define an object of optional validators more concisely.
|
|
97
|
+
*
|
|
98
|
+
* e.g. `partialFields({a: v.string(), b: v.number()})` is equivalent to
|
|
99
|
+
* `{a: v.optional(v.string()), b: v.optional(v.number())}`
|
|
100
|
+
*
|
|
101
|
+
* @param obj The object of validators to make optional. e.g. {a: v.string()}
|
|
102
|
+
* @returns A new object of validators that can be the value or undefined.
|
|
103
|
+
*/
|
|
104
|
+
function partialFields(obj) {
|
|
105
|
+
return Object.fromEntries(Object.entries(obj).map(([k, vv]) => [k, vv.isOptional === "optional" ? vv : v.optional(vv)]));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* partialObject helps you define an object of optional validators more concisely.
|
|
109
|
+
*
|
|
110
|
+
* e.g. `partialObject({a: v.string(), b: v.number()})` is equivalent to
|
|
111
|
+
* `{a: v.optional(v.string()), b: v.optional(v.number())}`
|
|
112
|
+
*
|
|
113
|
+
* @param obj The object of validators to make optional. e.g. {a: v.string()}
|
|
114
|
+
* @returns A new object of validators that can be the value or undefined.
|
|
115
|
+
*/
|
|
116
|
+
function partialVObject(obj) {
|
|
117
|
+
const o = v.object(partialFields(obj.fields));
|
|
118
|
+
if (obj.isOptional === "optional") return v.optional(o);
|
|
119
|
+
return o;
|
|
120
|
+
}
|
|
121
|
+
function partialUnion(union) {
|
|
122
|
+
const u = v.union(...union.members.map((m) => {
|
|
123
|
+
assert(m.isOptional === "required", "Union members cannot be optional");
|
|
124
|
+
if (m.kind === "object") return partialVObject(m);
|
|
125
|
+
if (m.kind === "union") return partialUnion(m);
|
|
126
|
+
throw new Error(`Invalid union member type: ${m.kind}`);
|
|
127
|
+
}));
|
|
128
|
+
if (union.isOptional === "optional") return v.optional(u);
|
|
129
|
+
return u;
|
|
130
|
+
}
|
|
131
|
+
/** @deprecated Use `v.string()` instead. Any string value. */
|
|
132
|
+
const string = v.string();
|
|
133
|
+
/** @deprecated Use `v.float64()` instead. JavaScript number, represented as a float64 in the database. */
|
|
134
|
+
const number = v.float64();
|
|
135
|
+
/** @deprecated Use `v.float64()` instead. JavaScript number, represented as a float64 in the database. */
|
|
136
|
+
const float64 = v.float64();
|
|
137
|
+
/** @deprecated Use `v.boolean()` instead. boolean value. For typing it only as true, use `l(true)` */
|
|
138
|
+
const boolean = v.boolean();
|
|
139
|
+
/** @deprecated Use `v.int64()` instead. bigint, though stored as an int64 in the database. */
|
|
140
|
+
const biging = v.int64();
|
|
141
|
+
/** @deprecated Use `v.int64()` instead. bigint, though stored as an int64 in the database. */
|
|
142
|
+
const int64 = v.int64();
|
|
143
|
+
/** @deprecated Use `v.any()` instead. Any Convex value */
|
|
144
|
+
const any = v.any();
|
|
145
|
+
/** @deprecated Use `v.null()` instead. Null value. Underscore is so it doesn't shadow the null builtin */
|
|
146
|
+
const null_ = v.null();
|
|
147
|
+
/** @deprecated Use `v.*()` instead. */
|
|
148
|
+
const { id, object, array, bytes, literal, optional, union } = v;
|
|
149
|
+
/** @deprecated Use `v.bytes()` instead. ArrayBuffer validator. */
|
|
150
|
+
const arrayBuffer = v.bytes();
|
|
151
|
+
function addFieldsToValidator(validatorOrFields, fields) {
|
|
152
|
+
const validator = asObjectValidator(validatorOrFields);
|
|
153
|
+
if (Object.keys(fields).length === 0) return validator;
|
|
154
|
+
switch (validator.kind) {
|
|
155
|
+
case "object": return v.object(intersectValidators(validator.fields, fields));
|
|
156
|
+
case "union": return v.union(...validator.members.map((m) => addFieldsToValidator(m, fields)));
|
|
157
|
+
default: throw new Error("Cannot add arguments to a validator that is not an object or union.");
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function intersectValidators(fields, fields2) {
|
|
161
|
+
const specificFields = { ...fields };
|
|
162
|
+
for (const [k, v] of Object.entries(fields2)) {
|
|
163
|
+
const existing = specificFields[k];
|
|
164
|
+
if (existing) {
|
|
165
|
+
if (existing.kind !== v.kind) throw new Error(`Cannot intersect validators with different kinds: ${existing.kind} and ${v.kind}`);
|
|
166
|
+
if (existing.isOptional !== v.isOptional && existing.isOptional === "optional") specificFields[k] = v;
|
|
167
|
+
} else specificFields[k] = v;
|
|
168
|
+
}
|
|
169
|
+
return specificFields;
|
|
170
|
+
}
|
|
171
|
+
/** Mark fields as deprecated with this permissive validator typed as null */
|
|
172
|
+
const deprecated = v.optional(v.any());
|
|
173
|
+
/** A maximally permissive validator that type checks as a given validator.
|
|
174
|
+
*
|
|
175
|
+
* If you want to have types that match some validator but you have invalid data
|
|
176
|
+
* and you want to temporarily not validate schema for this field,
|
|
177
|
+
* you can use this function to cast the permissive validator.
|
|
178
|
+
*
|
|
179
|
+
* Example in a schema:
|
|
180
|
+
* ```ts
|
|
181
|
+
* export default defineSchema({
|
|
182
|
+
* myTable: defineTable({
|
|
183
|
+
* myString: pretend(v.array(v.string())),
|
|
184
|
+
* }),
|
|
185
|
+
* });
|
|
186
|
+
* //...in some mutation
|
|
187
|
+
* ctx.db.insert("myTable", { myString: 123 as any }); // no runtime error
|
|
188
|
+
* ```
|
|
189
|
+
* Example in function argument validation:
|
|
190
|
+
* ```ts
|
|
191
|
+
* const myQuery = defineQuery({
|
|
192
|
+
* args: { myNumber: pretend(v.number()) },
|
|
193
|
+
* handler: async (ctx, args) => {
|
|
194
|
+
* // args.myNumber is typed as number, but it's not validated.
|
|
195
|
+
* const num = typeof args.myNumber === "number" ?
|
|
196
|
+
* args.myNumber : Number(args.myNumber);
|
|
197
|
+
* },
|
|
198
|
+
* });
|
|
199
|
+
*/
|
|
200
|
+
const pretend = (_typeToImmitate) => v.optional(v.any());
|
|
201
|
+
/** A validator that validates as optional but type checks as required.
|
|
202
|
+
*
|
|
203
|
+
* If you want to assume a field is set for type checking, but your data may not
|
|
204
|
+
* actually have it set for all documents (e.g. when adding a new field),
|
|
205
|
+
* you can use this function to allow the field to be unset at runtime.
|
|
206
|
+
* This is unsafe, but can be convenient in these situations:
|
|
207
|
+
*
|
|
208
|
+
* 1. You are developing locally and want to add a required field and write
|
|
209
|
+
* code assuming it is set. Once you push the code & schema, you can update
|
|
210
|
+
* the data to match before running your code.
|
|
211
|
+
* 2. You are going to run a migration right after pushing code, and are ok with
|
|
212
|
+
* and you don't want to edit your code to handle the field being unset,
|
|
213
|
+
* your app being in an inconsistent state until the migration completes.
|
|
214
|
+
*
|
|
215
|
+
* This differs from {@link pretend} in that it type checks the inner validator,
|
|
216
|
+
* if the value is provided.
|
|
217
|
+
*
|
|
218
|
+
* Example in a schema:
|
|
219
|
+
* ```ts
|
|
220
|
+
* export default defineSchema({
|
|
221
|
+
* myTable: defineTable({
|
|
222
|
+
* myString: pretendRequired(v.array(v.string())),
|
|
223
|
+
* }),
|
|
224
|
+
* });
|
|
225
|
+
* //...in some mutation
|
|
226
|
+
* ctx.db.insert("myTable", { myString: undefined }); // no runtime error
|
|
227
|
+
* ```
|
|
228
|
+
* Example in function argument validation:
|
|
229
|
+
* ```ts
|
|
230
|
+
* const myQuery = defineQuery({
|
|
231
|
+
* args: { myNumber: pretendRequired(v.number()) },
|
|
232
|
+
* handler: async (ctx, args) => {
|
|
233
|
+
* // args.myNumber is typed as number, but it might be undefined
|
|
234
|
+
* const num = args.myNumber || 0;
|
|
235
|
+
* },
|
|
236
|
+
* });
|
|
237
|
+
*/
|
|
238
|
+
const pretendRequired = (optionalType) => v.optional(optionalType);
|
|
239
|
+
/**
|
|
240
|
+
* Converts an optional validator to a required validator.
|
|
241
|
+
*
|
|
242
|
+
* This is the inverse of `v.optional()`. It takes a validator that may be optional
|
|
243
|
+
* and returns the equivalent required validator.
|
|
244
|
+
*
|
|
245
|
+
* ```ts
|
|
246
|
+
* const optionalString = v.optional(v.string());
|
|
247
|
+
* const requiredString = vRequired(optionalString); // v.string()
|
|
248
|
+
*
|
|
249
|
+
* // Already required validators are returned as-is
|
|
250
|
+
* const alreadyRequired = v.string();
|
|
251
|
+
* const stillRequired = vRequired(alreadyRequired); // v.string()
|
|
252
|
+
* ```
|
|
253
|
+
*
|
|
254
|
+
* @param validator The validator to make required.
|
|
255
|
+
* @returns A required version of the validator.
|
|
256
|
+
*/
|
|
257
|
+
function vRequired(validator) {
|
|
258
|
+
const { kind, isOptional } = validator;
|
|
259
|
+
if (isOptional === "required") return validator;
|
|
260
|
+
switch (kind) {
|
|
261
|
+
case "id": return v.id(validator.tableName);
|
|
262
|
+
case "string": return v.string();
|
|
263
|
+
case "float64": return v.float64();
|
|
264
|
+
case "int64": return v.int64();
|
|
265
|
+
case "boolean": return v.boolean();
|
|
266
|
+
case "null": return v.null();
|
|
267
|
+
case "any": return v.any();
|
|
268
|
+
case "literal": return v.literal(validator.value);
|
|
269
|
+
case "bytes": return v.bytes();
|
|
270
|
+
case "object": return v.object(validator.fields);
|
|
271
|
+
case "array": return v.array(validator.element);
|
|
272
|
+
case "record": return v.record(validator.key, validator.value);
|
|
273
|
+
case "union": return v.union(...validator.members);
|
|
274
|
+
default: throw new Error("Unknown Convex validator type: " + kind);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
//#endregion
|
|
279
|
+
export { pretendRequired as a, omit as c, pretend as i, pick as l, deprecated as n, vRequired as o, partial as r, asyncMap as s, addFieldsToValidator as t };
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { GenericId, GenericValidator, Infer, ObjectType, OptionalProperty, PropertyValidators, VAny, VArray, VBoolean, VBytes, VFloat64, VId, VInt64, VLiteral, VNull, VObject, VOptional, VRecord, VString, VUnion, Validator, v } from "convex/values";
|
|
2
|
+
import { GenericDataModel, GenericDatabaseReader, SchemaDefinition, TableNamesInDataModel } from "convex/server";
|
|
3
|
+
|
|
4
|
+
//#region src/internal/upstream/validators.d.ts
|
|
5
|
+
/** Mark fields as deprecated with this permissive validator typed as null */
|
|
6
|
+
declare const deprecated: Validator<null, "optional">;
|
|
7
|
+
/** A maximally permissive validator that type checks as a given validator.
|
|
8
|
+
*
|
|
9
|
+
* If you want to have types that match some validator but you have invalid data
|
|
10
|
+
* and you want to temporarily not validate schema for this field,
|
|
11
|
+
* you can use this function to cast the permissive validator.
|
|
12
|
+
*
|
|
13
|
+
* Example in a schema:
|
|
14
|
+
* ```ts
|
|
15
|
+
* export default defineSchema({
|
|
16
|
+
* myTable: defineTable({
|
|
17
|
+
* myString: pretend(v.array(v.string())),
|
|
18
|
+
* }),
|
|
19
|
+
* });
|
|
20
|
+
* //...in some mutation
|
|
21
|
+
* ctx.db.insert("myTable", { myString: 123 as any }); // no runtime error
|
|
22
|
+
* ```
|
|
23
|
+
* Example in function argument validation:
|
|
24
|
+
* ```ts
|
|
25
|
+
* const myQuery = defineQuery({
|
|
26
|
+
* args: { myNumber: pretend(v.number()) },
|
|
27
|
+
* handler: async (ctx, args) => {
|
|
28
|
+
* // args.myNumber is typed as number, but it's not validated.
|
|
29
|
+
* const num = typeof args.myNumber === "number" ?
|
|
30
|
+
* args.myNumber : Number(args.myNumber);
|
|
31
|
+
* },
|
|
32
|
+
* });
|
|
33
|
+
*/
|
|
34
|
+
declare const pretend: <T extends GenericValidator>(_typeToImmitate: T) => T;
|
|
35
|
+
/** A validator that validates as optional but type checks as required.
|
|
36
|
+
*
|
|
37
|
+
* If you want to assume a field is set for type checking, but your data may not
|
|
38
|
+
* actually have it set for all documents (e.g. when adding a new field),
|
|
39
|
+
* you can use this function to allow the field to be unset at runtime.
|
|
40
|
+
* This is unsafe, but can be convenient in these situations:
|
|
41
|
+
*
|
|
42
|
+
* 1. You are developing locally and want to add a required field and write
|
|
43
|
+
* code assuming it is set. Once you push the code & schema, you can update
|
|
44
|
+
* the data to match before running your code.
|
|
45
|
+
* 2. You are going to run a migration right after pushing code, and are ok with
|
|
46
|
+
* and you don't want to edit your code to handle the field being unset,
|
|
47
|
+
* your app being in an inconsistent state until the migration completes.
|
|
48
|
+
*
|
|
49
|
+
* This differs from {@link pretend} in that it type checks the inner validator,
|
|
50
|
+
* if the value is provided.
|
|
51
|
+
*
|
|
52
|
+
* Example in a schema:
|
|
53
|
+
* ```ts
|
|
54
|
+
* export default defineSchema({
|
|
55
|
+
* myTable: defineTable({
|
|
56
|
+
* myString: pretendRequired(v.array(v.string())),
|
|
57
|
+
* }),
|
|
58
|
+
* });
|
|
59
|
+
* //...in some mutation
|
|
60
|
+
* ctx.db.insert("myTable", { myString: undefined }); // no runtime error
|
|
61
|
+
* ```
|
|
62
|
+
* Example in function argument validation:
|
|
63
|
+
* ```ts
|
|
64
|
+
* const myQuery = defineQuery({
|
|
65
|
+
* args: { myNumber: pretendRequired(v.number()) },
|
|
66
|
+
* handler: async (ctx, args) => {
|
|
67
|
+
* // args.myNumber is typed as number, but it might be undefined
|
|
68
|
+
* const num = args.myNumber || 0;
|
|
69
|
+
* },
|
|
70
|
+
* });
|
|
71
|
+
*/
|
|
72
|
+
declare const pretendRequired: <T extends Validator<any, "required", any>>(optionalType: T) => T;
|
|
73
|
+
type NotUndefined<T> = Exclude<T, undefined>;
|
|
74
|
+
/**
|
|
75
|
+
* A type that converts an optional validator to a required validator.
|
|
76
|
+
*
|
|
77
|
+
* This is the inverse of `VOptional`. It takes a validator that may be optional
|
|
78
|
+
* and returns the equivalent required validator type.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* type OptionalString = VOptional<VString<string, "required">>;
|
|
83
|
+
* type RequiredString = VRequired<OptionalString>; // VString<string, "required">
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
type VRequired<T extends Validator<any, OptionalProperty, any>> = T extends VId<infer Type, OptionalProperty> ? VId<NotUndefined<Type>, 'required'> : T extends VString<infer Type, OptionalProperty> ? VString<NotUndefined<Type>, 'required'> : T extends VFloat64<infer Type, OptionalProperty> ? VFloat64<NotUndefined<Type>, 'required'> : T extends VInt64<infer Type, OptionalProperty> ? VInt64<NotUndefined<Type>, 'required'> : T extends VBoolean<infer Type, OptionalProperty> ? VBoolean<NotUndefined<Type>, 'required'> : T extends VNull<infer Type, OptionalProperty> ? VNull<NotUndefined<Type>, 'required'> : T extends VAny<infer Type, OptionalProperty> ? VAny<NotUndefined<Type>, 'required'> : T extends VLiteral<infer Type, OptionalProperty> ? VLiteral<NotUndefined<Type>, 'required'> : T extends VBytes<infer Type, OptionalProperty> ? VBytes<NotUndefined<Type>, 'required'> : T extends VObject<infer Type, infer Fields, OptionalProperty, infer FieldPaths> ? VObject<NotUndefined<Type>, Fields, 'required', FieldPaths> : T extends VArray<infer Type, infer Element, OptionalProperty> ? VArray<NotUndefined<Type>, Element, 'required'> : T extends VRecord<infer Type, infer Key, infer Value, OptionalProperty, infer FieldPaths> ? VRecord<NotUndefined<Type>, Key, Value, 'required', FieldPaths> : T extends VUnion<infer Type, infer Members, OptionalProperty, infer FieldPaths> ? VUnion<NotUndefined<Type>, Members, 'required', FieldPaths> : never;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { pretendRequired as i, deprecated as n, pretend as r, VRequired as t };
|
package/dist/watcher.mjs
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { n as getConvexConfig, r as logger, t as generateMeta } from "./codegen-lF80HSWu.mjs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
//#region src/cli/watcher.ts
|
|
7
|
+
function getWatchRoots(functionsDir) {
|
|
8
|
+
const convexDir = path.dirname(functionsDir);
|
|
9
|
+
return [functionsDir, path.join(convexDir, "routers")];
|
|
10
|
+
}
|
|
11
|
+
function parseTrimSegmentsEnv(value) {
|
|
12
|
+
if (!value) return;
|
|
13
|
+
const parseFromArray = (segments) => {
|
|
14
|
+
const normalized = [...new Set(segments.map((segment) => segment.trim()).filter((segment) => segment))];
|
|
15
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
16
|
+
};
|
|
17
|
+
const trimmed = value.trim();
|
|
18
|
+
if (!trimmed) return;
|
|
19
|
+
if (trimmed.startsWith("[")) try {
|
|
20
|
+
const parsed = JSON.parse(trimmed);
|
|
21
|
+
if (Array.isArray(parsed) && parsed.every((segment) => typeof segment === "string")) return parseFromArray(parsed);
|
|
22
|
+
} catch {}
|
|
23
|
+
return parseFromArray(trimmed.split(","));
|
|
24
|
+
}
|
|
25
|
+
function shouldIgnoreWatchPath(watchedPath, functionsDir, outputFile) {
|
|
26
|
+
const normalizedPath = path.resolve(watchedPath);
|
|
27
|
+
const normalizedFunctionsDir = path.resolve(functionsDir);
|
|
28
|
+
const normalizedOutputFile = path.resolve(outputFile);
|
|
29
|
+
const generatedDir = path.join(normalizedFunctionsDir, "generated");
|
|
30
|
+
const generatedFile = path.join(normalizedFunctionsDir, "generated.ts");
|
|
31
|
+
if (normalizedPath === normalizedOutputFile) return true;
|
|
32
|
+
if (normalizedPath === generatedFile) return true;
|
|
33
|
+
if (normalizedPath === generatedDir || normalizedPath.startsWith(`${generatedDir}${path.sep}`)) return true;
|
|
34
|
+
return normalizedPath.endsWith(".runtime.ts");
|
|
35
|
+
}
|
|
36
|
+
async function startWatcher(opts) {
|
|
37
|
+
const sharedDir = opts?.sharedDir ?? (process.env.KITCN_API_OUTPUT_DIR || void 0);
|
|
38
|
+
const debug = opts?.debug ?? process.env.KITCN_DEBUG === "1";
|
|
39
|
+
const scope = opts?.scope ?? process.env.KITCN_CODEGEN_SCOPE ?? "all";
|
|
40
|
+
const trimSegments = opts?.trimSegments ?? parseTrimSegmentsEnv(process.env.KITCN_CODEGEN_TRIM_SEGMENTS);
|
|
41
|
+
const debounceMs = opts?.debounceMs ?? 100;
|
|
42
|
+
const resolveConfig = opts?.getConvexConfig ?? getConvexConfig;
|
|
43
|
+
const runGenerateMeta = opts?.generateMeta ?? generateMeta;
|
|
44
|
+
const { functionsDir, outputFile } = resolveConfig(sharedDir);
|
|
45
|
+
const watchRoots = getWatchRoots(functionsDir);
|
|
46
|
+
const watch = opts?.watch ?? (await import("chokidar")).watch;
|
|
47
|
+
let debounceTimer = null;
|
|
48
|
+
let generateMetaInFlight = false;
|
|
49
|
+
let generateMetaQueued = false;
|
|
50
|
+
const createGenerateOptions = () => {
|
|
51
|
+
const generateOptions = {
|
|
52
|
+
debug,
|
|
53
|
+
silent: true,
|
|
54
|
+
scope
|
|
55
|
+
};
|
|
56
|
+
if (trimSegments && trimSegments.length > 0) generateOptions.trimSegments = trimSegments;
|
|
57
|
+
return generateOptions;
|
|
58
|
+
};
|
|
59
|
+
const runGenerateMetaSafely = async () => {
|
|
60
|
+
if (generateMetaInFlight) {
|
|
61
|
+
generateMetaQueued = true;
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
generateMetaInFlight = true;
|
|
65
|
+
try {
|
|
66
|
+
await runGenerateMeta(sharedDir, createGenerateOptions());
|
|
67
|
+
logger.success("Convex api updated");
|
|
68
|
+
} catch (error) {
|
|
69
|
+
logger.error("Watch codegen error:", error);
|
|
70
|
+
} finally {
|
|
71
|
+
generateMetaInFlight = false;
|
|
72
|
+
if (generateMetaQueued) {
|
|
73
|
+
generateMetaQueued = false;
|
|
74
|
+
scheduleGenerateMeta();
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const scheduleGenerateMeta = () => {
|
|
79
|
+
if (debounceTimer) clearTimeout(debounceTimer);
|
|
80
|
+
debounceTimer = setTimeout(() => {
|
|
81
|
+
debounceTimer = null;
|
|
82
|
+
runGenerateMetaSafely();
|
|
83
|
+
}, debounceMs);
|
|
84
|
+
};
|
|
85
|
+
return watch(watchRoots, {
|
|
86
|
+
ignoreInitial: true,
|
|
87
|
+
ignored: (watchedPath) => shouldIgnoreWatchPath(watchedPath, functionsDir, outputFile)
|
|
88
|
+
}).on("add", scheduleGenerateMeta).on("change", scheduleGenerateMeta).on("unlink", scheduleGenerateMeta).on("error", (err) => logger.error("Watch error:", err));
|
|
89
|
+
}
|
|
90
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) startWatcher().catch((error) => {
|
|
91
|
+
logger.error("Watch error:", error);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
//#endregion
|
|
96
|
+
export { getWatchRoots, shouldIgnoreWatchPath, startWatcher };
|