• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mia-platform / crud-service / 18993092424

01 Nov 2025 07:02AM UTC coverage: 97.283% (-0.04%) from 97.319%
18993092424

Pull #568

github

web-flow
Merge 4e13983cf into bd427899a
Pull Request #568: ci(deps): bump actions/setup-node from 5.0.0 to 6.0.0

1462 of 1570 branches covered (93.12%)

Branch coverage included in aggregate %.

9460 of 9657 relevant lines covered (97.96%)

7820.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.57
/lib/createIndexes.js
1
/*
99✔
2
 * Copyright 2023 Mia s.r.l.
99✔
3
 *
99✔
4
 * Licensed under the Apache License, Version 2.0 (the "License");
99✔
5
 * you may not use this file except in compliance with the License.
99✔
6
 * You may obtain a copy of the License at
99✔
7
 *
99✔
8
 *     http://www.apache.org/licenses/LICENSE-2.0
99✔
9
 *
99✔
10
 * Unless required by applicable law or agreed to in writing, software
99✔
11
 * distributed under the License is distributed on an "AS IS" BASIS,
99✔
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
99✔
13
 * See the License for the specific language governing permissions and
99✔
14
 * limitations under the License.
99✔
15
 */
99✔
16

99✔
17
'use strict'
99✔
18

99✔
19
const {
99✔
20
  MONGOID,
99✔
21
  HASHED_FIELD,
99✔
22
  GEO_FIELD,
99✔
23
  TEXT_FIELD,
99✔
24
  NORMAL_INDEX,
99✔
25
  HASHED_INDEX,
99✔
26
  GEO_INDEX,
99✔
27
  TEXT_INDEX,
99✔
28
} = require('./consts')
99✔
29
const { isEqual } = require('lodash')
99✔
30

99✔
31
const addKeyToSpec = (specObject, { name, order }) => ({ ...specObject, [name]: order })
99✔
32
const addTextKeyToSpec = (specObject, { name }) => ({ ...specObject, [name]: TEXT_FIELD })
99✔
33

99✔
34
module.exports = async function createIndexes(collection, indexes, prefixOfIndexesToPreserve) {
99✔
35
  let alreadyPresentIndexes = []
3,850✔
36
  const indexNamesToMantain = []
3,850✔
37
  const indexNamesToDrop = []
3,850✔
38
  try {
3,850✔
39
    alreadyPresentIndexes = await collection.indexes()
3,850✔
40
  } catch (error) {
3,850✔
41
    // throws if the collection doesn't exists...
3,523✔
42
  }
3,523✔
43

3,850✔
44
  const indexesNames = indexes.map(index => (index['name']))
3,850✔
45

3,850✔
46
  alreadyPresentIndexes.forEach(foundIndex => {
3,850✔
47
    if (
396✔
48
      !foundIndex.name.startsWith(prefixOfIndexesToPreserve)
396✔
49
      && !foundIndex.key._id
396✔
50
      && !(
396✔
51
        indexesNames.includes(foundIndex.name)
63✔
52
        && checkIndexEquality(foundIndex, indexes.find(idx => idx.name === foundIndex.name))
63✔
53
      )
63✔
54
    ) {
396✔
55
      indexNamesToDrop.push(foundIndex.name)
39✔
56
    } else {
395✔
57
      indexNamesToMantain.push(foundIndex.name)
357✔
58
    }
357✔
59
  })
3,850✔
60

3,850✔
61
  await Promise.all(indexNamesToDrop.map(name => collection.dropIndex(name)))
3,850✔
62

3,850✔
63
  return Promise.all(indexes
3,850✔
64
    .filter(index => index.name !== MONGOID && !indexNamesToMantain.includes(index.name))
3,850✔
65
    .map(index => createIndex(collection, index)))
3,850✔
66
}
3,850✔
67

