adapt-authoring-api 3.2.3 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -658,7 +658,7 @@ class AbstractApiModule extends AbstractModule {
658
658
  if (results.length > 1) {
659
659
  throw this.app.errors.TOO_MANY_RESULTS.setData({ actual: results.length, expected: 1, query })
660
660
  }
661
- if (options.strict !== false && !results.length) {
661
+ if ((options.throwOnMissing ?? options.strict) !== false && !results.length) {
662
662
  throw this.app.errors.NOT_FOUND.setData({ id: query, type: options.schemaName })
663
663
  }
664
664
  return results[0] ?? null
package/lib/typedefs.js CHANGED
@@ -49,6 +49,8 @@
49
49
  * @typedef {Object} FindOptions
50
50
  * @property {String} schemaName Name of the schema to validate against
51
51
  * @property {String} collectionName DB collection to insert document into
52
+ * @property {Boolean} throwOnMissing Whether to throw a NOT_FOUND error when no results are found (default: true)
53
+ * @property {Boolean} [strict] @deprecated Use throwOnMissing instead
52
54
  */
53
55
  /**
54
56
  * @memberof api
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adapt-authoring-api",
3
- "version": "3.2.3",
3
+ "version": "3.3.0",
4
4
  "description": "Abstract module for creating APIs",
5
5
  "homepage": "https://github.com/adapt-security/adapt-authoring-api",
6
6
  "license": "GPL-3.0",
@@ -142,6 +142,56 @@ describe('AbstractApiModule', () => {
142
142
  })
143
143
  })
144
144
 
145
+ describe('#findOne()', () => {
146
+ function createFindOneInstance (findResults) {
147
+ const notFoundError = { setData: () => { const e = new Error('NOT_FOUND'); e.code = 'NOT_FOUND'; return e } }
148
+ const tooManyResultsError = { setData: () => { const e = new Error('TOO_MANY_RESULTS'); e.code = 'TOO_MANY_RESULTS'; return e } }
149
+ const instance = Object.create(AbstractApiModule.prototype)
150
+ instance.find = async () => findResults
151
+ instance.app = { errors: { NOT_FOUND: notFoundError, TOO_MANY_RESULTS: tooManyResultsError } }
152
+ return instance
153
+ }
154
+
155
+ it('should throw NOT_FOUND when no results and throwOnMissing is not set', async () => {
156
+ const instance = createFindOneInstance([])
157
+ await assert.rejects(() => instance.findOne({}), /NOT_FOUND/)
158
+ })
159
+
160
+ it('should throw NOT_FOUND when no results and throwOnMissing is true', async () => {
161
+ const instance = createFindOneInstance([])
162
+ await assert.rejects(() => instance.findOne({}, { throwOnMissing: true }), /NOT_FOUND/)
163
+ })
164
+
165
+ it('should return null when no results and throwOnMissing is false', async () => {
166
+ const instance = createFindOneInstance([])
167
+ const result = await instance.findOne({}, { throwOnMissing: false })
168
+ assert.equal(result, null)
169
+ })
170
+
171
+ it('should return null when no results and strict is false (backward compat)', async () => {
172
+ const instance = createFindOneInstance([])
173
+ const result = await instance.findOne({}, { strict: false })
174
+ assert.equal(result, null)
175
+ })
176
+
177
+ it('should prefer throwOnMissing over strict when both are set', async () => {
178
+ const instance = createFindOneInstance([])
179
+ await assert.rejects(() => instance.findOne({}, { throwOnMissing: true, strict: false }), /NOT_FOUND/)
180
+ })
181
+
182
+ it('should return the single result when found', async () => {
183
+ const doc = { _id: '1', name: 'test' }
184
+ const instance = createFindOneInstance([doc])
185
+ const result = await instance.findOne({})
186
+ assert.deepEqual(result, doc)
187
+ })
188
+
189
+ it('should throw TOO_MANY_RESULTS when more than one result is returned', async () => {
190
+ const instance = createFindOneInstance([{ _id: '1' }, { _id: '2' }])
191
+ await assert.rejects(() => instance.findOne({}), /TOO_MANY_RESULTS/)
192
+ })
193
+ })
194
+
145
195
  describe('default-routes.json', () => {
146
196
  it('should define an array of route objects', () => {
147
197
  assert.ok(Array.isArray(defaultRoutes.routes))