Skip to content

Commit

Permalink
Add sort()
Browse files Browse the repository at this point in the history
  • Loading branch information
ehmicky committed Mar 13, 2022
1 parent 7bfa247 commit 272ad3c
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 28 deletions.
2 changes: 1 addition & 1 deletion src/config/normalize/lib/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const applyRuleDeep = async function (
{ config, moves, warnings },
{ rule, rule: { namePath }, context, cwd, prefix, parent },
) {
const entries = list(config, namePath, { childFirst: true })
const entries = list(config, namePath, { childFirst: true, sort: true })
return await pReduce(
entries,
(memo, { value, query: nameQuery, path: namePathA }) =>
Expand Down
10 changes: 5 additions & 5 deletions src/config/normalize/lib/wild_wild_path/get.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ import { iterate } from './iterate/main.js'
// Retrieve all properties in `target` matching a query string.
// Unlike `get|has()` it also return missing entries, letting consumers filter
// them or not.
export const list = function (target, query, { childFirst = false } = {}) {
return [...iterate(target, query, { childFirst })]
export const list = function (target, query, { childFirst, sort } = {}) {
return [...iterate(target, query, { childFirst, sort })]
}

// Retrieve a single property's value in `target` matching a query string.
// Wildcards can be used, but only the first value is returned.
export const get = function (target, query, { childFirst = false } = {}) {
const entry = find(target, query, { childFirst })
export const get = function (target, query, { childFirst, sort } = {}) {
const entry = find(target, query, { childFirst, sort })
return entry === undefined ? undefined : entry.value
}

// Check if a property is not missing according to a query
export const has = function (target, query) {
return find(target, query, { childFirst: false }) !== undefined
return find(target, query, { childFirst: false, sort: false }) !== undefined
}

// Find the first non-missing entry
Expand Down
17 changes: 17 additions & 0 deletions src/config/normalize/lib/wild_wild_path/iterate/group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { groupBy } from '../../../../../utils/group.js'

// We need to group entries by the last property to ensure `childFirst` order.
// We also sort when `sort` is true`
export const groupSortChildEntries = function (childEntries, sort) {
const childEntriesObj = groupBy(childEntries, getLastProp)
return sort
? // eslint-disable-next-line fp/no-mutating-methods
Object.keys(childEntriesObj)
.sort()
.map((prop) => childEntriesObj[prop])
: Object.values(childEntriesObj)
}

const getLastProp = function ({ path }) {
return path[path.length - 1]
}
14 changes: 2 additions & 12 deletions src/config/normalize/lib/wild_wild_path/iterate/main.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { groupBy } from '../../../../../utils/group.js'
import { parseQuery } from '../parsing/parse.js'
import { serializePath } from '../parsing/serialize.js'

import { removeDuplicates } from './duplicate.js'
import { expandToken } from './expand.js'
import { groupSortChildEntries } from './group.js'

// Iterate over all values (and their associated path) matching a specific
// query for on specific target value.
Expand Down Expand Up @@ -92,20 +92,10 @@ const iterateChildren = function* ({ childEntries, childFirst, sort, index }) {
return
}

const childEntriesGroups = groupSortChildEntries(childEntries)
const childEntriesGroups = groupSortChildEntries(childEntries, sort)

// eslint-disable-next-line fp/no-loops
for (const entries of childEntriesGroups) {
yield* iterateLevel({ entries, childFirst, sort, index: nextIndex })
}
}

// We need to group entries by the last property to ensure `childFirst` order.
// We also sort when `sort` is true`
const groupSortChildEntries = function (childEntries) {
return Object.values(groupBy(childEntries, getLastProp))
}

const getLastProp = function ({ path }) {
return path[path.length - 1]
}
5 changes: 4 additions & 1 deletion src/config/normalize/lib/wild_wild_path/set.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export const reduceParents = function (target, query, setFunc) {
const paths = []

// eslint-disable-next-line fp/no-loops
for (const { path } of iterate(target, query, { childFirst: false })) {
for (const { path } of iterate(target, query, {
childFirst: false,
sort: false,
})) {
// eslint-disable-next-line max-depth
if (!parentIsSet(paths, path)) {
// eslint-disable-next-line fp/no-mutating-methods
Expand Down
9 changes: 7 additions & 2 deletions src/config/normalize/lib/wild_wild_path_utils/find.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@ import { iterate } from '../wild_wild_path/main.js'

// Find the first non-missing property that matches a condition
// eslint-disable-next-line max-params
export const find = function (target, query, condition, { childFirst } = {}) {
export const find = function (
target,
query,
condition,
{ childFirst, sort } = {},
) {
// eslint-disable-next-line fp/no-loops
for (const entry of iterate(target, query, { childFirst })) {
for (const entry of iterate(target, query, { childFirst, sort })) {
// eslint-disable-next-line max-depth
if (!entry.missing && condition(entry)) {
return entry
Expand Down
24 changes: 18 additions & 6 deletions src/config/normalize/lib/wild_wild_path_utils/include.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@ import {
} from '../wild_wild_path/main.js'

// Returns an object with only the properties being queried.
export const pick = function (target, query) {
return reduceParents(pickEntry, returnTrue, { target, newTarget: {}, query })
export const pick = function (target, query, { sort } = {}) {
return reduceParents(pickEntry, returnTrue, {
target,
newTarget: {},
query,
sort,
})
}

const pickEntry = function (target, { path, value }) {
Expand All @@ -20,8 +25,14 @@ const returnTrue = function () {
}

// Remove values not matching a query
export const include = function (target, query, condition) {
return reduceParents(pickEntry, condition, { target, newTarget: {}, query })
// eslint-disable-next-line max-params
export const include = function (target, query, condition, { sort } = {}) {
return reduceParents(pickEntry, condition, {
target,
newTarget: {},
query,
sort,
})
}

// Remove values matching a query
Expand All @@ -31,6 +42,7 @@ export const exclude = function (target, query, condition) {
target,
newTarget: target,
query,
sort: false,
})
}

Expand All @@ -49,12 +61,12 @@ const shouldExclude = function (condition, { path, query, missing }, target) {
const reduceParents = function (
setFunc,
condition,
{ target, newTarget, query },
{ target, newTarget, query, sort },
) {
const paths = []

// eslint-disable-next-line fp/no-loops
for (const entry of iterate(target, query, { childFirst: false })) {
for (const entry of iterate(target, query, { childFirst: false, sort })) {
// eslint-disable-next-line max-depth
if (shouldUseEntry({ entry, paths, newTarget, condition })) {
// eslint-disable-next-line fp/no-mutating-methods
Expand Down
5 changes: 4 additions & 1 deletion src/config/normalize/lib/wild_wild_path_utils/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ export const map = function (target, query, mapFunc) {
let newTarget = target

// eslint-disable-next-line fp/no-loops
for (const entry of iterate(target, query, { childFirst: true })) {
for (const entry of iterate(target, query, {
childFirst: true,
sort: false,
})) {
// eslint-disable-next-line fp/no-mutation
newTarget = mapEntry(mapFunc, newTarget, entry)
}
Expand Down

0 comments on commit 272ad3c

Please sign in to comment.