Skip to content

Commit 113f396

Browse files
committed
Move helper functions to the end of the file
1 parent 33945c9 commit 113f396

File tree

1 file changed

+118
-118
lines changed

1 file changed

+118
-118
lines changed

packages/db/src/collection/change-events.ts

Lines changed: 118 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -30,124 +30,6 @@ export interface CollectionLike<
3030
`get` | `has` | `entries` | `indexes` | `id`
3131
> {}
3232

33-
/**
34-
* Gets ordered keys from a collection using index optimization when possible
35-
* @param collection - The collection to get keys from
36-
* @param orderBy - The order by clause
37-
* @param limit - Optional limit on number of keys to return
38-
* @param whereFilter - Optional filter function to apply while traversing
39-
* @returns Array of keys in sorted order
40-
*/
41-
function getOrderedKeys<T extends object, TKey extends string | number>(
42-
collection: CollectionLike<T, TKey>,
43-
orderBy: OrderBy,
44-
limit?: number,
45-
whereFilter?: (item: T) => boolean,
46-
optimizedOnly?: boolean
47-
): Array<TKey> | undefined {
48-
// For single-column orderBy on a ref expression, try index optimization
49-
if (orderBy.length === 1) {
50-
const clause = orderBy[0]!
51-
const orderByExpression = clause.expression
52-
53-
if (orderByExpression.type === `ref`) {
54-
const propRef = orderByExpression
55-
const fieldPath = propRef.path
56-
57-
// Ensure index exists for this field
58-
ensureIndexForField(
59-
fieldPath[0]!,
60-
fieldPath,
61-
collection as CollectionImpl<T, TKey>,
62-
clause.compareOptions
63-
)
64-
65-
// Find the index
66-
const index = findIndexForField(
67-
collection.indexes,
68-
fieldPath,
69-
clause.compareOptions
70-
)
71-
72-
if (index && index.supports(`gt`)) {
73-
// Use index optimization
74-
const filterFn = (key: TKey): boolean => {
75-
const value = collection.get(key)
76-
if (value === undefined) {
77-
return false
78-
}
79-
return whereFilter?.(value) ?? true
80-
}
81-
82-
// Take the keys that match the filter and limit
83-
// if no limit is provided `index.keyCount` is used,
84-
// i.e. we will take all keys that match the filter
85-
return index.take(limit ?? index.keyCount, undefined, filterFn)
86-
}
87-
}
88-
}
89-
90-
if (optimizedOnly) {
91-
return
92-
}
93-
94-
// Fallback: collect all items and sort in memory
95-
const allItems: Array<{ key: TKey; value: T }> = []
96-
for (const [key, value] of collection.entries()) {
97-
if (whereFilter?.(value) ?? true) {
98-
allItems.push({ key, value })
99-
}
100-
}
101-
102-
// Sort using makeComparator
103-
const compare = (a: { key: TKey; value: T }, b: { key: TKey; value: T }) => {
104-
for (const clause of orderBy) {
105-
const compareFn = makeComparator(clause.compareOptions)
106-
107-
// Extract values for comparison
108-
const aValue = extractValueFromItem(a.value, clause.expression)
109-
const bValue = extractValueFromItem(b.value, clause.expression)
110-
111-
const result = compareFn(aValue, bValue)
112-
if (result !== 0) {
113-
return result
114-
}
115-
}
116-
return 0
117-
}
118-
119-
allItems.sort(compare)
120-
const sortedKeys = allItems.map((item) => item.key)
121-
122-
// Apply limit if provided
123-
if (limit !== undefined) {
124-
return sortedKeys.slice(0, limit)
125-
}
126-
127-
// if no limit is provided, we will return all keys
128-
return sortedKeys
129-
}
130-
131-
/**
132-
* Helper function to extract a value from an item based on an expression
133-
*/
134-
function extractValueFromItem(item: any, expression: BasicExpression): any {
135-
if (expression.type === `ref`) {
136-
const propRef = expression
137-
let value = item
138-
for (const pathPart of propRef.path) {
139-
value = value?.[pathPart]
140-
}
141-
return value
142-
} else if (expression.type === `val`) {
143-
return expression.value
144-
} else {
145-
// It must be a function
146-
const evaluator = compileSingleRowExpression(expression)
147-
return evaluator(item as Record<string, unknown>)
148-
}
149-
}
150-
15133
/**
15234
* Returns the current state of the collection as an array of changes
15335
* @param collection - The collection to get changes from
@@ -420,3 +302,121 @@ export function createFilteredCallback<T extends object>(
420302
}
421303
}
422304
}
305+
306+
/**
307+
* Gets ordered keys from a collection using index optimization when possible
308+
* @param collection - The collection to get keys from
309+
* @param orderBy - The order by clause
310+
* @param limit - Optional limit on number of keys to return
311+
* @param whereFilter - Optional filter function to apply while traversing
312+
* @returns Array of keys in sorted order
313+
*/
314+
function getOrderedKeys<T extends object, TKey extends string | number>(
315+
collection: CollectionLike<T, TKey>,
316+
orderBy: OrderBy,
317+
limit?: number,
318+
whereFilter?: (item: T) => boolean,
319+
optimizedOnly?: boolean
320+
): Array<TKey> | undefined {
321+
// For single-column orderBy on a ref expression, try index optimization
322+
if (orderBy.length === 1) {
323+
const clause = orderBy[0]!
324+
const orderByExpression = clause.expression
325+
326+
if (orderByExpression.type === `ref`) {
327+
const propRef = orderByExpression
328+
const fieldPath = propRef.path
329+
330+
// Ensure index exists for this field
331+
ensureIndexForField(
332+
fieldPath[0]!,
333+
fieldPath,
334+
collection as CollectionImpl<T, TKey>,
335+
clause.compareOptions
336+
)
337+
338+
// Find the index
339+
const index = findIndexForField(
340+
collection.indexes,
341+
fieldPath,
342+
clause.compareOptions
343+
)
344+
345+
if (index && index.supports(`gt`)) {
346+
// Use index optimization
347+
const filterFn = (key: TKey): boolean => {
348+
const value = collection.get(key)
349+
if (value === undefined) {
350+
return false
351+
}
352+
return whereFilter?.(value) ?? true
353+
}
354+
355+
// Take the keys that match the filter and limit
356+
// if no limit is provided `index.keyCount` is used,
357+
// i.e. we will take all keys that match the filter
358+
return index.take(limit ?? index.keyCount, undefined, filterFn)
359+
}
360+
}
361+
}
362+
363+
if (optimizedOnly) {
364+
return
365+
}
366+
367+
// Fallback: collect all items and sort in memory
368+
const allItems: Array<{ key: TKey; value: T }> = []
369+
for (const [key, value] of collection.entries()) {
370+
if (whereFilter?.(value) ?? true) {
371+
allItems.push({ key, value })
372+
}
373+
}
374+
375+
// Sort using makeComparator
376+
const compare = (a: { key: TKey; value: T }, b: { key: TKey; value: T }) => {
377+
for (const clause of orderBy) {
378+
const compareFn = makeComparator(clause.compareOptions)
379+
380+
// Extract values for comparison
381+
const aValue = extractValueFromItem(a.value, clause.expression)
382+
const bValue = extractValueFromItem(b.value, clause.expression)
383+
384+
const result = compareFn(aValue, bValue)
385+
if (result !== 0) {
386+
return result
387+
}
388+
}
389+
return 0
390+
}
391+
392+
allItems.sort(compare)
393+
const sortedKeys = allItems.map((item) => item.key)
394+
395+
// Apply limit if provided
396+
if (limit !== undefined) {
397+
return sortedKeys.slice(0, limit)
398+
}
399+
400+
// if no limit is provided, we will return all keys
401+
return sortedKeys
402+
}
403+
404+
/**
405+
* Helper function to extract a value from an item based on an expression
406+
*/
407+
function extractValueFromItem(item: any, expression: BasicExpression): any {
408+
if (expression.type === `ref`) {
409+
const propRef = expression
410+
let value = item
411+
for (const pathPart of propRef.path) {
412+
value = value?.[pathPart]
413+
}
414+
return value
415+
} else if (expression.type === `val`) {
416+
return expression.value
417+
} else {
418+
// It must be a function
419+
const evaluator = compileSingleRowExpression(expression)
420+
return evaluator(item as Record<string, unknown>)
421+
}
422+
}

0 commit comments

Comments
 (0)