99✔
68
async function createIndex(collection, index) {
4,765✔
69
  let spec
4,765✔
70

4,765✔
71
  switch (index.type) {
4,765✔
72
  case NORMAL_INDEX: {
4,765✔
73
    spec = index.fields.reduce(addKeyToSpec, {})
3,155✔
74
    break
3,155✔
75
  }
3,155✔
76
  case GEO_INDEX: {
4,765✔
77
    const { field } = index
905✔
78
    spec = { [field]: GEO_FIELD }
905✔
79
    break
905✔
80
  }
905✔
81
  case HASHED_INDEX: {
4,765✔
82
    const { field } = index
21✔
83
    spec = { [field]: HASHED_FIELD }
21✔
84
    break
21✔
85
  }
21✔
86
  case TEXT_INDEX: {
4,765✔
87
    spec = index.fields.reduce(addTextKeyToSpec, {})
684✔
88
    break
684✔
89
  }
684✔
90
  default: {
4,765!
91
    throw new Error(`Cannot create index of type ${index?.type}`)
×
92
  }
×
93
  }
4,765✔
94

4,765✔
95
  const options = getIndexOptions(index)
4,765✔
96
  return collection.createIndex(spec, options)
4,765✔
97
}
4,765✔
98

99✔
99
function getIndexOptions(index) {
4,765✔
100
  let options = {
4,765✔
101
    name: index.name,
4,765✔
102
    unique: index.unique || false,
4,765✔
103
    background: true,
4,765✔
104
  }
4,765✔
105

4,765✔
106
  if (index.expireAfterSeconds) {
4,765✔
107
    options = { ...options, expireAfterSeconds: index.expireAfterSeconds }
240✔
108
  }
240✔
109
  if (index.weights) {
4,765✔
110
    options = { ...options, weights: index.weights }
675✔
111
  }
675✔
112
  if (index.defaultLanguage) {
4,765✔
113
    options = { ...options, default_language: index.defaultLanguage }
675✔
114
  }
675✔
115
  if (index.languageOverride) {
4,765✔
116
    options = { ...options, language_override: index.languageOverride }
675✔
117
  }
675✔
118
  if (index.usePartialFilter) {
4,765✔
119
    const partialFilterExpression = parsePartialIndex(index)
242✔
120
    options = { ...options, partialFilterExpression }
242✔
121
  }
242✔
122
  return options
4,765✔
123
}
4,765✔
124

99✔
125
function parsePartialIndex(index) {
296✔
126
  try {
296✔
127
    return index.partialFilterExpression ? JSON.parse(index.partialFilterExpression) : {}
296✔
128
  } catch (error) {
296!
129
    throw new Error(`Impossible to parse the Partial Index expression of index ${index.name}`, { catch: error })
×
130
  }
×
131
}
296✔
132

99✔
133
function checkIndexEquality(foundIndex, index) {
54✔
134
  const isOptionUniqueEqual = index.unique ? foundIndex.unique === true : foundIndex.unique === undefined
54✔
135
  const isOptionExpireAfterSecondsEqual = foundIndex.expireAfterSeconds === index.expireAfterSeconds
54✔
136
  const isOptionPartialFilterEqual = isEqual(
54✔
137
    foundIndex.partialFilterExpression || {},
54✔
138
    parsePartialIndex(index)
54✔
139
  )
54✔
140
  return (
54✔
141
    isOptionUniqueEqual
54✔
142
    && isOptionExpireAfterSecondsEqual
54✔
143
    && isOptionPartialFilterEqual
54✔
144
    && checkIndexEqualityByType(foundIndex, index)
54✔
145
  )
54✔
146
}
54✔
147

99✔
148
function checkIndexEqualityByType(foundIndex, index) {
43✔
149
  switch (index.type) {
43✔
150
  case NORMAL_INDEX: {
43✔
151
    const expectedKey = index.fields.reduce(addKeyToSpec, {})
23✔
152
    return JSON.stringify(foundIndex.key) === JSON.stringify(expectedKey)
23✔
153
  }
23✔
154
  case GEO_INDEX: {
43✔
155
    return foundIndex.key[index.field] === GEO_FIELD
10✔
156
  }
10✔
157
  case HASHED_INDEX: {
43✔
158
    return foundIndex.key[index.field] === HASHED_FIELD
9✔
159
  }
9✔
160
  case TEXT_INDEX: {
43!
161
    const expectedKey = index.fields.reduce(addTextKeyToSpec, {})
1✔
162
    return JSON.stringify(foundIndex.key) === JSON.stringify(expectedKey)
1✔
163
  }
1✔
164
  default:
43!
165
    return false
×
166
  }
43✔
167
}
43✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc