kitcn 0.25.2 → 0.25.4
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/dist/aggregate/index.d.ts +2 -2
- package/dist/auth/generated/index.d.ts +1 -1
- package/dist/auth/index.d.ts +6 -6
- package/dist/{capabilities-Bem7xvGK.d.ts → capabilities-DtDfpdcH.d.ts} +20 -1
- package/dist/{generated-contract-disabled-BEc4d98x.d.ts → generated-contract-disabled-DwYwySy3.d.ts} +2 -2
- package/dist/orm/aggregate-index/index.d.ts +1 -1
- package/dist/orm/aggregate-index/index.js +15 -4
- package/dist/orm/index.d.ts +2 -2
- package/dist/orm/index.js +63 -149
- package/dist/orm/migrations/index.d.ts +2 -2
- package/dist/{schema-D8sVYuYO.js → schema-e0wbZ_Ax.js} +138 -77
- package/dist/{where-clause-compiler-TMNQB6US.d.ts → where-clause-compiler-CCMtAIdx.d.ts} +56 -56
- package/package.json +1 -1
- package/skills/kitcn/references/features/aggregates.md +3 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Bn as ConvexTextBuilderInitial, Xt as ConvexTableWithColumns } from "../capabilities-
|
|
2
|
-
import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial } from "../where-clause-compiler-
|
|
1
|
+
import { Bn as ConvexTextBuilderInitial, Xt as ConvexTableWithColumns } from "../capabilities-DtDfpdcH.js";
|
|
2
|
+
import { C as ConvexNumberBuilderInitial, E as ConvexIdBuilderInitial, N as ConvexCustomBuilderInitial } from "../where-clause-compiler-CCMtAIdx.js";
|
|
3
3
|
import * as convex_values0 from "convex/values";
|
|
4
4
|
import { GenericId, Infer, Value } from "convex/values";
|
|
5
5
|
import { DocumentByName, GenericDataModel, GenericDatabaseReader, GenericDatabaseWriter, TableNamesInDataModel } from "convex/server";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-
|
|
1
|
+
import { S as defineAuth, _ as GenericAuthBeforeResult, b as GenericAuthTriggerHandlers, g as BetterAuthOptionsWithoutDatabase, i as getGeneratedAuthDisabledReason, n as GeneratedAuthDisabledReasonKind, r as createDisabledAuthRuntime, t as AuthRuntime, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../../generated-contract-disabled-DwYwySy3.js";
|
|
2
2
|
export { type AuthRuntime, BetterAuthOptionsWithoutDatabase, type GeneratedAuthDisabledReasonKind, GenericAuthBeforeResult, GenericAuthDefinition, GenericAuthTriggerChange, GenericAuthTriggerHandlers, GenericAuthTriggers, createDisabledAuthRuntime, defineAuth, getGeneratedAuthDisabledReason };
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as QueryCtxWithPreferredOrmQueryTable, n as LookupByIdResultByCtx, t as DocByCtx } from "../query-context-DJONf8X5.js";
|
|
2
2
|
import { t as GetAuth } from "../types-Bf3XQex5.js";
|
|
3
3
|
import { t as GenericCtx } from "../context-utils-DwZ3Cam1.js";
|
|
4
|
-
import { S as defineAuth, _ as GenericAuthBeforeResult, a as AuthFunctions, b as GenericAuthTriggerHandlers, c as createApi, d as deleteOneHandler, f as findManyHandler, g as BetterAuthOptionsWithoutDatabase, h as updateOneHandler, i as getGeneratedAuthDisabledReason, l as createHandler, m as updateManyHandler, n as GeneratedAuthDisabledReasonKind, o as Triggers, p as findOneHandler, r as createDisabledAuthRuntime, s as createClient, t as AuthRuntime, u as deleteManyHandler, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../generated-contract-disabled-
|
|
4
|
+
import { S as defineAuth, _ as GenericAuthBeforeResult, a as AuthFunctions, b as GenericAuthTriggerHandlers, c as createApi, d as deleteOneHandler, f as findManyHandler, g as BetterAuthOptionsWithoutDatabase, h as updateOneHandler, i as getGeneratedAuthDisabledReason, l as createHandler, m as updateManyHandler, n as GeneratedAuthDisabledReasonKind, o as Triggers, p as findOneHandler, r as createDisabledAuthRuntime, s as createClient, t as AuthRuntime, u as deleteManyHandler, v as GenericAuthDefinition, x as GenericAuthTriggers, y as GenericAuthTriggerChange } from "../generated-contract-disabled-DwYwySy3.js";
|
|
5
5
|
import * as convex_values0 from "convex/values";
|
|
6
6
|
import { Infer } from "convex/values";
|
|
7
7
|
import { AuthConfig, DocumentByName, GenericDataModel, GenericMutationCtx, GenericQueryCtx, GenericSchema, PaginationOptions, PaginationResult, SchemaDefinition, TableNamesInDataModel } from "convex/server";
|
|
@@ -123,6 +123,7 @@ declare const adapterWhereValidator: convex_values0.VObject<{
|
|
|
123
123
|
value: convex_values0.VUnion<string | number | boolean | string[] | number[] | null, [convex_values0.VString<string, "required">, convex_values0.VFloat64<number, "required">, convex_values0.VBoolean<boolean, "required">, convex_values0.VArray<string[], convex_values0.VString<string, "required">, "required">, convex_values0.VArray<number[], convex_values0.VFloat64<number, "required">, "required">, convex_values0.VNull<null, "required">], "required", never>;
|
|
124
124
|
}, "required", "mode" | "value" | "connector" | "field" | "operator">;
|
|
125
125
|
declare const adapterArgsValidator: convex_values0.VObject<{
|
|
126
|
+
limit?: number | undefined;
|
|
126
127
|
select?: string[] | undefined;
|
|
127
128
|
where?: {
|
|
128
129
|
mode?: "sensitive" | "insensitive" | undefined;
|
|
@@ -131,11 +132,10 @@ declare const adapterArgsValidator: convex_values0.VObject<{
|
|
|
131
132
|
value: string | number | boolean | string[] | number[] | null;
|
|
132
133
|
field: string;
|
|
133
134
|
}[] | undefined;
|
|
134
|
-
limit?: number | undefined;
|
|
135
135
|
offset?: number | undefined;
|
|
136
136
|
sortBy?: {
|
|
137
|
-
field: string;
|
|
138
137
|
direction: "asc" | "desc";
|
|
138
|
+
field: string;
|
|
139
139
|
} | undefined;
|
|
140
140
|
model: string;
|
|
141
141
|
}, {
|
|
@@ -144,12 +144,12 @@ declare const adapterArgsValidator: convex_values0.VObject<{
|
|
|
144
144
|
offset: convex_values0.VFloat64<number | undefined, "optional">;
|
|
145
145
|
select: convex_values0.VArray<string[] | undefined, convex_values0.VString<string, "required">, "optional">;
|
|
146
146
|
sortBy: convex_values0.VObject<{
|
|
147
|
-
field: string;
|
|
148
147
|
direction: "asc" | "desc";
|
|
148
|
+
field: string;
|
|
149
149
|
} | undefined, {
|
|
150
150
|
direction: convex_values0.VUnion<"asc" | "desc", [convex_values0.VLiteral<"asc", "required">, convex_values0.VLiteral<"desc", "required">], "required", never>;
|
|
151
151
|
field: convex_values0.VString<string, "required">;
|
|
152
|
-
}, "optional", "
|
|
152
|
+
}, "optional", "direction" | "field">;
|
|
153
153
|
where: convex_values0.VArray<{
|
|
154
154
|
mode?: "sensitive" | "insensitive" | undefined;
|
|
155
155
|
connector?: "AND" | "OR" | undefined;
|
|
@@ -169,7 +169,7 @@ declare const adapterArgsValidator: convex_values0.VObject<{
|
|
|
169
169
|
operator: convex_values0.VUnion<"lt" | "lte" | "gt" | "gte" | "eq" | "in" | "not_in" | "ne" | "contains" | "starts_with" | "ends_with" | undefined, [convex_values0.VLiteral<"lt", "required">, convex_values0.VLiteral<"lte", "required">, convex_values0.VLiteral<"gt", "required">, convex_values0.VLiteral<"gte", "required">, convex_values0.VLiteral<"eq", "required">, convex_values0.VLiteral<"in", "required">, convex_values0.VLiteral<"not_in", "required">, convex_values0.VLiteral<"ne", "required">, convex_values0.VLiteral<"contains", "required">, convex_values0.VLiteral<"starts_with", "required">, convex_values0.VLiteral<"ends_with", "required">], "optional", never>;
|
|
170
170
|
value: convex_values0.VUnion<string | number | boolean | string[] | number[] | null, [convex_values0.VString<string, "required">, convex_values0.VFloat64<number, "required">, convex_values0.VBoolean<boolean, "required">, convex_values0.VArray<string[], convex_values0.VString<string, "required">, "required">, convex_values0.VArray<number[], convex_values0.VFloat64<number, "required">, "required">, convex_values0.VNull<null, "required">], "required", never>;
|
|
171
171
|
}, "required", "mode" | "value" | "connector" | "field" | "operator">, "optional">;
|
|
172
|
-
}, "required", "
|
|
172
|
+
}, "required", "limit" | "model" | "select" | "where" | "offset" | "sortBy" | "sortBy.direction" | "sortBy.field">;
|
|
173
173
|
declare const hasUniqueFields: (betterAuthSchema: BetterAuthDBSchema, model: string, input: Record<string, any>) => boolean;
|
|
174
174
|
declare const checkUniqueFields: <Schema extends SchemaDefinition<any, any>>(ctx: GenericQueryCtx<GenericDataModel>, schema: Schema, betterAuthSchema: BetterAuthDBSchema, table: string, input: Record<string, any>, doc?: Record<string, any>) => Promise<void>;
|
|
175
175
|
declare const selectFields: <T extends TableNamesInDataModel<GenericDataModel>, D extends DocumentByName<GenericDataModel, T>>(doc: D | null, select?: string[]) => D | null;
|
|
@@ -2139,7 +2139,7 @@ declare const createAggregateError: (code: AggregateErrorCode, message: string)
|
|
|
2139
2139
|
declare const ensureCountAllowedForRls: (tableConfig: TableRelationalConfig, rlsMode: "skip" | "default" | undefined) => void;
|
|
2140
2140
|
declare const ensureAggregateAllowedForRls: (tableConfig: TableRelationalConfig, rlsMode: "skip" | "default" | undefined, methodName: string) => void;
|
|
2141
2141
|
declare namespace runtime_d_exports$1 {
|
|
2142
|
-
export { AGGREGATE_ERROR, AGGREGATE_STATE_KIND_METRIC, AGGREGATE_STATE_KIND_RANK, AggregateBucketDelta, AggregateErrorCode, AggregateExtremaDelta, AggregateIndexDefinition, AggregateMemberWrite, AggregateMembershipDelta, AggregateQueryPlan, AggregateRangeConstraint, COUNT_ERROR, COUNT_STATUS_BUILDING, COUNT_STATUS_CLEARING, COUNT_STATUS_READY, ClearIndexChunkResult, CountErrorCode, CountIndexDefinition, CountQueryPlan, CountState, PlanBucketReadCache, applyAggregateIndexesForChange, applyCountIndexesForChange, asUnknownArray, assertAggregateIndexesWritable, clearCountIndexChunk, compileAggregateQueryPlan, compileCountFieldQueryPlan, compileCountQueryPlan, computeAggregateMembershipDelta, computeAggregateMetricValues, computeCountKeyParts, createAggregateError, createCountError, ensureAggregateAllowedForRls, ensureAggregateIndexReady, ensureCountAllowedForRls, ensureCountIndexReady, flushAggregateMembershipDeltas, getAggregateIndexDefinitions, getCountIndexDefinitions, getCountIndexValuesForFields, getCountState, isAggregatePlanZero, isIndexCountZero, listCountStates, listSchemaAggregateIndexes, listSchemaCountIndexes, parseAggregateWhere, parseCountWhere, readAverageFromBuckets, readCountFieldFromBuckets, readCountFromBuckets, readExtremaFromBuckets, readPlanBuckets, readSumFromBuckets, reconcileAggregateMembership, serializeCountKeyParts, setCountState, setCountStateError };
|
|
2142
|
+
export { AGGREGATE_ERROR, AGGREGATE_STATE_KIND_METRIC, AGGREGATE_STATE_KIND_RANK, AggregateBucketDelta, AggregateErrorCode, AggregateExtremaDelta, AggregateIndexDefinition, AggregateMemberWrite, AggregateMembershipDelta, AggregateQueryPlan, AggregateRangeConstraint, COUNT_ERROR, COUNT_STATUS_BUILDING, COUNT_STATUS_CLEARING, COUNT_STATUS_READY, ClearIndexChunkResult, CountErrorCode, CountIndexDefinition, CountQueryPlan, CountState, NULLISH_PROBE_VALUES, PlanBucketReadCache, applyAggregateIndexesForChange, applyCountIndexesForChange, asUnknownArray, assertAggregateIndexesWritable, clearCountIndexChunk, compileAggregateQueryPlan, compileCountFieldQueryPlan, compileCountQueryPlan, computeAggregateMembershipDelta, computeAggregateMetricValues, computeCountKeyParts, createAggregateError, createCountError, ensureAggregateAllowedForRls, ensureAggregateIndexReady, ensureCountAllowedForRls, ensureCountIndexReady, flushAggregateMembershipDeltas, getAggregateIndexDefinitions, getCountIndexDefinitions, getCountIndexValuesForFields, getCountState, isAggregatePlanZero, isIndexCountZero, listCountStates, listSchemaAggregateIndexes, listSchemaCountIndexes, parseAggregateWhere, parseCountWhere, readAverageFromBuckets, readCountFieldFromBuckets, readCountFromBuckets, readExtremaFromBuckets, readPlanBuckets, readSumFromBuckets, reconcileAggregateMembership, serializeCountKeyParts, setCountState, setCountStateError };
|
|
2143
2143
|
}
|
|
2144
2144
|
declare const AGGREGATE_STATE_KIND_METRIC = "metric";
|
|
2145
2145
|
declare const AGGREGATE_STATE_KIND_RANK = "rank";
|
|
@@ -2216,6 +2216,17 @@ type AggregateQueryPlan = {
|
|
|
2216
2216
|
metric: AggregateMetricRequest;
|
|
2217
2217
|
};
|
|
2218
2218
|
type PlanBucketReadCache = Map<string, Promise<unknown[]>>;
|
|
2219
|
+
/**
|
|
2220
|
+
* A nullable column is `v.optional(v.union(v.null(), ...))`, so a row that
|
|
2221
|
+
* never had the column written stores it absent, and `computeCountKeyParts`
|
|
2222
|
+
* encodes absent as the `__kitcnUndefined` sentinel — a different bucket from
|
|
2223
|
+
* the one an explicit `null` lands in. `isNull` means null-or-absent
|
|
2224
|
+
* everywhere else in the ORM, so probing only the `null` bucket silently
|
|
2225
|
+
* undercounts every row written before the column existed. Both probes are
|
|
2226
|
+
* looked up through `serializeStable`, which maps `undefined` onto the same
|
|
2227
|
+
* sentinel the write path stored.
|
|
2228
|
+
*/
|
|
2229
|
+
declare const NULLISH_PROBE_VALUES: readonly unknown[];
|
|
2219
2230
|
declare const serializeCountKeyParts: (parts: unknown[]) => string;
|
|
2220
2231
|
declare const compileCountQueryPlan: (tableConfig: TableRelationalConfig, where: unknown) => CountQueryPlan;
|
|
2221
2232
|
declare const compileCountFieldQueryPlan: (tableConfig: TableRelationalConfig, where: unknown, field: string) => AggregateQueryPlan;
|
|
@@ -3030,6 +3041,14 @@ declare class GelRelationalQuery<TSchema extends TablesRelationalConfig, TTableC
|
|
|
3030
3041
|
private _pushGroupByConstraint;
|
|
3031
3042
|
private _parseGroupByFieldConstraint;
|
|
3032
3043
|
private _collectGroupByFieldValues;
|
|
3044
|
+
/**
|
|
3045
|
+
* One group per distinct value, where `null` and absent count as the same
|
|
3046
|
+
* value. They occupy different aggregate buckets, so the emitted group key
|
|
3047
|
+
* and the filter that reads it diverge: the key reports `null` while the
|
|
3048
|
+
* filter keeps `isNull` so the aggregate compiler reads both buckets and
|
|
3049
|
+
* combines their metrics into a single row.
|
|
3050
|
+
*/
|
|
3051
|
+
private _buildGroupBySlots;
|
|
3033
3052
|
private _buildGroupByCandidates;
|
|
3034
3053
|
private _coerceGroupByByFields;
|
|
3035
3054
|
private _isGroupByOrderDirection;
|
package/dist/{generated-contract-disabled-BEc4d98x.d.ts → generated-contract-disabled-DwYwySy3.d.ts}
RENAMED
|
@@ -224,6 +224,7 @@ declare const createApi: <Schema extends SchemaDefinition<any, any>, DataModel e
|
|
|
224
224
|
};
|
|
225
225
|
}, Promise<Record<string, unknown> | undefined>>;
|
|
226
226
|
findMany: convex_server0.RegisteredQuery<"internal", {
|
|
227
|
+
limit?: number | undefined;
|
|
227
228
|
join?: any;
|
|
228
229
|
where?: {
|
|
229
230
|
mode?: "sensitive" | "insensitive" | undefined;
|
|
@@ -232,11 +233,10 @@ declare const createApi: <Schema extends SchemaDefinition<any, any>, DataModel e
|
|
|
232
233
|
value: string | number | boolean | string[] | number[] | null;
|
|
233
234
|
field: string;
|
|
234
235
|
}[] | undefined;
|
|
235
|
-
limit?: number | undefined;
|
|
236
236
|
offset?: number | undefined;
|
|
237
237
|
sortBy?: {
|
|
238
|
-
field: string;
|
|
239
238
|
direction: "asc" | "desc";
|
|
239
|
+
field: string;
|
|
240
240
|
} | undefined;
|
|
241
241
|
model: string;
|
|
242
242
|
paginationOpts: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as RankOrderField, G as CountBackfillKickoffArgs, J as AggregateQueryPlan, K as CountBackfillMode, Q as RankIndexDefinition, W as CountBackfillChunkArgs, X as AggregateIndexDefinition, Y as CountQueryPlan, Z as CountIndexDefinition, q as CountBackfillStatusArgs, r as OrmCapability } from "../../capabilities-
|
|
1
|
+
import { $ as RankOrderField, G as CountBackfillKickoffArgs, J as AggregateQueryPlan, K as CountBackfillMode, Q as RankIndexDefinition, W as CountBackfillChunkArgs, X as AggregateIndexDefinition, Y as CountQueryPlan, Z as CountIndexDefinition, q as CountBackfillStatusArgs, r as OrmCapability } from "../../capabilities-DtDfpdcH.js";
|
|
2
2
|
|
|
3
3
|
//#region src/orm/aggregate-index/capability.d.ts
|
|
4
4
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { t as DirectAggregate } from "../../runtime-BdqTbgKh.js";
|
|
2
2
|
import { a as Columns } from "../../table-CX2lnX7e.js";
|
|
3
|
-
import { Y as normalizeTemporalComparableValue,
|
|
3
|
+
import { Y as normalizeTemporalComparableValue, bt as PUBLIC_CREATED_AT_FIELD, c as AGGREGATE_ERROR, f as createError, i as AGGREGATE_STATE_TABLE, l as COUNT_ERROR, lt as mapWithConcurrency, n as AGGREGATE_EXTREMA_TABLE, o as getAggregateIndexDefinitions, r as AGGREGATE_MEMBER_TABLE, s as getRankIndexDefinitions, t as AGGREGATE_BUCKET_TABLE, xt as usesSystemCreatedAtAlias, yt as INTERNAL_CREATION_TIME_FIELD } from "../../schema-e0wbZ_Ax.js";
|
|
4
4
|
|
|
5
5
|
//#region src/orm/aggregate-index/runtime.ts
|
|
6
6
|
const UNDEFINED_SENTINEL = "__kitcnUndefined";
|
|
@@ -27,6 +27,17 @@ const normalizeUndefined = (value) => {
|
|
|
27
27
|
return value;
|
|
28
28
|
};
|
|
29
29
|
const serializeStable = (value) => JSON.stringify(normalizeUndefined(value));
|
|
30
|
+
/**
|
|
31
|
+
* A nullable column is `v.optional(v.union(v.null(), ...))`, so a row that
|
|
32
|
+
* never had the column written stores it absent, and `computeCountKeyParts`
|
|
33
|
+
* encodes absent as the `__kitcnUndefined` sentinel — a different bucket from
|
|
34
|
+
* the one an explicit `null` lands in. `isNull` means null-or-absent
|
|
35
|
+
* everywhere else in the ORM, so probing only the `null` bucket silently
|
|
36
|
+
* undercounts every row written before the column existed. Both probes are
|
|
37
|
+
* looked up through `serializeStable`, which maps `undefined` onto the same
|
|
38
|
+
* sentinel the write path stored.
|
|
39
|
+
*/
|
|
40
|
+
const NULLISH_PROBE_VALUES = [null, void 0];
|
|
30
41
|
const toConstraintSet = (values) => {
|
|
31
42
|
const set = /* @__PURE__ */ new Map();
|
|
32
43
|
for (const value of values) set.set(serializeStable(value), value);
|
|
@@ -138,7 +149,7 @@ const parseFieldFilter = (tableConfig, fieldName, value, target, codes, methodNa
|
|
|
138
149
|
if (Object.hasOwn(filter, "isNull")) {
|
|
139
150
|
hasRecognizedOperator = true;
|
|
140
151
|
if (filter.isNull !== true) throw createFilterError(codes, methodName, `field '${fieldName}'.isNull only supports true.`);
|
|
141
|
-
pushConstraint(target, fieldName, [
|
|
152
|
+
pushConstraint(target, fieldName, [...NULLISH_PROBE_VALUES]);
|
|
142
153
|
}
|
|
143
154
|
for (const operator of [
|
|
144
155
|
"gt",
|
|
@@ -405,9 +416,9 @@ const enforceCartesianExpansionGuards = (options) => {
|
|
|
405
416
|
const maxTrackedCombinations = Math.max(cartesianMaxKeys, maxCombinationsByWork);
|
|
406
417
|
const combinations = countCartesianCombinations(options.fields, options.fieldValues, maxTrackedCombinations);
|
|
407
418
|
if (combinations === 0) return;
|
|
408
|
-
if (combinations > cartesianMaxKeys) throw createFilterError(options.codes, options.methodName, `expands
|
|
419
|
+
if (combinations > cartesianMaxKeys) throw createFilterError(options.codes, options.methodName, `expands to ${combinations} key combinations on aggregateIndex '${options.indexName}', exceeding aggregateCartesianMaxKeys (${cartesianMaxKeys}). Each 'in' value and each 'isNull' field (which reads both the null and the absent key) multiplies the combinations. Reduce IN list sizes, split the query, add a narrower aggregateIndex, or increase defineSchema(..., { defaults: { aggregateCartesianMaxKeys } }).`);
|
|
409
420
|
const estimatedWork = combinations * workUnitsPerCombination;
|
|
410
|
-
if (estimatedWork > workBudget) throw createFilterError(options.codes, options.methodName, `estimated ${options.workLabel} is ${estimatedWork} units on aggregateIndex '${options.indexName}', exceeding aggregateWorkBudget (${workBudget}). Reduce IN fan-out, split the query, or increase defineSchema(..., { defaults: { aggregateWorkBudget } }).`);
|
|
421
|
+
if (estimatedWork > workBudget) throw createFilterError(options.codes, options.methodName, `estimated ${options.workLabel} is ${estimatedWork} units on aggregateIndex '${options.indexName}', exceeding aggregateWorkBudget (${workBudget}). Reduce IN or isNull fan-out, split the query, or increase defineSchema(..., { defaults: { aggregateWorkBudget } }).`);
|
|
411
422
|
};
|
|
412
423
|
const hasLogicalOr = (where) => {
|
|
413
424
|
if (Object.hasOwn(where, "OR")) return true;
|
package/dist/orm/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { $n as BinaryExpression, $t as OrmLifecycleOperation, A as DatabaseWithMutations, An as ConvexCheckConfig, Ar as AnyColumn, At as VectorQueryConfig, B as RlsContext, Bn as ConvexTextBuilderInitial, Br as IsUnique, Bt as RelationsBuilderColumnConfig, C as MigrationTableName, Cn as aggregateIndex, Cr as notBetween, Ct as OrderDirection, D as defineMigrationSet, Dn as uniqueIndex, Dt as ReturningResult, E as defineMigration, En as searchIndex, Er as startsWith, Et as ReturningAll, Fn as ConvexUniqueConstraintConfig, Fr as ColumnBuilderWithTableName, Ft as ExtractTablesWithRelations, Gt as defineRelations, H as EdgeMetadata, In as check, Ir as ColumnDataType, It as ManyConfig, Jt as ConvexDeletionConfig, Kt as defineRelationsPart, Ln as foreignKey, Lr as DrizzleEntity, Lt as OneConfig, M as OrmReader$1, Mn as ConvexForeignKeyConfig, Mr as ColumnBuilderBaseConfig, Mt as unsetToken, N as OrmWriter$1, Nn as ConvexUniqueConstraintBuilder, Nr as ColumnBuilderRuntimeConfig, O as detectMigrationDrift, On as vectorIndex, Or as SystemFields, Ot as ReturningSelection, Pn as ConvexUniqueConstraintBuilderOn, Pr as ColumnBuilderTypeConfig, Pt as ExtractTablesFromSchema, Qn as TableName, Qt as OrmLifecycleChange, Rn as unique, Rr as HasDefault, Rt as RelationsBuilder, S as MigrationStep, Sn as ConvexVectorIndexConfig, Sr as not, St as OrderByClause, T as buildMigrationPlan, Tn as rankIndex, Tr as or, Tt as PredicateWhereIndexConfig, U as extractRelationsConfig, Un as Brand, Ut as TableRelationalConfig, V as RlsMode, Vn as text, Vr as NotNull, Wn as Columns, Wt as TablesRelationalConfig, Xn as OrmSchemaRelations, Xt as ConvexTableWithColumns, Yn as OrmSchemaExtensions, Yt as ConvexTable, Zn as OrmSchemaTriggers, Zt as DiscriminatorBuilderConfig, _ as MigrationMigrateOne, _n as ConvexSearchIndexBuilder, _r as isNull, _t as MutationPaginateConfig, an as RlsPolicyConfig, ar as and, at as CountConfig, b as MigrationSet, bn as ConvexVectorIndexBuilder, br as lte, bt as MutationReturning, cn as RlsRole, cr as endsWith, ct as FilterOperators, d as MigrationDefinition, dn as ConvexAggregateIndexBuilder, dr as gt, dt as InferModelFromColumns, en as TableConfig, er as ExpressionVisitor, et as AggregateConfig, f as MigrationDirection, fn as ConvexAggregateIndexBuilderOn, fr as gte, ft as InferSelectModel, g as MigrationManifestEntry, gn as ConvexRankIndexBuilderOn, gr as isNotNull, gt as MutationExecutionMode, h as MigrationDriftIssue, hn as ConvexRankIndexBuilder, hr as isFieldReference, ht as MutationExecuteResult, i as OrmMigrationCapability, in as RlsPolicy, ir as UnaryExpression, it as BuildRelationResult, j as DatabaseWithQuery, jn as ConvexForeignKeyBuilder, jr as ColumnBuilder, jt as VectorSearchProvider, kn as ConvexCheckBuilder, kt as UpdateSet, ln as RlsRoleConfig, lr as eq, lt as GetColumnData, m as MigrationDocContext, mn as ConvexIndexBuilderOn, mr as inArray, mt as MutationExecuteConfig, n as OrmCapabilities, nn as deletion, nr as FilterExpression, nt as AggregateResult, on as RlsPolicyToOption, or as between, ot as CountResult, p as MigrationDoc, pn as ConvexIndexBuilder, pr as ilike, pt as InsertValue, qn as OrmSchemaExtensionTables, qt as ConvexDeletionBuilder, r as OrmCapability, rn as discriminator, rr as LogicalExpression, rt as BuildQueryResult, sn as rlsPolicy, sr as contains, st as DBQueryConfig, t as OrmAggregateCapability, tn as convexTable, tr as FieldReference, tt as AggregateFieldValue, u as MigrationAppliedState, un as rlsRole, ur as fieldRef, ut as InferInsertModel, v as MigrationPlan, vn as ConvexSearchIndexBuilderOn, vr as like, vt as MutationPaginatedResult, w as MigrationWriteMode, wn as index, wr as notInArray, wt as PaginatedResult, x as MigrationStateMap, xn as ConvexVectorIndexBuilderOn, xr as ne, xt as MutationRunMode, y as MigrationRunStatus, yn as ConvexSearchIndexConfig, yr as lt, yt as MutationResult, zn as ConvexTextBuilder, zr as IsPrimaryKey, zt as RelationsBuilderColumnBase } from "../capabilities-
|
|
2
|
-
import { $ as OrmClientWithApi$1, A as ConvexDateMode, B as ConvexBytesBuilderInitial, C as ConvexNumberBuilderInitial, D as id, E as ConvexIdBuilderInitial, F as custom, G as ConvexBigIntBuilder, H as ConvexBooleanBuilder, I as json, J as CreateOrmOptions, K as ConvexBigIntBuilderInitial, L as objectOf, M as ConvexCustomBuilder, N as ConvexCustomBuilderInitial, O as ConvexDateBuilder, P as arrayOf, Q as OrmClientBase$1, R as unionOf, S as ConvexNumberBuilder, St as defineTriggers, T as ConvexIdBuilder, U as ConvexBooleanBuilderInitial, V as bytes, W as boolean, X as GenericOrmCtx$1, Y as GenericOrm$1, Z as OrmApiResult, _ as ConvexTimestampMode, _t as OrmBeforeResult, a as requireSchemaRelations, at as ScheduledMutationBatchArgs, b as ConvexTextEnumBuilderInitial, bt as OrmTriggerContext, c as TableConfigResult, ct as scheduledDeleteFactory, d as OrmNotFoundError, et as OrmFunctions, f as ConvexVectorBuilder, g as ConvexTimestampBuilderInitial, gt as defineSchemaExtension, h as ConvexTimestampBuilder, ht as SchemaExtension, i as getSchemaTriggers, it as createOrm, j as date, k as ConvexDateBuilderInitial, l as getTableColumns, m as vector, n as defineSchema, nt as OrmWriterCtx, o as asc, ot as scheduledMutationBatchFactory, p as ConvexVectorBuilderInitial, q as bigint, r as getSchemaRelations, rt as ResolveOrmSchema, s as desc, st as ScheduledDeleteArgs, t as WhereClauseResult, tt as OrmReaderCtx, u as getTableConfig, v as timestamp, vt as OrmTableTriggers, w as integer, x as textEnum, xt as OrmTriggers, y as ConvexTextEnumBuilder, yt as OrmTriggerChange, z as ConvexBytesBuilder } from "../where-clause-compiler-
|
|
1
|
+
import { $n as BinaryExpression, $t as OrmLifecycleOperation, A as DatabaseWithMutations, An as ConvexCheckConfig, Ar as AnyColumn, At as VectorQueryConfig, B as RlsContext, Bn as ConvexTextBuilderInitial, Br as IsUnique, Bt as RelationsBuilderColumnConfig, C as MigrationTableName, Cn as aggregateIndex, Cr as notBetween, Ct as OrderDirection, D as defineMigrationSet, Dn as uniqueIndex, Dt as ReturningResult, E as defineMigration, En as searchIndex, Er as startsWith, Et as ReturningAll, Fn as ConvexUniqueConstraintConfig, Fr as ColumnBuilderWithTableName, Ft as ExtractTablesWithRelations, Gt as defineRelations, H as EdgeMetadata, In as check, Ir as ColumnDataType, It as ManyConfig, Jt as ConvexDeletionConfig, Kt as defineRelationsPart, Ln as foreignKey, Lr as DrizzleEntity, Lt as OneConfig, M as OrmReader$1, Mn as ConvexForeignKeyConfig, Mr as ColumnBuilderBaseConfig, Mt as unsetToken, N as OrmWriter$1, Nn as ConvexUniqueConstraintBuilder, Nr as ColumnBuilderRuntimeConfig, O as detectMigrationDrift, On as vectorIndex, Or as SystemFields, Ot as ReturningSelection, Pn as ConvexUniqueConstraintBuilderOn, Pr as ColumnBuilderTypeConfig, Pt as ExtractTablesFromSchema, Qn as TableName, Qt as OrmLifecycleChange, Rn as unique, Rr as HasDefault, Rt as RelationsBuilder, S as MigrationStep, Sn as ConvexVectorIndexConfig, Sr as not, St as OrderByClause, T as buildMigrationPlan, Tn as rankIndex, Tr as or, Tt as PredicateWhereIndexConfig, U as extractRelationsConfig, Un as Brand, Ut as TableRelationalConfig, V as RlsMode, Vn as text, Vr as NotNull, Wn as Columns, Wt as TablesRelationalConfig, Xn as OrmSchemaRelations, Xt as ConvexTableWithColumns, Yn as OrmSchemaExtensions, Yt as ConvexTable, Zn as OrmSchemaTriggers, Zt as DiscriminatorBuilderConfig, _ as MigrationMigrateOne, _n as ConvexSearchIndexBuilder, _r as isNull, _t as MutationPaginateConfig, an as RlsPolicyConfig, ar as and, at as CountConfig, b as MigrationSet, bn as ConvexVectorIndexBuilder, br as lte, bt as MutationReturning, cn as RlsRole, cr as endsWith, ct as FilterOperators, d as MigrationDefinition, dn as ConvexAggregateIndexBuilder, dr as gt, dt as InferModelFromColumns, en as TableConfig, er as ExpressionVisitor, et as AggregateConfig, f as MigrationDirection, fn as ConvexAggregateIndexBuilderOn, fr as gte, ft as InferSelectModel, g as MigrationManifestEntry, gn as ConvexRankIndexBuilderOn, gr as isNotNull, gt as MutationExecutionMode, h as MigrationDriftIssue, hn as ConvexRankIndexBuilder, hr as isFieldReference, ht as MutationExecuteResult, i as OrmMigrationCapability, in as RlsPolicy, ir as UnaryExpression, it as BuildRelationResult, j as DatabaseWithQuery, jn as ConvexForeignKeyBuilder, jr as ColumnBuilder, jt as VectorSearchProvider, kn as ConvexCheckBuilder, kt as UpdateSet, ln as RlsRoleConfig, lr as eq, lt as GetColumnData, m as MigrationDocContext, mn as ConvexIndexBuilderOn, mr as inArray, mt as MutationExecuteConfig, n as OrmCapabilities, nn as deletion, nr as FilterExpression, nt as AggregateResult, on as RlsPolicyToOption, or as between, ot as CountResult, p as MigrationDoc, pn as ConvexIndexBuilder, pr as ilike, pt as InsertValue, qn as OrmSchemaExtensionTables, qt as ConvexDeletionBuilder, r as OrmCapability, rn as discriminator, rr as LogicalExpression, rt as BuildQueryResult, sn as rlsPolicy, sr as contains, st as DBQueryConfig, t as OrmAggregateCapability, tn as convexTable, tr as FieldReference, tt as AggregateFieldValue, u as MigrationAppliedState, un as rlsRole, ur as fieldRef, ut as InferInsertModel, v as MigrationPlan, vn as ConvexSearchIndexBuilderOn, vr as like, vt as MutationPaginatedResult, w as MigrationWriteMode, wn as index, wr as notInArray, wt as PaginatedResult, x as MigrationStateMap, xn as ConvexVectorIndexBuilderOn, xr as ne, xt as MutationRunMode, y as MigrationRunStatus, yn as ConvexSearchIndexConfig, yr as lt, yt as MutationResult, zn as ConvexTextBuilder, zr as IsPrimaryKey, zt as RelationsBuilderColumnBase } from "../capabilities-DtDfpdcH.js";
|
|
2
|
+
import { $ as OrmClientWithApi$1, A as ConvexDateMode, B as ConvexBytesBuilderInitial, C as ConvexNumberBuilderInitial, D as id, E as ConvexIdBuilderInitial, F as custom, G as ConvexBigIntBuilder, H as ConvexBooleanBuilder, I as json, J as CreateOrmOptions, K as ConvexBigIntBuilderInitial, L as objectOf, M as ConvexCustomBuilder, N as ConvexCustomBuilderInitial, O as ConvexDateBuilder, P as arrayOf, Q as OrmClientBase$1, R as unionOf, S as ConvexNumberBuilder, St as defineTriggers, T as ConvexIdBuilder, U as ConvexBooleanBuilderInitial, V as bytes, W as boolean, X as GenericOrmCtx$1, Y as GenericOrm$1, Z as OrmApiResult, _ as ConvexTimestampMode, _t as OrmBeforeResult, a as requireSchemaRelations, at as ScheduledMutationBatchArgs, b as ConvexTextEnumBuilderInitial, bt as OrmTriggerContext, c as TableConfigResult, ct as scheduledDeleteFactory, d as OrmNotFoundError, et as OrmFunctions, f as ConvexVectorBuilder, g as ConvexTimestampBuilderInitial, gt as defineSchemaExtension, h as ConvexTimestampBuilder, ht as SchemaExtension, i as getSchemaTriggers, it as createOrm, j as date, k as ConvexDateBuilderInitial, l as getTableColumns, m as vector, n as defineSchema, nt as OrmWriterCtx, o as asc, ot as scheduledMutationBatchFactory, p as ConvexVectorBuilderInitial, q as bigint, r as getSchemaRelations, rt as ResolveOrmSchema, s as desc, st as ScheduledDeleteArgs, t as WhereClauseResult, tt as OrmReaderCtx, u as getTableConfig, v as timestamp, vt as OrmTableTriggers, w as integer, x as textEnum, xt as OrmTriggers, y as ConvexTextEnumBuilder, yt as OrmTriggerChange, z as ConvexBytesBuilder } from "../where-clause-compiler-CCMtAIdx.js";
|
|
3
3
|
import { i as pretendRequired, n as deprecated, r as pretend } from "../validators-wOIjhkfN.js";
|
|
4
4
|
import { a as QueryCtxWithPreferredOrmQueryTable, i as QueryCtxWithOrmQueryTable, n as LookupByIdResultByCtx, o as getByIdWithOrmQueryFallback, r as QueryCtxWithOptionalOrmQueryTable, t as DocByCtx } from "../query-context-DJONf8X5.js";
|
|
5
5
|
import { DefineSchemaOptions, GenericDatabaseReader, GenericDatabaseWriter, GenericSchema, SchemaDefinition } from "convex/server";
|
package/dist/orm/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { a as pretendRequired, i as pretend, n as deprecated } from "../validato
|
|
|
4
4
|
import { t as id } from "../id-CuSfWa5q.js";
|
|
5
5
|
import { A as or, C as matchLikePattern, D as notIlike, E as notBetween, O as notInArray, S as lte, T as not, _ as isFieldReference, a as between, b as like, c as endsWith, d as filterValueInList, f as filterValuesEqual, g as inArray, h as ilike, i as arrayOverlaps, j as startsWith, k as notLike, l as eq, m as gte, n as arrayContained, o as column, p as gt, r as arrayContains, s as contains, t as and, u as fieldRef, v as isNotNull, w as ne, x as lt, y as isNull } from "../filter-expression-Dydt8wS0.js";
|
|
6
6
|
import { a as indexKeyWithinBounds, c as streamIndexRange, i as getIndexFields, l as isUnsetToken, n as EmptyStream, o as mergedStream, r as QueryStream, s as stream, t as getByIdWithOrmQueryFallback, u as unsetToken } from "../query-context-DOm5Xm3H.js";
|
|
7
|
-
import { $ as serializeFilterExpression, A as ensureNonNullValues, B as getMutationExecutionMode, C as deserializeFilterExpression, D as enforcePolymorphicWrite, E as enforceForeignKeys, F as getChecks, G as getUniqueIndexes, H as getTableColumns$2, I as getColumnName$1, J as normalizeDateFieldsForWrite, K as hardDeleteRow, L as getForeignKeys, M as evaluateCheckConstraintTriState, N as evaluateFilter, O as enforceUniqueIndexes, P as extractPrimaryIdLookup, Q as selectReturningRowWithHydration, R as getMutationAsyncDelayMs, S as decodeUndefinedDeep, T as enforceCheckConstraints, U as getTableDeleteConfig, V as getOrmContext, W as getTableName, X as patchReferencingRows, Y as normalizeTemporalComparableValue, Z as resolveOrmRuntimeDefaults, _ as applyIncomingForeignKeyActionsOnUpdate, _t as
|
|
7
|
+
import { $ as serializeFilterExpression, A as ensureNonNullValues, B as getMutationExecutionMode, C as deserializeFilterExpression, D as enforcePolymorphicWrite, E as enforceForeignKeys, F as getChecks, G as getUniqueIndexes, H as getTableColumns$2, I as getColumnName$1, J as normalizeDateFieldsForWrite, K as hardDeleteRow, L as getForeignKeys, M as evaluateCheckConstraintTriState, N as evaluateFilter, O as enforceUniqueIndexes, P as extractPrimaryIdLookup, Q as selectReturningRowWithHydration, R as getMutationAsyncDelayMs, S as decodeUndefinedDeep, T as enforceCheckConstraints, U as getTableDeleteConfig, V as getOrmContext, W as getTableName, X as patchReferencingRows, Y as normalizeTemporalComparableValue, Z as resolveOrmRuntimeDefaults, _ as applyIncomingForeignKeyActionsOnUpdate, _t as resolveIndexOrderPushdown, a as aggregateExtension, at as markLifecycleHookedTables, b as collectMutationRowsBounded, bt as PUBLIC_CREATED_AT_FIELD, c as AGGREGATE_ERROR, ct as isConvexEnforceableFilter, d as createCountError, dt as findRelationIndex, et as softDeleteRow, ft as findSearchIndexByName, g as applyIncomingForeignKeyActionsOnDelete, gt as getRankIndexes, h as applyDefaults, ht as getIndexes, it as hasLifecycleHooks, j as ensureNullableColumns, k as ensureDefaultColumns, l as COUNT_ERROR, lt as mapWithConcurrency, m as ensureCountAllowedForRls, mt as getAggregateIndexes, nt as takeRowsWithinByteBudget, o as getAggregateIndexDefinitions, ot as compileConvexFilter, p as ensureAggregateAllowedForRls, pt as findVectorIndexByName, q as hydrateDateFieldsForRead, rt as toConvexFilter, s as getRankIndexDefinitions, st as convexAnd, tt as splitReturningSelection, u as createAggregateError, ut as findIndexForColumns, v as buildForeignKeyGraph, vt as CREATED_AT_MIGRATION_MESSAGE, w as encodeUndefinedDeep, x as collectPrimaryIdLookupRows, xt as usesSystemCreatedAtAlias, y as canUsePrimaryIdLookupCursor, yt as INTERNAL_CREATION_TIME_FIELD, z as getMutationCollectionLimits } from "../schema-e0wbZ_Ax.js";
|
|
8
8
|
import { t as defineSchemaExtension } from "../extensions-Blzsyekm.js";
|
|
9
9
|
import { compareValues, v } from "convex/values";
|
|
10
10
|
import { defineSchema as defineSchema$1, internalActionGeneric, internalMutationGeneric } from "convex/server";
|
|
@@ -1270,24 +1270,6 @@ var WhereClauseCompiler = class {
|
|
|
1270
1270
|
|
|
1271
1271
|
//#endregion
|
|
1272
1272
|
//#region src/orm/query.ts
|
|
1273
|
-
/**
|
|
1274
|
-
* Operators that Convex's `.filter()` cannot express, so `_toConvexExpression`
|
|
1275
|
-
* compiles them to a `() => true` placeholder and `_evaluatePostFetchFilter`
|
|
1276
|
-
* applies the real predicate in JavaScript after the rows are read.
|
|
1277
|
-
* Keep in sync with the string/array cases in `_toConvexExpression`.
|
|
1278
|
-
*/
|
|
1279
|
-
const POST_FETCH_ONLY_OPERATORS = new Set([
|
|
1280
|
-
"like",
|
|
1281
|
-
"ilike",
|
|
1282
|
-
"notLike",
|
|
1283
|
-
"notIlike",
|
|
1284
|
-
"startsWith",
|
|
1285
|
-
"endsWith",
|
|
1286
|
-
"contains",
|
|
1287
|
-
"arrayContains",
|
|
1288
|
-
"arrayContained",
|
|
1289
|
-
"arrayOverlaps"
|
|
1290
|
-
]);
|
|
1291
1273
|
const DEFAULT_RELATION_FAN_OUT_MAX_KEYS = 1e3;
|
|
1292
1274
|
/**
|
|
1293
1275
|
* How many child rows the bounded relation stream filters at a time. Batching
|
|
@@ -1743,14 +1725,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
1743
1725
|
* expression before relying on it.
|
|
1744
1726
|
*/
|
|
1745
1727
|
_isConvexEnforceableFilter(filter) {
|
|
1746
|
-
|
|
1747
|
-
if (filter.type === "unary") {
|
|
1748
|
-
const [operand] = filter.operands;
|
|
1749
|
-
if (isFieldReference(operand)) return true;
|
|
1750
|
-
return this._isConvexEnforceableFilter(operand);
|
|
1751
|
-
}
|
|
1752
|
-
if (filter.type === "logical") return filter.operands.every((operand) => this._isConvexEnforceableFilter(operand));
|
|
1753
|
-
return true;
|
|
1728
|
+
return isConvexEnforceableFilter(filter);
|
|
1754
1729
|
}
|
|
1755
1730
|
/**
|
|
1756
1731
|
* Evaluate a filter expression against a fetched row
|
|
@@ -3218,7 +3193,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
3218
3193
|
if (Object.hasOwn(filter, "isNull")) {
|
|
3219
3194
|
hasRecognized = true;
|
|
3220
3195
|
if (filter.isNull !== true) throw createAggregateError(AGGREGATE_ERROR.FILTER_UNSUPPORTED, `groupBy() field '${fieldName}'.isNull only supports true.`);
|
|
3221
|
-
this._pushGroupByConstraint(constraints, fieldName, [null]);
|
|
3196
|
+
this._pushGroupByConstraint(constraints, fieldName, [null, void 0]);
|
|
3222
3197
|
}
|
|
3223
3198
|
if (Object.hasOwn(filter, "gt") || Object.hasOwn(filter, "gte") || Object.hasOwn(filter, "lt") || Object.hasOwn(filter, "lte")) throw createAggregateError(AGGREGATE_ERROR.FILTER_UNSUPPORTED, `groupBy() requires finite eq/in/isNull constraints for 'by' field '${fieldName}'. Range operators are unsupported for group keys.`);
|
|
3224
3199
|
const unsupportedKeys = Object.keys(filter).filter((key) => ![
|
|
@@ -3267,24 +3242,60 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
3267
3242
|
}
|
|
3268
3243
|
return output;
|
|
3269
3244
|
}
|
|
3245
|
+
/**
|
|
3246
|
+
* One group per distinct value, where `null` and absent count as the same
|
|
3247
|
+
* value. They occupy different aggregate buckets, so the emitted group key
|
|
3248
|
+
* and the filter that reads it diverge: the key reports `null` while the
|
|
3249
|
+
* filter keeps `isNull` so the aggregate compiler reads both buckets and
|
|
3250
|
+
* combines their metrics into a single row.
|
|
3251
|
+
*/
|
|
3252
|
+
_buildGroupBySlots(values) {
|
|
3253
|
+
const nullishValues = values.filter((value) => value === null || value === void 0);
|
|
3254
|
+
const slots = [];
|
|
3255
|
+
let mergedNullish = false;
|
|
3256
|
+
for (const value of values) {
|
|
3257
|
+
if (value !== null && value !== void 0) {
|
|
3258
|
+
slots.push({
|
|
3259
|
+
key: value,
|
|
3260
|
+
filter: value,
|
|
3261
|
+
probeCount: 1
|
|
3262
|
+
});
|
|
3263
|
+
continue;
|
|
3264
|
+
}
|
|
3265
|
+
if (mergedNullish) continue;
|
|
3266
|
+
mergedNullish = true;
|
|
3267
|
+
slots.push({
|
|
3268
|
+
key: null,
|
|
3269
|
+
filter: nullishValues.length > 1 ? { isNull: true } : value,
|
|
3270
|
+
probeCount: nullishValues.length
|
|
3271
|
+
});
|
|
3272
|
+
}
|
|
3273
|
+
return slots;
|
|
3274
|
+
}
|
|
3270
3275
|
_buildGroupByCandidates(byFields, byFieldValues) {
|
|
3271
3276
|
if (byFields.length === 0) return [];
|
|
3272
3277
|
const output = [];
|
|
3273
|
-
const
|
|
3274
|
-
const
|
|
3278
|
+
const key = {};
|
|
3279
|
+
const where = {};
|
|
3280
|
+
const build = (index, probeCount) => {
|
|
3275
3281
|
if (index >= byFields.length) {
|
|
3276
|
-
output.push({
|
|
3282
|
+
output.push({
|
|
3283
|
+
key: { ...key },
|
|
3284
|
+
probeCount,
|
|
3285
|
+
where: { ...where }
|
|
3286
|
+
});
|
|
3277
3287
|
return;
|
|
3278
3288
|
}
|
|
3279
3289
|
const field = byFields[index];
|
|
3280
|
-
const
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
build(index + 1);
|
|
3290
|
+
for (const slot of this._buildGroupBySlots(byFieldValues[field] ?? [])) {
|
|
3291
|
+
key[field] = slot.key;
|
|
3292
|
+
where[field] = slot.filter;
|
|
3293
|
+
build(index + 1, probeCount * slot.probeCount);
|
|
3284
3294
|
}
|
|
3285
|
-
delete
|
|
3295
|
+
delete key[field];
|
|
3296
|
+
delete where[field];
|
|
3286
3297
|
};
|
|
3287
|
-
build(0);
|
|
3298
|
+
build(0, 1);
|
|
3288
3299
|
return output;
|
|
3289
3300
|
}
|
|
3290
3301
|
_coerceGroupByByFields(by) {
|
|
@@ -3631,9 +3642,11 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
3631
3642
|
const orderSpecs = this._coerceGroupByOrderSpecs(config.orderBy, by, aggregate);
|
|
3632
3643
|
const window = this._coerceGroupByWindowConfig(config, orderSpecs);
|
|
3633
3644
|
const maxKeys = this._getAggregateCartesianMaxKeys();
|
|
3634
|
-
|
|
3645
|
+
let candidateProbeCount = 0;
|
|
3646
|
+
for (const candidate of candidates) candidateProbeCount += candidate.probeCount;
|
|
3647
|
+
if (candidateProbeCount > maxKeys) throw createAggregateError(AGGREGATE_ERROR.ARGS_UNSUPPORTED, `groupBy() expands to ${candidateProbeCount} aggregate key probes, exceeding aggregateCartesianMaxKeys (${maxKeys}). Reduce IN/isNull fan-out or increase defineSchema(..., { defaults: { aggregateCartesianMaxKeys } }).`);
|
|
3635
3648
|
const metricReads = (aggregate.count === true ? 1 : aggregate.count ? (aggregate.count.all ? 1 : 0) + aggregate.count.fields.length : 0) + aggregate.sumFields.length + aggregate.avgFields.length + aggregate.minFields.length + aggregate.maxFields.length;
|
|
3636
|
-
const estimatedWork =
|
|
3649
|
+
const estimatedWork = candidateProbeCount * Math.max(1, metricReads);
|
|
3637
3650
|
const workBudget = this._getAggregateWorkBudget();
|
|
3638
3651
|
if (estimatedWork > workBudget) throw createAggregateError(AGGREGATE_ERROR.ARGS_UNSUPPORTED, `groupBy() estimated work is ${estimatedWork} units, exceeding aggregateWorkBudget (${workBudget}). Reduce group fan-out or increase defineSchema(..., { defaults: { aggregateWorkBudget } }).`);
|
|
3639
3652
|
return {
|
|
@@ -3667,13 +3680,13 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
3667
3680
|
const metricConfig = this._buildAggregateMetricConfig(normalized.aggregate);
|
|
3668
3681
|
const byOutputKeys = new Set(normalized.by.map((entry) => entry.raw));
|
|
3669
3682
|
let rows = await this._mapWithConcurrency(normalized.candidates, async (candidate) => {
|
|
3670
|
-
const groupWhere = this._isEmptyWhere(normalized.aggregate.where) ? candidate : { AND: [normalized.aggregate.where, candidate] };
|
|
3683
|
+
const groupWhere = this._isEmptyWhere(normalized.aggregate.where) ? candidate.where : { AND: [normalized.aggregate.where, candidate.where] };
|
|
3671
3684
|
const aggregateRow = await this._executeAggregate({
|
|
3672
3685
|
...metricConfig,
|
|
3673
3686
|
where: groupWhere
|
|
3674
3687
|
});
|
|
3675
3688
|
return {
|
|
3676
|
-
...Object.fromEntries(normalized.by.map((entry) => [entry.raw, this._coerceAggregateReturnValue(entry.field, candidate[entry.field])])),
|
|
3689
|
+
...Object.fromEntries(normalized.by.map((entry) => [entry.raw, this._coerceAggregateReturnValue(entry.field, candidate.key[entry.field])])),
|
|
3677
3690
|
...aggregateRow
|
|
3678
3691
|
};
|
|
3679
3692
|
});
|
|
@@ -4060,14 +4073,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
4060
4073
|
return indexQuery;
|
|
4061
4074
|
});
|
|
4062
4075
|
if (probeBound !== void 0 && probeOrderDirection) probeQuery = probeQuery.order(probeOrderDirection);
|
|
4063
|
-
if (convexProbeFilters.length > 0) probeQuery = probeQuery.filter((q) =>
|
|
4064
|
-
let result = null;
|
|
4065
|
-
for (const filter of convexProbeFilters) {
|
|
4066
|
-
const expr = this._toConvexExpression(filter)(q);
|
|
4067
|
-
result = result ? q.and(result, expr) : expr;
|
|
4068
|
-
}
|
|
4069
|
-
return result ?? q;
|
|
4070
|
-
});
|
|
4076
|
+
if (convexProbeFilters.length > 0) probeQuery = probeQuery.filter((q) => convexAnd(q, convexProbeFilters.map((filter) => this._toConvexExpression(filter)(q))));
|
|
4071
4077
|
return probeBound === void 0 ? await probeQuery.collect() : await probeQuery.take(probeBound);
|
|
4072
4078
|
}));
|
|
4073
4079
|
let rows = Array.from(new Map(probeRows.flat().map((row) => [String(row._id), row])).values());
|
|
@@ -4182,14 +4188,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
4182
4188
|
splitCursor: paginationResult.splitCursor
|
|
4183
4189
|
};
|
|
4184
4190
|
}
|
|
4185
|
-
if (convexPostFilters.length > 0) query = query.filter((q) =>
|
|
4186
|
-
let result = null;
|
|
4187
|
-
for (const filter of convexPostFilters) {
|
|
4188
|
-
const expr = this._toConvexExpression(filter)(q);
|
|
4189
|
-
result = result ? q.and(result, expr) : expr;
|
|
4190
|
-
}
|
|
4191
|
-
return result ?? q;
|
|
4192
|
-
});
|
|
4191
|
+
if (convexPostFilters.length > 0) query = query.filter((q) => convexAnd(q, convexPostFilters.map((filter) => this._toConvexExpression(filter)(q))));
|
|
4193
4192
|
if (queryConfig.order && primaryOrder) {
|
|
4194
4193
|
if (needsPostFetchSortForPrimary) {
|
|
4195
4194
|
if (strict) throw new Error(`Pagination: Field '${primaryOrder.field}' has no index. Add an index or disable strict.`);
|
|
@@ -4214,14 +4213,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
4214
4213
|
const convexPostFilters = queryConfig.postFilters.filter((filter) => this._isConvexEnforceableFilter(filter));
|
|
4215
4214
|
const hasResidualPostFilter = convexPostFilters.length !== queryConfig.postFilters.length;
|
|
4216
4215
|
const hasPostFetchMembership = this._hasSearchDisallowedRelationFilter(whereFilter, this.tableConfig) || this.rls?.mode !== "skip" && isRlsEnabled(this.tableConfig.table);
|
|
4217
|
-
if (convexPostFilters.length > 0) query = query.filter((q) =>
|
|
4218
|
-
let result = null;
|
|
4219
|
-
for (const filter of convexPostFilters) {
|
|
4220
|
-
const expr = this._toConvexExpression(filter)(q);
|
|
4221
|
-
result = result ? q.and(result, expr) : expr;
|
|
4222
|
-
}
|
|
4223
|
-
return result ?? q;
|
|
4224
|
-
});
|
|
4216
|
+
if (convexPostFilters.length > 0) query = query.filter((q) => convexAnd(q, convexPostFilters.map((filter) => this._toConvexExpression(filter)(q))));
|
|
4225
4217
|
const offset = config.offset ?? 0;
|
|
4226
4218
|
if (typeof offset !== "number") throw new Error("Only numeric offset is supported in kitcn ORM.");
|
|
4227
4219
|
const limit = this._resolveNonPaginatedLimit(config);
|
|
@@ -4337,9 +4329,7 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
4337
4329
|
return builder;
|
|
4338
4330
|
}
|
|
4339
4331
|
_buildFilterPredicate(q, fields, values) {
|
|
4340
|
-
|
|
4341
|
-
for (let i = 1; i < fields.length; i += 1) expression = q.and(expression, q.eq(q.field(fields[i]), values[i]));
|
|
4342
|
-
return expression;
|
|
4332
|
+
return convexAnd(q, fields.map((field, index) => q.eq(q.field(field), values[index])));
|
|
4343
4333
|
}
|
|
4344
4334
|
_queryByFields(query, fields, values, indexName) {
|
|
4345
4335
|
if (indexName) return query.withIndex(indexName, (q) => this._buildIndexPredicate(q, fields, values));
|
|
@@ -4383,79 +4373,10 @@ var GelRelationalQuery = class GelRelationalQuery extends QueryPromise {
|
|
|
4383
4373
|
* Uses visitor pattern to traverse expression tree
|
|
4384
4374
|
*/
|
|
4385
4375
|
_toConvexExpression(expression) {
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
const fieldName = field.fieldName;
|
|
4391
|
-
const normalizedValue = this._normalizeComparableValue(fieldName, value);
|
|
4392
|
-
switch (expr.operator) {
|
|
4393
|
-
case "eq": return (q) => q.eq(q.field(fieldName), normalizedValue);
|
|
4394
|
-
case "ne": return (q) => q.neq(q.field(fieldName), normalizedValue);
|
|
4395
|
-
case "gt": return (q) => q.gt(q.field(fieldName), normalizedValue);
|
|
4396
|
-
case "gte": return (q) => q.gte(q.field(fieldName), normalizedValue);
|
|
4397
|
-
case "lt": return (q) => q.lt(q.field(fieldName), normalizedValue);
|
|
4398
|
-
case "lte": return (q) => q.lte(q.field(fieldName), normalizedValue);
|
|
4399
|
-
case "inArray": {
|
|
4400
|
-
const values = normalizedValue;
|
|
4401
|
-
return (q) => {
|
|
4402
|
-
if (values.length === 0) return q.eq(q.field("_id"), "__better_convex_never__");
|
|
4403
|
-
return values.map((v) => q.eq(q.field(fieldName), v)).reduce((acc, cond) => q.or(acc, cond));
|
|
4404
|
-
};
|
|
4405
|
-
}
|
|
4406
|
-
case "notInArray": {
|
|
4407
|
-
const values = normalizedValue;
|
|
4408
|
-
return (q) => {
|
|
4409
|
-
return values.map((v) => q.neq(q.field(fieldName), v)).reduce((acc, cond) => q.and(acc, cond));
|
|
4410
|
-
};
|
|
4411
|
-
}
|
|
4412
|
-
case "like":
|
|
4413
|
-
case "ilike":
|
|
4414
|
-
case "notLike":
|
|
4415
|
-
case "notIlike":
|
|
4416
|
-
case "startsWith":
|
|
4417
|
-
case "endsWith":
|
|
4418
|
-
case "contains":
|
|
4419
|
-
case "arrayContains":
|
|
4420
|
-
case "arrayContained":
|
|
4421
|
-
case "arrayOverlaps": return () => true;
|
|
4422
|
-
default: throw new Error(`Unsupported binary operator: ${expr.operator}`);
|
|
4423
|
-
}
|
|
4424
|
-
},
|
|
4425
|
-
visitLogical: (expr) => {
|
|
4426
|
-
const operandFns = expr.operands.map((op) => op.accept(visitor));
|
|
4427
|
-
if (expr.operator === "and") return (q) => {
|
|
4428
|
-
let result = operandFns[0](q);
|
|
4429
|
-
for (let i = 1; i < operandFns.length; i++) result = q.and(result, operandFns[i](q));
|
|
4430
|
-
return result;
|
|
4431
|
-
};
|
|
4432
|
-
if (expr.operator === "or") return (q) => {
|
|
4433
|
-
let result = operandFns[0](q);
|
|
4434
|
-
for (let i = 1; i < operandFns.length; i++) result = q.or(result, operandFns[i](q));
|
|
4435
|
-
return result;
|
|
4436
|
-
};
|
|
4437
|
-
throw new Error(`Unsupported logical operator: ${expr.operator}`);
|
|
4438
|
-
},
|
|
4439
|
-
visitUnary: (expr) => {
|
|
4440
|
-
const operand = expr.operands[0];
|
|
4441
|
-
if (expr.operator === "not") {
|
|
4442
|
-
const operandFn = operand.accept(visitor);
|
|
4443
|
-
return (q) => q.not(operandFn(q));
|
|
4444
|
-
}
|
|
4445
|
-
if (expr.operator === "isNull") {
|
|
4446
|
-
if (!isFieldReference(operand)) throw new Error("isNull must operate on a field reference");
|
|
4447
|
-
const fieldName = operand.fieldName;
|
|
4448
|
-
return (q) => q.or(q.eq(q.field(fieldName), null), q.eq(q.field(fieldName), void 0));
|
|
4449
|
-
}
|
|
4450
|
-
if (expr.operator === "isNotNull") {
|
|
4451
|
-
if (!isFieldReference(operand)) throw new Error("isNotNull must operate on a field reference");
|
|
4452
|
-
const fieldName = operand.fieldName;
|
|
4453
|
-
return (q) => q.and(q.neq(q.field(fieldName), null), q.neq(q.field(fieldName), void 0));
|
|
4454
|
-
}
|
|
4455
|
-
throw new Error(`Unsupported unary operator: ${expr.operator}`);
|
|
4456
|
-
}
|
|
4457
|
-
};
|
|
4458
|
-
return expression.accept(visitor);
|
|
4376
|
+
return compileConvexFilter(expression, {
|
|
4377
|
+
normalizeValue: (fieldName, value) => this._normalizeComparableValue(fieldName, value),
|
|
4378
|
+
nullMatchesUndefined: true
|
|
4379
|
+
});
|
|
4459
4380
|
}
|
|
4460
4381
|
/**
|
|
4461
4382
|
* Get edge metadata for a target table
|
|
@@ -5717,14 +5638,7 @@ var ConvexInsertBuilder = class extends QueryPromise {
|
|
|
5717
5638
|
else {
|
|
5718
5639
|
if (!allowFullScan) throw new Error("onConflict requires allowFullScan: true when no index is available.");
|
|
5719
5640
|
if (strict) console.warn("onConflict running without index (allowFullScan: true).");
|
|
5720
|
-
query = query.filter((q) =>
|
|
5721
|
-
let expr = q.eq(q.field(filterValuePairs[0][0]), filterValuePairs[0][1]);
|
|
5722
|
-
for (let i = 1; i < filterValuePairs.length; i++) {
|
|
5723
|
-
const [field, fieldValue] = filterValuePairs[i];
|
|
5724
|
-
expr = q.and(expr, q.eq(q.field(field), fieldValue));
|
|
5725
|
-
}
|
|
5726
|
-
return expr;
|
|
5727
|
-
});
|
|
5641
|
+
query = query.filter((q) => convexAnd(q, filterValuePairs.map(([field, fieldValue]) => q.eq(q.field(field), fieldValue))));
|
|
5728
5642
|
}
|
|
5729
5643
|
const row = await query.first();
|
|
5730
5644
|
return row ? row : null;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { C as MigrationTableName, D as defineMigrationSet, E as defineMigration, O as detectMigrationDrift, S as MigrationStep, T as buildMigrationPlan, _ as MigrationMigrateOne, a as MigrationCancelArgs, b as MigrationSet, c as MigrationStatusArgs, d as MigrationDefinition, f as MigrationDirection, g as MigrationManifestEntry, h as MigrationDriftIssue, l as createMigrationHandlers, m as MigrationDocContext, o as MigrationRunArgs, p as MigrationDoc, s as MigrationRunChunkArgs, u as MigrationAppliedState, v as MigrationPlan, w as MigrationWriteMode, x as MigrationStateMap, y as MigrationRunStatus } from "../../capabilities-
|
|
2
|
-
import { Ct as migrationCapability, dt as MIGRATION_STORAGE_TABLE_NAMES, ft as injectMigrationStorageTables, lt as MIGRATION_RUN_TABLE, mt as migrationStorageTables, pt as migrationExtension, ut as MIGRATION_STATE_TABLE } from "../../where-clause-compiler-
|
|
1
|
+
import { C as MigrationTableName, D as defineMigrationSet, E as defineMigration, O as detectMigrationDrift, S as MigrationStep, T as buildMigrationPlan, _ as MigrationMigrateOne, a as MigrationCancelArgs, b as MigrationSet, c as MigrationStatusArgs, d as MigrationDefinition, f as MigrationDirection, g as MigrationManifestEntry, h as MigrationDriftIssue, l as createMigrationHandlers, m as MigrationDocContext, o as MigrationRunArgs, p as MigrationDoc, s as MigrationRunChunkArgs, u as MigrationAppliedState, v as MigrationPlan, w as MigrationWriteMode, x as MigrationStateMap, y as MigrationRunStatus } from "../../capabilities-DtDfpdcH.js";
|
|
2
|
+
import { Ct as migrationCapability, dt as MIGRATION_STORAGE_TABLE_NAMES, ft as injectMigrationStorageTables, lt as MIGRATION_RUN_TABLE, mt as migrationStorageTables, pt as migrationExtension, ut as MIGRATION_STATE_TABLE } from "../../where-clause-compiler-CCMtAIdx.js";
|
|
3
3
|
export { MIGRATION_RUN_TABLE, MIGRATION_STATE_TABLE, MIGRATION_STORAGE_TABLE_NAMES, type MigrationAppliedState, type MigrationCancelArgs, type MigrationDefinition, type MigrationDirection, type MigrationDoc, type MigrationDocContext, type MigrationDriftIssue, type MigrationManifestEntry, type MigrationMigrateOne, type MigrationPlan, type MigrationRunArgs, type MigrationRunChunkArgs, type MigrationRunStatus, type MigrationSet, type MigrationStateMap, type MigrationStatusArgs, type MigrationStep, type MigrationTableName, type MigrationWriteMode, buildMigrationPlan, createMigrationHandlers, defineMigration, defineMigrationSet, detectMigrationDrift, injectMigrationStorageTables, migrationCapability, migrationExtension, migrationStorageTables };
|
|
@@ -125,6 +125,138 @@ async function mapWithConcurrency(items, limit, worker) {
|
|
|
125
125
|
return results;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/orm/convex-filter-compiler.ts
|
|
130
|
+
/**
|
|
131
|
+
* Operators Convex's `.filter()` cannot express, so they compile to a
|
|
132
|
+
* `() => true` placeholder and the real predicate runs in JavaScript after the
|
|
133
|
+
* rows are read. Callers that push a compiled expression into Convex must
|
|
134
|
+
* first check `isConvexEnforceableFilter`: a `true` placeholder makes a
|
|
135
|
+
* downstream `take()` spend its budget on unfiltered rows, and a surrounding
|
|
136
|
+
* `NOT` turns it into `q.not(true)`, which matches nothing.
|
|
137
|
+
*/
|
|
138
|
+
const POST_FETCH_ONLY_OPERATORS = new Set([
|
|
139
|
+
"like",
|
|
140
|
+
"ilike",
|
|
141
|
+
"notLike",
|
|
142
|
+
"notIlike",
|
|
143
|
+
"startsWith",
|
|
144
|
+
"endsWith",
|
|
145
|
+
"contains",
|
|
146
|
+
"arrayContains",
|
|
147
|
+
"arrayContained",
|
|
148
|
+
"arrayOverlaps"
|
|
149
|
+
]);
|
|
150
|
+
/**
|
|
151
|
+
* Compared against `_id`, which is a Convex id and can never equal a plain
|
|
152
|
+
* string, so `eq` against it is unsatisfiable. Convex's expression grammar has
|
|
153
|
+
* no literal boolean, so this is how `in []` says "match nothing".
|
|
154
|
+
*/
|
|
155
|
+
const NEVER_MATCH_SENTINEL = "__better_convex_never__";
|
|
156
|
+
/**
|
|
157
|
+
* Convex's `q.or` / `q.and` are variadic — `or(...exprs)` serializes to a flat
|
|
158
|
+
* `{ $or: [...] }` (see `convex/src/server/impl/filter_builder_impl.ts`).
|
|
159
|
+
* Folding them pairwise instead nests one `$or` per operand, so the serialized
|
|
160
|
+
* filter's JSON depth grows as `2N + 1` and the backend rejects the whole query
|
|
161
|
+
* with `Received invalid json: recursion limit exceeded` once the list passes a
|
|
162
|
+
* few dozen entries. Always combine in one variadic call.
|
|
163
|
+
*/
|
|
164
|
+
function convexOr(q, expressions) {
|
|
165
|
+
return expressions.length === 1 ? expressions[0] : q.or(...expressions);
|
|
166
|
+
}
|
|
167
|
+
/** Flat `$and` counterpart of {@link convexOr}. */
|
|
168
|
+
function convexAnd(q, expressions) {
|
|
169
|
+
return expressions.length === 1 ? expressions[0] : q.and(...expressions);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Whether Convex can carry the whole expression in `.filter()`, or some part of
|
|
173
|
+
* it compiles to a `() => true` placeholder that only JavaScript can enforce.
|
|
174
|
+
*/
|
|
175
|
+
function isConvexEnforceableFilter(filter) {
|
|
176
|
+
if (filter.type === "binary") return !POST_FETCH_ONLY_OPERATORS.has(filter.operator);
|
|
177
|
+
if (filter.type === "unary") {
|
|
178
|
+
const [operand] = filter.operands;
|
|
179
|
+
if (isFieldReference(operand)) return true;
|
|
180
|
+
return isConvexEnforceableFilter(operand);
|
|
181
|
+
}
|
|
182
|
+
if (filter.type === "logical") return filter.operands.every((operand) => isConvexEnforceableFilter(operand));
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Compile a filter expression to a Convex `.filter()` callback.
|
|
187
|
+
*
|
|
188
|
+
* @param expression - Filter expression tree
|
|
189
|
+
* @param options - Per-lane semantics; see {@link ConvexFilterCompilerOptions}
|
|
190
|
+
*/
|
|
191
|
+
function compileConvexFilter(expression, options = {}) {
|
|
192
|
+
const { normalizeValue, nullMatchesUndefined = false } = options;
|
|
193
|
+
const visitor = {
|
|
194
|
+
visitBinary: (expr) => {
|
|
195
|
+
const [field, value] = expr.operands;
|
|
196
|
+
if (!isFieldReference(field)) throw new Error("Binary expression must have FieldReference as first operand");
|
|
197
|
+
const fieldName = field.fieldName;
|
|
198
|
+
const normalizedValue = normalizeValue ? normalizeValue(fieldName, value) : value;
|
|
199
|
+
switch (expr.operator) {
|
|
200
|
+
case "eq": return (q) => q.eq(q.field(fieldName), normalizedValue);
|
|
201
|
+
case "ne": return (q) => q.neq(q.field(fieldName), normalizedValue);
|
|
202
|
+
case "gt": return (q) => q.gt(q.field(fieldName), normalizedValue);
|
|
203
|
+
case "gte": return (q) => q.gte(q.field(fieldName), normalizedValue);
|
|
204
|
+
case "lt": return (q) => q.lt(q.field(fieldName), normalizedValue);
|
|
205
|
+
case "lte": return (q) => q.lte(q.field(fieldName), normalizedValue);
|
|
206
|
+
case "inArray": {
|
|
207
|
+
const values = normalizedValue;
|
|
208
|
+
return (q) => {
|
|
209
|
+
if (values.length === 0) return q.eq(q.field("_id"), NEVER_MATCH_SENTINEL);
|
|
210
|
+
return convexOr(q, values.map((v) => q.eq(q.field(fieldName), v)));
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
case "notInArray": {
|
|
214
|
+
const values = normalizedValue;
|
|
215
|
+
return (q) => convexAnd(q, values.map((v) => q.neq(q.field(fieldName), v)));
|
|
216
|
+
}
|
|
217
|
+
case "like":
|
|
218
|
+
case "ilike":
|
|
219
|
+
case "notLike":
|
|
220
|
+
case "notIlike":
|
|
221
|
+
case "startsWith":
|
|
222
|
+
case "endsWith":
|
|
223
|
+
case "contains":
|
|
224
|
+
case "arrayContains":
|
|
225
|
+
case "arrayContained":
|
|
226
|
+
case "arrayOverlaps": return () => true;
|
|
227
|
+
default: throw new Error(`Unsupported binary operator: ${expr.operator}`);
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
visitLogical: (expr) => {
|
|
231
|
+
const operandFns = expr.operands.map((op) => op.accept(visitor));
|
|
232
|
+
if (expr.operator === "and") return (q) => convexAnd(q, operandFns.map((fn) => fn(q)));
|
|
233
|
+
if (expr.operator === "or") return (q) => convexOr(q, operandFns.map((fn) => fn(q)));
|
|
234
|
+
throw new Error(`Unsupported logical operator: ${expr.operator}`);
|
|
235
|
+
},
|
|
236
|
+
visitUnary: (expr) => {
|
|
237
|
+
const operand = expr.operands[0];
|
|
238
|
+
if (expr.operator === "not") {
|
|
239
|
+
const operandFn = operand.accept(visitor);
|
|
240
|
+
return (q) => q.not(operandFn(q));
|
|
241
|
+
}
|
|
242
|
+
if (expr.operator === "isNull") {
|
|
243
|
+
if (!isFieldReference(operand)) throw new Error("isNull must operate on a field reference");
|
|
244
|
+
const fieldName = operand.fieldName;
|
|
245
|
+
if (!nullMatchesUndefined) return (q) => q.eq(q.field(fieldName), null);
|
|
246
|
+
return (q) => q.or(q.eq(q.field(fieldName), null), q.eq(q.field(fieldName), void 0));
|
|
247
|
+
}
|
|
248
|
+
if (expr.operator === "isNotNull") {
|
|
249
|
+
if (!isFieldReference(operand)) throw new Error("isNotNull must operate on a field reference");
|
|
250
|
+
const fieldName = operand.fieldName;
|
|
251
|
+
if (!nullMatchesUndefined) return (q) => q.neq(q.field(fieldName), null);
|
|
252
|
+
return (q) => q.and(q.neq(q.field(fieldName), null), q.neq(q.field(fieldName), void 0));
|
|
253
|
+
}
|
|
254
|
+
throw new Error(`Unsupported unary operator: ${expr.operator}`);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
return expression.accept(visitor);
|
|
258
|
+
}
|
|
259
|
+
|
|
128
260
|
//#endregion
|
|
129
261
|
//#region src/orm/write-fanout.ts
|
|
130
262
|
/**
|
|
@@ -385,7 +517,9 @@ const deserializeFilterExpression = (expression) => {
|
|
|
385
517
|
}
|
|
386
518
|
if (expression.type === "logical") {
|
|
387
519
|
const logical = expression;
|
|
388
|
-
|
|
520
|
+
const operands = logical.operands.map((operand) => deserializeFilterExpression(operand)).filter((operand) => !!operand);
|
|
521
|
+
if (operands.length === 0) throw new Error("Serialized logical expression requires at least one operand.");
|
|
522
|
+
return createLogicalExpression(logical.operator, operands);
|
|
389
523
|
}
|
|
390
524
|
const unary = expression;
|
|
391
525
|
const operand = unary.operand;
|
|
@@ -754,9 +888,7 @@ function buildIndexPredicate(q, columns, values) {
|
|
|
754
888
|
return builder;
|
|
755
889
|
}
|
|
756
890
|
function buildFilterPredicate(q, columns, values) {
|
|
757
|
-
|
|
758
|
-
for (let i = 1; i < columns.length; i++) expr = q.and(expr, q.eq(q.field(columns[i]), values[i]));
|
|
759
|
-
return expr;
|
|
891
|
+
return convexAnd(q, columns.map((column, index) => q.eq(q.field(column), values[index])));
|
|
760
892
|
}
|
|
761
893
|
function ensureNullableColumns(table, columns, context) {
|
|
762
894
|
for (const columnName of columns) {
|
|
@@ -1197,78 +1329,7 @@ function enforceCheckConstraints(table, candidate) {
|
|
|
1197
1329
|
for (const check of checks) if (evaluateCheckConstraintTriState(candidate, check.expression) === false) throw new Error(`Check constraint '${check.name}' violation on '${tableName}'.`);
|
|
1198
1330
|
}
|
|
1199
1331
|
function toConvexFilter(expression) {
|
|
1200
|
-
|
|
1201
|
-
visitBinary: (expr) => {
|
|
1202
|
-
const [field, value] = expr.operands;
|
|
1203
|
-
if (!isFieldReference(field)) throw new Error("Binary expression must have FieldReference as first operand");
|
|
1204
|
-
const fieldName = field.fieldName;
|
|
1205
|
-
switch (expr.operator) {
|
|
1206
|
-
case "eq": return (q) => q.eq(q.field(fieldName), value);
|
|
1207
|
-
case "ne": return (q) => q.neq(q.field(fieldName), value);
|
|
1208
|
-
case "gt": return (q) => q.gt(q.field(fieldName), value);
|
|
1209
|
-
case "gte": return (q) => q.gte(q.field(fieldName), value);
|
|
1210
|
-
case "lt": return (q) => q.lt(q.field(fieldName), value);
|
|
1211
|
-
case "lte": return (q) => q.lte(q.field(fieldName), value);
|
|
1212
|
-
case "inArray": {
|
|
1213
|
-
const values = value;
|
|
1214
|
-
return (q) => {
|
|
1215
|
-
if (values.length === 0) return q.eq(q.field("_id"), "__better_convex_never__");
|
|
1216
|
-
return values.map((v) => q.eq(q.field(fieldName), v)).reduce((acc, cond) => q.or(acc, cond));
|
|
1217
|
-
};
|
|
1218
|
-
}
|
|
1219
|
-
case "notInArray": {
|
|
1220
|
-
const values = value;
|
|
1221
|
-
return (q) => {
|
|
1222
|
-
return values.map((v) => q.neq(q.field(fieldName), v)).reduce((acc, cond) => q.and(acc, cond));
|
|
1223
|
-
};
|
|
1224
|
-
}
|
|
1225
|
-
case "like":
|
|
1226
|
-
case "ilike":
|
|
1227
|
-
case "notLike":
|
|
1228
|
-
case "notIlike":
|
|
1229
|
-
case "startsWith":
|
|
1230
|
-
case "endsWith":
|
|
1231
|
-
case "contains":
|
|
1232
|
-
case "arrayContains":
|
|
1233
|
-
case "arrayContained":
|
|
1234
|
-
case "arrayOverlaps": return () => true;
|
|
1235
|
-
default: throw new Error(`Unsupported binary operator: ${expr.operator}`);
|
|
1236
|
-
}
|
|
1237
|
-
},
|
|
1238
|
-
visitLogical: (expr) => {
|
|
1239
|
-
const operandFns = expr.operands.map((op) => op.accept(visitor));
|
|
1240
|
-
if (expr.operator === "and") return (q) => {
|
|
1241
|
-
let result = operandFns[0](q);
|
|
1242
|
-
for (let i = 1; i < operandFns.length; i++) result = q.and(result, operandFns[i](q));
|
|
1243
|
-
return result;
|
|
1244
|
-
};
|
|
1245
|
-
if (expr.operator === "or") return (q) => {
|
|
1246
|
-
let result = operandFns[0](q);
|
|
1247
|
-
for (let i = 1; i < operandFns.length; i++) result = q.or(result, operandFns[i](q));
|
|
1248
|
-
return result;
|
|
1249
|
-
};
|
|
1250
|
-
throw new Error(`Unsupported logical operator: ${expr.operator}`);
|
|
1251
|
-
},
|
|
1252
|
-
visitUnary: (expr) => {
|
|
1253
|
-
const operand = expr.operands[0];
|
|
1254
|
-
if (expr.operator === "not") {
|
|
1255
|
-
const operandFn = operand.accept(visitor);
|
|
1256
|
-
return (q) => q.not(operandFn(q));
|
|
1257
|
-
}
|
|
1258
|
-
if (expr.operator === "isNull") {
|
|
1259
|
-
if (!isFieldReference(operand)) throw new Error("isNull must operate on a field reference");
|
|
1260
|
-
const fieldName = operand.fieldName;
|
|
1261
|
-
return (q) => q.eq(q.field(fieldName), null);
|
|
1262
|
-
}
|
|
1263
|
-
if (expr.operator === "isNotNull") {
|
|
1264
|
-
if (!isFieldReference(operand)) throw new Error("isNotNull must operate on a field reference");
|
|
1265
|
-
const fieldName = operand.fieldName;
|
|
1266
|
-
return (q) => q.neq(q.field(fieldName), null);
|
|
1267
|
-
}
|
|
1268
|
-
throw new Error(`Unsupported unary operator: ${expr.operator}`);
|
|
1269
|
-
}
|
|
1270
|
-
};
|
|
1271
|
-
return expression.accept(visitor);
|
|
1332
|
+
return compileConvexFilter(expression);
|
|
1272
1333
|
}
|
|
1273
1334
|
|
|
1274
1335
|
//#endregion
|
|
@@ -1422,4 +1483,4 @@ function aggregateExtension() {
|
|
|
1422
1483
|
}
|
|
1423
1484
|
|
|
1424
1485
|
//#endregion
|
|
1425
|
-
export { serializeFilterExpression as $, ensureNonNullValues as A, getMutationExecutionMode as B, deserializeFilterExpression as C, enforcePolymorphicWrite as D, enforceForeignKeys as E, getChecks as F, getUniqueIndexes as G, getTableColumns as H, getColumnName as I, normalizeDateFieldsForWrite as J, hardDeleteRow as K, getForeignKeys as L, evaluateCheckConstraintTriState as M, evaluateFilter as N, enforceUniqueIndexes as O, extractPrimaryIdLookup as P, selectReturningRowWithHydration as Q, getMutationAsyncDelayMs as R, decodeUndefinedDeep as S, enforceCheckConstraints as T, getTableDeleteConfig as U, getOrmContext as V, getTableName as W, patchReferencingRows as X, normalizeTemporalComparableValue as Y, resolveOrmRuntimeDefaults as Z, applyIncomingForeignKeyActionsOnUpdate as _,
|
|
1486
|
+
export { serializeFilterExpression as $, ensureNonNullValues as A, getMutationExecutionMode as B, deserializeFilterExpression as C, enforcePolymorphicWrite as D, enforceForeignKeys as E, getChecks as F, getUniqueIndexes as G, getTableColumns as H, getColumnName as I, normalizeDateFieldsForWrite as J, hardDeleteRow as K, getForeignKeys as L, evaluateCheckConstraintTriState as M, evaluateFilter as N, enforceUniqueIndexes as O, extractPrimaryIdLookup as P, selectReturningRowWithHydration as Q, getMutationAsyncDelayMs as R, decodeUndefinedDeep as S, enforceCheckConstraints as T, getTableDeleteConfig as U, getOrmContext as V, getTableName as W, patchReferencingRows as X, normalizeTemporalComparableValue as Y, resolveOrmRuntimeDefaults as Z, applyIncomingForeignKeyActionsOnUpdate as _, resolveIndexOrderPushdown as _t, aggregateExtension as a, markLifecycleHookedTables as at, collectMutationRowsBounded as b, PUBLIC_CREATED_AT_FIELD as bt, AGGREGATE_ERROR as c, isConvexEnforceableFilter as ct, createCountError as d, findRelationIndex as dt, softDeleteRow as et, createError as f, findSearchIndexByName as ft, applyIncomingForeignKeyActionsOnDelete as g, getRankIndexes as gt, applyDefaults as h, getIndexes as ht, AGGREGATE_STATE_TABLE as i, hasLifecycleHooks as it, ensureNullableColumns as j, ensureDefaultColumns as k, COUNT_ERROR as l, mapWithConcurrency as lt, ensureCountAllowedForRls as m, getAggregateIndexes as mt, AGGREGATE_EXTREMA_TABLE as n, takeRowsWithinByteBudget as nt, getAggregateIndexDefinitions as o, compileConvexFilter as ot, ensureAggregateAllowedForRls as p, findVectorIndexByName as pt, hydrateDateFieldsForRead as q, AGGREGATE_MEMBER_TABLE as r, toConvexFilter as rt, getRankIndexDefinitions as s, convexAnd as st, AGGREGATE_BUCKET_TABLE as t, splitReturningSelection as tt, createAggregateError as u, findIndexForColumns as ut, buildForeignKeyGraph as v, CREATED_AT_MIGRATION_MESSAGE as vt, encodeUndefinedDeep as w, collectPrimaryIdLookupRows as x, usesSystemCreatedAtAlias as xt, canUsePrimaryIdLookupCursor as y, INTERNAL_CREATION_TIME_FIELD as yt, getMutationCollectionLimits as z };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Bn as ConvexTextBuilderInitial, Dr as SystemFieldAliases, F as DeleteMode, Gn as OrmRuntimeDefaults, H as EdgeMetadata, Hn as ConvexColumnBuilder, Hr as entityKind, Ht as RelationsConfigWithSchema, I as SerializedFilterExpression, Jn as OrmSchemaExtensionTriggers, Kn as OrmSchemaExtensionRelations, L as getChecks, M as OrmReader, Mr as ColumnBuilderBaseConfig, N as OrmWriter, Nt as AnyRelationsBuilderConfig, Or as SystemFields, P as CascadeMode, Pt as ExtractTablesFromSchema, Qt as OrmLifecycleChange, R as getForeignKeys, Rr as HasDefault, Rt as RelationsBuilder, St as OrderByClause, Ut as TableRelationalConfig, Vt as RelationsBuilderConfigValue, Wn as Columns, Wt as TablesRelationalConfig, Xn as OrmSchemaRelations, Xt as ConvexTableWithColumns, Yt as ConvexTable, Zn as OrmSchemaTriggers, b as MigrationSet, ft as InferSelectModel, in as RlsPolicy, jr as ColumnBuilder, jt as VectorSearchProvider, k as CreateDatabaseOptions, kr as $Type, nr as FilterExpression$1, r as OrmCapability, ut as InferInsertModel, z as getUniqueIndexes } from "./capabilities-
|
|
1
|
+
import { Bn as ConvexTextBuilderInitial, Dr as SystemFieldAliases, F as DeleteMode, Gn as OrmRuntimeDefaults, H as EdgeMetadata, Hn as ConvexColumnBuilder, Hr as entityKind, Ht as RelationsConfigWithSchema, I as SerializedFilterExpression, Jn as OrmSchemaExtensionTriggers, Kn as OrmSchemaExtensionRelations, L as getChecks, M as OrmReader, Mr as ColumnBuilderBaseConfig, N as OrmWriter, Nt as AnyRelationsBuilderConfig, Or as SystemFields, P as CascadeMode, Pt as ExtractTablesFromSchema, Qt as OrmLifecycleChange, R as getForeignKeys, Rr as HasDefault, Rt as RelationsBuilder, St as OrderByClause, Ut as TableRelationalConfig, Vt as RelationsBuilderConfigValue, Wn as Columns, Wt as TablesRelationalConfig, Xn as OrmSchemaRelations, Xt as ConvexTableWithColumns, Yt as ConvexTable, Zn as OrmSchemaTriggers, b as MigrationSet, ft as InferSelectModel, in as RlsPolicy, jr as ColumnBuilder, jt as VectorSearchProvider, k as CreateDatabaseOptions, kr as $Type, nr as FilterExpression$1, r as OrmCapability, ut as InferInsertModel, z as getUniqueIndexes } from "./capabilities-DtDfpdcH.js";
|
|
2
2
|
import * as convex_values0 from "convex/values";
|
|
3
3
|
import { GenericId, Validator, Value } from "convex/values";
|
|
4
4
|
import { DefineSchemaOptions, GenericDatabaseReader, GenericDatabaseWriter, GenericSchema, SchedulableFunctionReference, Scheduler, SchemaDefinition, internalActionGeneric, internalMutationGeneric } from "convex/server";
|
|
@@ -111,15 +111,6 @@ declare const migrationStorageTables: {
|
|
|
111
111
|
fieldName: "cursor";
|
|
112
112
|
};
|
|
113
113
|
};
|
|
114
|
-
direction: ConvexTextBuilderInitial<""> & {
|
|
115
|
-
_: {
|
|
116
|
-
tableName: "migration_state";
|
|
117
|
-
};
|
|
118
|
-
} & {
|
|
119
|
-
_: {
|
|
120
|
-
fieldName: "direction";
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
114
|
migrationId: ConvexTextBuilderInitial<""> & {
|
|
124
115
|
_: {
|
|
125
116
|
notNull: true;
|
|
@@ -159,6 +150,15 @@ declare const migrationStorageTables: {
|
|
|
159
150
|
fieldName: "applied";
|
|
160
151
|
};
|
|
161
152
|
};
|
|
153
|
+
direction: ConvexTextBuilderInitial<""> & {
|
|
154
|
+
_: {
|
|
155
|
+
tableName: "migration_state";
|
|
156
|
+
};
|
|
157
|
+
} & {
|
|
158
|
+
_: {
|
|
159
|
+
fieldName: "direction";
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
162
|
runId: ConvexTextBuilderInitial<""> & {
|
|
163
163
|
_: {
|
|
164
164
|
tableName: "migration_state";
|
|
@@ -1008,7 +1008,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1008
1008
|
readonly aggregate_bucket: ConvexTableWithColumns<{
|
|
1009
1009
|
name: "aggregate_bucket";
|
|
1010
1010
|
columns: {
|
|
1011
|
-
|
|
1011
|
+
count: ConvexNumberBuilderInitial<""> & {
|
|
1012
1012
|
_: {
|
|
1013
1013
|
notNull: true;
|
|
1014
1014
|
};
|
|
@@ -1018,10 +1018,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1018
1018
|
};
|
|
1019
1019
|
} & {
|
|
1020
1020
|
_: {
|
|
1021
|
-
fieldName: "
|
|
1021
|
+
fieldName: "count";
|
|
1022
1022
|
};
|
|
1023
1023
|
};
|
|
1024
|
-
|
|
1024
|
+
updatedAt: ConvexNumberBuilderInitial<""> & {
|
|
1025
1025
|
_: {
|
|
1026
1026
|
notNull: true;
|
|
1027
1027
|
};
|
|
@@ -1031,10 +1031,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1031
1031
|
};
|
|
1032
1032
|
} & {
|
|
1033
1033
|
_: {
|
|
1034
|
-
fieldName: "
|
|
1034
|
+
fieldName: "updatedAt";
|
|
1035
1035
|
};
|
|
1036
1036
|
};
|
|
1037
|
-
|
|
1037
|
+
indexName: ConvexTextBuilderInitial<""> & {
|
|
1038
1038
|
_: {
|
|
1039
1039
|
notNull: true;
|
|
1040
1040
|
};
|
|
@@ -1044,10 +1044,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1044
1044
|
};
|
|
1045
1045
|
} & {
|
|
1046
1046
|
_: {
|
|
1047
|
-
fieldName: "
|
|
1047
|
+
fieldName: "indexName";
|
|
1048
1048
|
};
|
|
1049
1049
|
};
|
|
1050
|
-
|
|
1050
|
+
tableKey: ConvexTextBuilderInitial<""> & {
|
|
1051
1051
|
_: {
|
|
1052
1052
|
notNull: true;
|
|
1053
1053
|
};
|
|
@@ -1057,7 +1057,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1057
1057
|
};
|
|
1058
1058
|
} & {
|
|
1059
1059
|
_: {
|
|
1060
|
-
fieldName: "
|
|
1060
|
+
fieldName: "tableKey";
|
|
1061
1061
|
};
|
|
1062
1062
|
};
|
|
1063
1063
|
keyHash: ConvexTextBuilderInitial<""> & {
|
|
@@ -1133,7 +1133,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1133
1133
|
readonly aggregate_member: ConvexTableWithColumns<{
|
|
1134
1134
|
name: "aggregate_member";
|
|
1135
1135
|
columns: {
|
|
1136
|
-
|
|
1136
|
+
updatedAt: ConvexNumberBuilderInitial<""> & {
|
|
1137
1137
|
_: {
|
|
1138
1138
|
notNull: true;
|
|
1139
1139
|
};
|
|
@@ -1143,10 +1143,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1143
1143
|
};
|
|
1144
1144
|
} & {
|
|
1145
1145
|
_: {
|
|
1146
|
-
fieldName: "
|
|
1146
|
+
fieldName: "updatedAt";
|
|
1147
1147
|
};
|
|
1148
1148
|
};
|
|
1149
|
-
|
|
1149
|
+
kind: ConvexTextBuilderInitial<""> & {
|
|
1150
1150
|
_: {
|
|
1151
1151
|
notNull: true;
|
|
1152
1152
|
};
|
|
@@ -1156,7 +1156,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1156
1156
|
};
|
|
1157
1157
|
} & {
|
|
1158
1158
|
_: {
|
|
1159
|
-
fieldName: "
|
|
1159
|
+
fieldName: "kind";
|
|
1160
1160
|
};
|
|
1161
1161
|
};
|
|
1162
1162
|
indexName: ConvexTextBuilderInitial<""> & {
|
|
@@ -1323,11 +1323,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1323
1323
|
readonly aggregate_extrema: ConvexTableWithColumns<{
|
|
1324
1324
|
name: "aggregate_extrema";
|
|
1325
1325
|
columns: {
|
|
1326
|
-
|
|
1327
|
-
_: {
|
|
1328
|
-
$type: convex_values0.Value;
|
|
1329
|
-
};
|
|
1330
|
-
} & {
|
|
1326
|
+
count: ConvexNumberBuilderInitial<""> & {
|
|
1331
1327
|
_: {
|
|
1332
1328
|
notNull: true;
|
|
1333
1329
|
};
|
|
@@ -1337,7 +1333,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1337
1333
|
};
|
|
1338
1334
|
} & {
|
|
1339
1335
|
_: {
|
|
1340
|
-
fieldName: "
|
|
1336
|
+
fieldName: "count";
|
|
1341
1337
|
};
|
|
1342
1338
|
};
|
|
1343
1339
|
updatedAt: ConvexNumberBuilderInitial<""> & {
|
|
@@ -1353,7 +1349,11 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1353
1349
|
fieldName: "updatedAt";
|
|
1354
1350
|
};
|
|
1355
1351
|
};
|
|
1356
|
-
|
|
1352
|
+
value: ConvexCustomBuilderInitial<"", convex_values0.VAny<any, "required", string>> & {
|
|
1353
|
+
_: {
|
|
1354
|
+
$type: convex_values0.Value;
|
|
1355
|
+
};
|
|
1356
|
+
} & {
|
|
1357
1357
|
_: {
|
|
1358
1358
|
notNull: true;
|
|
1359
1359
|
};
|
|
@@ -1363,10 +1363,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1363
1363
|
};
|
|
1364
1364
|
} & {
|
|
1365
1365
|
_: {
|
|
1366
|
-
fieldName: "
|
|
1366
|
+
fieldName: "value";
|
|
1367
1367
|
};
|
|
1368
1368
|
};
|
|
1369
|
-
|
|
1369
|
+
indexName: ConvexTextBuilderInitial<""> & {
|
|
1370
1370
|
_: {
|
|
1371
1371
|
notNull: true;
|
|
1372
1372
|
};
|
|
@@ -1376,10 +1376,10 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1376
1376
|
};
|
|
1377
1377
|
} & {
|
|
1378
1378
|
_: {
|
|
1379
|
-
fieldName: "
|
|
1379
|
+
fieldName: "indexName";
|
|
1380
1380
|
};
|
|
1381
1381
|
};
|
|
1382
|
-
|
|
1382
|
+
tableKey: ConvexTextBuilderInitial<""> & {
|
|
1383
1383
|
_: {
|
|
1384
1384
|
notNull: true;
|
|
1385
1385
|
};
|
|
@@ -1389,7 +1389,7 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1389
1389
|
};
|
|
1390
1390
|
} & {
|
|
1391
1391
|
_: {
|
|
1392
|
-
fieldName: "
|
|
1392
|
+
fieldName: "tableKey";
|
|
1393
1393
|
};
|
|
1394
1394
|
};
|
|
1395
1395
|
keyHash: ConvexTextBuilderInitial<""> & {
|
|
@@ -1589,19 +1589,6 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1589
1589
|
fieldName: "status";
|
|
1590
1590
|
};
|
|
1591
1591
|
};
|
|
1592
|
-
kind: ConvexTextBuilderInitial<""> & {
|
|
1593
|
-
_: {
|
|
1594
|
-
notNull: true;
|
|
1595
|
-
};
|
|
1596
|
-
} & {
|
|
1597
|
-
_: {
|
|
1598
|
-
tableName: "aggregate_state";
|
|
1599
|
-
};
|
|
1600
|
-
} & {
|
|
1601
|
-
_: {
|
|
1602
|
-
fieldName: "kind";
|
|
1603
|
-
};
|
|
1604
|
-
};
|
|
1605
1592
|
cursor: ConvexTextBuilderInitial<""> & {
|
|
1606
1593
|
_: {
|
|
1607
1594
|
tableName: "aggregate_state";
|
|
@@ -1668,6 +1655,19 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1668
1655
|
fieldName: "lastError";
|
|
1669
1656
|
};
|
|
1670
1657
|
};
|
|
1658
|
+
kind: ConvexTextBuilderInitial<""> & {
|
|
1659
|
+
_: {
|
|
1660
|
+
notNull: true;
|
|
1661
|
+
};
|
|
1662
|
+
} & {
|
|
1663
|
+
_: {
|
|
1664
|
+
tableName: "aggregate_state";
|
|
1665
|
+
};
|
|
1666
|
+
} & {
|
|
1667
|
+
_: {
|
|
1668
|
+
fieldName: "kind";
|
|
1669
|
+
};
|
|
1670
|
+
};
|
|
1671
1671
|
indexName: ConvexTextBuilderInitial<""> & {
|
|
1672
1672
|
_: {
|
|
1673
1673
|
notNull: true;
|
|
@@ -1753,15 +1753,6 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1753
1753
|
fieldName: "cursor";
|
|
1754
1754
|
};
|
|
1755
1755
|
};
|
|
1756
|
-
direction: ConvexTextBuilderInitial<""> & {
|
|
1757
|
-
_: {
|
|
1758
|
-
tableName: "migration_state";
|
|
1759
|
-
};
|
|
1760
|
-
} & {
|
|
1761
|
-
_: {
|
|
1762
|
-
fieldName: "direction";
|
|
1763
|
-
};
|
|
1764
|
-
};
|
|
1765
1756
|
migrationId: ConvexTextBuilderInitial<""> & {
|
|
1766
1757
|
_: {
|
|
1767
1758
|
notNull: true;
|
|
@@ -1801,6 +1792,15 @@ declare const BUILTIN_SCHEMA_EXTENSIONS: readonly [SchemaExtension<{
|
|
|
1801
1792
|
fieldName: "applied";
|
|
1802
1793
|
};
|
|
1803
1794
|
};
|
|
1795
|
+
direction: ConvexTextBuilderInitial<""> & {
|
|
1796
|
+
_: {
|
|
1797
|
+
tableName: "migration_state";
|
|
1798
|
+
};
|
|
1799
|
+
} & {
|
|
1800
|
+
_: {
|
|
1801
|
+
fieldName: "direction";
|
|
1802
|
+
};
|
|
1803
|
+
};
|
|
1804
1804
|
runId: ConvexTextBuilderInitial<""> & {
|
|
1805
1805
|
_: {
|
|
1806
1806
|
tableName: "migration_state";
|
package/package.json
CHANGED
|
@@ -67,6 +67,8 @@ const total = await ctx.orm.query.todos.count({ where: { projectId } });
|
|
|
67
67
|
Unfiltered `count()` uses native Convex count syscall (no aggregateIndex required).
|
|
68
68
|
Filtered `count()` accepts `eq`, `in`, `isNull`, `gt`, `gte`, `lt`, `lte`, conjunction via `AND`, and bounded finite DNF `OR` when every branch is index-plannable on one `aggregateIndex`. Requires matching `aggregateIndex`.
|
|
69
69
|
|
|
70
|
+
`isNull: true` matches an explicitly-`null` column and an absent column (a nullable column is optional, so a row inserted without it stores it absent). Matching `null` exactly (`{ status: null }` or `{ status: { eq: null } }`) matches only explicitly-`null` rows. `count()`, `aggregate()`, `groupBy()`, and relation `_count` use the same null semantics as `findMany()`.
|
|
71
|
+
|
|
70
72
|
Windowed count: `count({ where, orderBy, skip, take, cursor })` counts rows within a window.
|
|
71
73
|
|
|
72
74
|
- `skip`/`take` for pagination windows, `cursor` for "after this value" counting (requires `orderBy`, single field in v1)
|
|
@@ -102,6 +104,7 @@ Windowed aggregate:
|
|
|
102
104
|
|
|
103
105
|
- `by` is required
|
|
104
106
|
- every `by` field must be constrained in `where` via `eq`/`in`/`isNull`
|
|
107
|
+
- an `isNull`-constrained `by` field emits one group keyed `null`, covering both explicitly-`null` and absent rows
|
|
105
108
|
- `orderBy` supports `by` fields and selected metric fields
|
|
106
109
|
- `skip`/`take`/`cursor` require explicit `orderBy`
|
|
107
110
|
- `having` supports conjunction filters on `by` fields and selected metrics
|