@terreno/api 0.11.7 → 0.11.9

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.
Files changed (44) hide show
  1. package/dist/betterAuthSetup.js +10 -3
  2. package/dist/configurationPlugin.d.ts +2 -1
  3. package/dist/configurationPlugin.js +16 -9
  4. package/dist/errors.d.ts +6 -6
  5. package/dist/errors.js +22 -22
  6. package/dist/errors.test.d.ts +1 -0
  7. package/dist/errors.test.js +280 -0
  8. package/dist/githubAuth.d.ts +3 -3
  9. package/dist/githubAuth.js +16 -16
  10. package/dist/middleware.d.ts +1 -1
  11. package/dist/middleware.js +4 -3
  12. package/dist/middleware.test.d.ts +1 -0
  13. package/dist/middleware.test.js +82 -0
  14. package/dist/notifiers/googleChatNotifier.js +4 -3
  15. package/dist/notifiers/zoomNotifier.js +12 -11
  16. package/dist/openApiCompat.js +2 -1
  17. package/dist/openApiEtag.d.ts +1 -1
  18. package/dist/openApiEtag.js +4 -3
  19. package/dist/openApiValidator.d.ts +12 -12
  20. package/dist/openApiValidator.js +59 -58
  21. package/dist/plugins.d.ts +12 -1
  22. package/dist/plugins.js +34 -1
  23. package/dist/plugins.test.js +212 -8
  24. package/dist/scriptRunner.d.ts +8 -7
  25. package/dist/secretProviders.js +17 -7
  26. package/dist/types/consentForm.d.ts +4 -2
  27. package/package.json +1 -1
  28. package/src/betterAuthSetup.ts +10 -3
  29. package/src/configurationPlugin.ts +18 -9
  30. package/src/errors.test.ts +302 -0
  31. package/src/errors.ts +18 -13
  32. package/src/githubAuth.ts +11 -10
  33. package/src/middleware.test.ts +71 -0
  34. package/src/middleware.ts +6 -2
  35. package/src/notifiers/googleChatNotifier.ts +4 -3
  36. package/src/notifiers/zoomNotifier.ts +4 -3
  37. package/src/openApiCompat.ts +2 -1
  38. package/src/openApiEtag.ts +2 -2
  39. package/src/openApiValidator.ts +46 -46
  40. package/src/plugins.test.ts +130 -0
  41. package/src/plugins.ts +35 -0
  42. package/src/scriptRunner.ts +23 -27
  43. package/src/secretProviders.ts +27 -9
  44. package/src/types/consentForm.ts +6 -4
@@ -96,18 +96,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
96
96
  return (mod && mod.__esModule) ? mod : { "default": mod };
97
97
  };
98
98
  Object.defineProperty(exports, "__esModule", { value: true });
99
- exports.isOpenApiValidatorConfigured = isOpenApiValidatorConfigured;
100
- exports.configureOpenApiValidator = configureOpenApiValidator;
101
- exports.getOpenApiValidatorConfig = getOpenApiValidatorConfig;
102
- exports.resetOpenApiValidatorConfig = resetOpenApiValidatorConfig;
103
- exports.validateRequestBody = validateRequestBody;
104
- exports.validateQueryParams = validateQueryParams;
105
- exports.createValidator = createValidator;
106
- exports.validateResponseData = validateResponseData;
107
- exports.getSchemaFromModel = getSchemaFromModel;
108
- exports.validateModelRequestBody = validateModelRequestBody;
109
- exports.createModelValidators = createModelValidators;
110
- exports.buildQuerySchemaFromFields = buildQuerySchemaFromFields;
99
+ exports.buildQuerySchemaFromFields = exports.createModelValidators = exports.validateModelRequestBody = exports.getSchemaFromModel = exports.validateResponseData = exports.createValidator = exports.validateQueryParams = exports.validateRequestBody = exports.resetOpenApiValidatorConfig = exports.getOpenApiValidatorConfig = exports.configureOpenApiValidator = exports.isOpenApiValidatorConfigured = void 0;
111
100
  var ajv_1 = __importDefault(require("ajv"));
112
101
  var ajv_formats_1 = __importDefault(require("ajv-formats"));
113
102
  var mongoose_to_swagger_1 = __importDefault(require("mongoose-to-swagger"));
@@ -128,9 +117,10 @@ var globalConfig = {
128
117
  * Check whether `configureOpenApiValidator()` has been called.
129
118
  * Validation middleware is a no-op when this returns false.
130
119
  */
131
- function isOpenApiValidatorConfigured() {
120
+ var isOpenApiValidatorConfigured = function () {
132
121
  return isConfigured;
133
- }
122
+ };
123
+ exports.isOpenApiValidatorConfigured = isOpenApiValidatorConfigured;
134
124
  /**
135
125
  * Configure the global OpenAPI validator settings.
136
126
  * Calling this function activates validation — middleware that was previously
@@ -148,7 +138,7 @@ function isOpenApiValidatorConfigured() {
148
138
  * });
149
139
  * ```
150
140
  */
151
- function configureOpenApiValidator(config) {
141
+ var configureOpenApiValidator = function (config) {
152
142
  if (config === void 0) { config = {}; }
153
143
  isConfigured = true;
154
144
  globalConfig = __assign(__assign({}, globalConfig), config);
@@ -156,19 +146,21 @@ function configureOpenApiValidator(config) {
156
146
  ajvCache.clear();
157
147
  validatorCache.clear();
158
148
  logger_1.logger.debug("OpenAPI validator configured: ".concat(JSON.stringify(globalConfig)));
159
- }
149
+ };
150
+ exports.configureOpenApiValidator = configureOpenApiValidator;
160
151
  /**
161
152
  * Get the current global validator configuration.
162
153
  */
163
- function getOpenApiValidatorConfig() {
154
+ var getOpenApiValidatorConfig = function () {
164
155
  return __assign({}, globalConfig);
165
- }
156
+ };
157
+ exports.getOpenApiValidatorConfig = getOpenApiValidatorConfig;
166
158
  /**
167
159
  * Reset the global validator configuration to defaults.
168
160
  * Also resets `isConfigured` to false.
169
161
  * Useful for testing.
170
162
  */
171
- function resetOpenApiValidatorConfig() {
163
+ var resetOpenApiValidatorConfig = function () {
172
164
  isConfigured = false;
173
165
  globalConfig = {
174
166
  coerceTypes: true,
@@ -179,13 +171,14 @@ function resetOpenApiValidatorConfig() {
179
171
  };
180
172
  ajvCache.clear();
181
173
  validatorCache.clear();
182
- }
174
+ };
175
+ exports.resetOpenApiValidatorConfig = resetOpenApiValidatorConfig;
183
176
  // Lazy AJV instance cache keyed by coerceTypes + removeAdditional
184
177
  var ajvCache = new Map();
185
178
  /**
186
179
  * Get or create an AJV instance with the current config settings.
187
180
  */
188
- function getAjvInstance() {
181
+ var getAjvInstance = function () {
189
182
  var _a, _b, _c, _d;
190
183
  var key = "coerce:".concat((_a = globalConfig.coerceTypes) !== null && _a !== void 0 ? _a : true, ",remove:").concat((_b = globalConfig.removeAdditional) !== null && _b !== void 0 ? _b : true);
191
184
  var instance = ajvCache.get(key);
@@ -202,15 +195,15 @@ function getAjvInstance() {
202
195
  ajvCache.set(key, instance);
203
196
  }
204
197
  return instance;
205
- }
198
+ };
206
199
  // Cache compiled validators by schema hash + config key
207
200
  var validatorCache = new Map();
208
201
  /**
209
202
  * Generate a simple hash for a schema to use as a cache key.
210
203
  */
211
- function hashSchema(schema) {
204
+ var hashSchema = function (schema) {
212
205
  return JSON.stringify(schema);
213
- }
206
+ };
214
207
  var VALID_JSON_SCHEMA_TYPES = new Set([
215
208
  "string",
216
209
  "number",
@@ -229,7 +222,7 @@ var MONGOOSE_TYPE_MAP = {
229
222
  * Recursively replace non-standard mongoose-to-swagger types with valid JSON Schema types
230
223
  * so AJV can compile the schema.
231
224
  */
232
- function sanitizeSchemaForAjv(schema) {
225
+ var sanitizeSchemaForAjv = function (schema) {
233
226
  var e_1, _a;
234
227
  if (!schema || typeof schema !== "object") {
235
228
  return schema;
@@ -274,14 +267,14 @@ function sanitizeSchemaForAjv(schema) {
274
267
  result.additionalProperties = sanitizeSchemaForAjv(result.additionalProperties);
275
268
  }
276
269
  return result;
277
- }
270
+ };
278
271
  /**
279
272
  * Get or create a compiled validator for a schema.
280
273
  * Uses the current config so changes take effect on next call.
281
274
  * Sanitizes non-standard mongoose-to-swagger types before compilation.
282
275
  * Returns null if the schema still cannot be compiled after sanitization.
283
276
  */
284
- function getValidator(schema) {
277
+ var getValidator = function (schema) {
285
278
  var _a, _b;
286
279
  var ajv = getAjvInstance();
287
280
  var configKey = "coerce:".concat((_a = globalConfig.coerceTypes) !== null && _a !== void 0 ? _a : true, ",remove:").concat((_b = globalConfig.removeAdditional) !== null && _b !== void 0 ? _b : true);
@@ -301,11 +294,11 @@ function getValidator(schema) {
301
294
  validatorCache.set(hash, null);
302
295
  return null;
303
296
  }
304
- }
297
+ };
305
298
  /**
306
299
  * Format AJV errors into a human-readable string.
307
300
  */
308
- function formatValidationErrors(errors) {
301
+ var formatValidationErrors = function (errors) {
309
302
  return errors
310
303
  .map(function (err) {
311
304
  var path = err.instancePath || "/";
@@ -313,13 +306,13 @@ function formatValidationErrors(errors) {
313
306
  return "".concat(path, ": ").concat(message);
314
307
  })
315
308
  .join("; ");
316
- }
309
+ };
317
310
  /**
318
311
  * Convert OpenApiSchemaProperty to a full OpenApiSchema suitable for AJV.
319
312
  * Strips `required` from individual properties (OpenAPI-style) and moves it
320
313
  * to the schema-level `required` array (JSON Schema-style) for AJV compatibility.
321
314
  */
322
- function propertiesToSchema(properties, requiredFields) {
315
+ var propertiesToSchema = function (properties, requiredFields) {
323
316
  var e_2, _a;
324
317
  // Extract required fields from properties that have required: true
325
318
  var autoRequired = Object.entries(properties)
@@ -359,7 +352,7 @@ function propertiesToSchema(properties, requiredFields) {
359
352
  schema.additionalProperties = false;
360
353
  }
361
354
  return schema;
362
- }
355
+ };
363
356
  /**
364
357
  * Creates middleware that validates the request body against an OpenAPI schema.
365
358
  *
@@ -370,7 +363,7 @@ function propertiesToSchema(properties, requiredFields) {
370
363
  * @param options - Optional configuration for this validator
371
364
  * @returns Express middleware function
372
365
  */
373
- function validateRequestBody(schema, options) {
366
+ var validateRequestBody = function (schema, options) {
374
367
  var fullSchema = propertiesToSchema(schema, options === null || options === void 0 ? void 0 : options.required);
375
368
  return function (req, _res, next) {
376
369
  var _a, _b, _c;
@@ -447,7 +440,8 @@ function validateRequestBody(schema, options) {
447
440
  }
448
441
  next();
449
442
  };
450
- }
443
+ };
444
+ exports.validateRequestBody = validateRequestBody;
451
445
  /**
452
446
  * Creates middleware that validates query parameters against an OpenAPI schema.
453
447
  *
@@ -455,7 +449,7 @@ function validateRequestBody(schema, options) {
455
449
  * @param options - Optional configuration for this validator
456
450
  * @returns Express middleware function
457
451
  */
458
- function validateQueryParams(schema, options) {
452
+ var validateQueryParams = function (schema, options) {
459
453
  var fullSchema = propertiesToSchema(schema);
460
454
  return function (req, _res, next) {
461
455
  var _a, _b, _c, _d;
@@ -513,7 +507,8 @@ function validateQueryParams(schema, options) {
513
507
  }
514
508
  next();
515
509
  };
516
- }
510
+ };
511
+ exports.validateQueryParams = validateQueryParams;
517
512
  /**
518
513
  * Creates a combined validation middleware for both body and query parameters.
519
514
  *
@@ -531,12 +526,12 @@ function validateQueryParams(schema, options) {
531
526
  * ], handler);
532
527
  * ```
533
528
  */
534
- function createValidator(options) {
529
+ var createValidator = function (options) {
535
530
  var bodyValidator = options.body
536
- ? validateRequestBody(options.body, { enabled: options.enabled })
531
+ ? (0, exports.validateRequestBody)(options.body, { enabled: options.enabled })
537
532
  : null;
538
533
  var queryValidator = options.query
539
- ? validateQueryParams(options.query, { enabled: options.enabled })
534
+ ? (0, exports.validateQueryParams)(options.query, { enabled: options.enabled })
540
535
  : null;
541
536
  return function (req, res, next) {
542
537
  // Run body validation first
@@ -562,7 +557,8 @@ function createValidator(options) {
562
557
  next();
563
558
  }
564
559
  };
565
- }
560
+ };
561
+ exports.createValidator = createValidator;
566
562
  /**
567
563
  * Validates response data against a schema.
568
564
  * This is primarily for development/testing to ensure responses match documentation.
@@ -571,7 +567,7 @@ function createValidator(options) {
571
567
  * @param schema - The expected schema
572
568
  * @returns Object with valid flag and any errors
573
569
  */
574
- function validateResponseData(data, schema) {
570
+ var validateResponseData = function (data, schema) {
575
571
  if (!globalConfig.validateResponses) {
576
572
  return { valid: true };
577
573
  }
@@ -588,7 +584,8 @@ function validateResponseData(data, schema) {
588
584
  return { errors: validator.errors, valid: false };
589
585
  }
590
586
  return { valid: true };
591
- }
587
+ };
588
+ exports.validateResponseData = validateResponseData;
592
589
  var m2sOptions = {
593
590
  props: ["readOnly", "required", "enum", "default"],
594
591
  };
@@ -600,19 +597,20 @@ var m2sOptions = {
600
597
  * @param model - A Mongoose model
601
598
  * @returns Schema properties suitable for validation
602
599
  */
603
- function getSchemaFromModel(model) {
600
+ var getSchemaFromModel = function (model) {
604
601
  var modelSwagger = (0, mongoose_to_swagger_1.default)(model, m2sOptions);
605
602
  (0, populate_1.fixMixedFields)(model.schema, modelSwagger.properties);
606
603
  return modelSwagger.properties;
607
- }
604
+ };
605
+ exports.getSchemaFromModel = getSchemaFromModel;
608
606
  /**
609
607
  * Extract required field names from a Mongoose model's swagger schema.
610
608
  */
611
- function getRequiredFieldsFromModel(model) {
609
+ var getRequiredFieldsFromModel = function (model) {
612
610
  var _a;
613
611
  var modelSwagger = (0, mongoose_to_swagger_1.default)(model, m2sOptions);
614
612
  return (_a = modelSwagger.required) !== null && _a !== void 0 ? _a : [];
615
- }
613
+ };
616
614
  /**
617
615
  * Creates a request body validator middleware from a Mongoose model.
618
616
  * This is a convenience function that combines getSchemaFromModel and validateRequestBody.
@@ -621,9 +619,9 @@ function getRequiredFieldsFromModel(model) {
621
619
  * @param options - Optional configuration for the validator
622
620
  * @returns Express middleware function
623
621
  */
624
- function validateModelRequestBody(model, options) {
622
+ var validateModelRequestBody = function (model, options) {
625
623
  var _a, _b;
626
- var schema = getSchemaFromModel(model);
624
+ var schema = (0, exports.getSchemaFromModel)(model);
627
625
  var requiredFields = getRequiredFieldsFromModel(model);
628
626
  if ((_a = options === null || options === void 0 ? void 0 : options.excludeFields) === null || _a === void 0 ? void 0 : _a.length) {
629
627
  var excluded_1 = new Set(options.excludeFields);
@@ -633,8 +631,9 @@ function validateModelRequestBody(model, options) {
633
631
  }));
634
632
  requiredFields = requiredFields.filter(function (f) { return !excluded_1.has(f); });
635
633
  }
636
- return validateRequestBody(schema, __assign(__assign({}, options), { required: __spreadArray(__spreadArray([], __read(((_b = options === null || options === void 0 ? void 0 : options.required) !== null && _b !== void 0 ? _b : [])), false), __read(requiredFields), false) }));
637
- }
634
+ return (0, exports.validateRequestBody)(schema, __assign(__assign({}, options), { required: __spreadArray(__spreadArray([], __read(((_b = options === null || options === void 0 ? void 0 : options.required) !== null && _b !== void 0 ? _b : [])), false), __read(requiredFields), false) }));
635
+ };
636
+ exports.validateModelRequestBody = validateModelRequestBody;
638
637
  /**
639
638
  * Creates validation middleware for use with modelRouter.
640
639
  * Returns an object with middleware for each operation type.
@@ -643,21 +642,22 @@ function validateModelRequestBody(model, options) {
643
642
  * @param options - Configuration options
644
643
  * @returns Object with create and update validation middleware
645
644
  */
646
- function createModelValidators(model, options) {
647
- var schema = getSchemaFromModel(model);
645
+ var createModelValidators = function (model, options) {
646
+ var schema = (0, exports.getSchemaFromModel)(model);
648
647
  return {
649
- create: validateRequestBody(schema, {
648
+ create: (0, exports.validateRequestBody)(schema, {
650
649
  enabled: options === null || options === void 0 ? void 0 : options.validateCreate,
651
650
  onAdditionalPropertiesRemoved: options === null || options === void 0 ? void 0 : options.onAdditionalPropertiesRemoved,
652
651
  onError: options === null || options === void 0 ? void 0 : options.onError,
653
652
  }),
654
- update: validateRequestBody(schema, {
653
+ update: (0, exports.validateRequestBody)(schema, {
655
654
  enabled: options === null || options === void 0 ? void 0 : options.validateUpdate,
656
655
  onAdditionalPropertiesRemoved: options === null || options === void 0 ? void 0 : options.onAdditionalPropertiesRemoved,
657
656
  onError: options === null || options === void 0 ? void 0 : options.onError,
658
657
  }),
659
658
  };
660
- }
659
+ };
660
+ exports.createModelValidators = createModelValidators;
661
661
  /**
662
662
  * Build a query parameter schema from a model's Mongoose schema and queryFields array.
663
663
  * Always includes pagination parameters (limit, page, sort).
@@ -666,10 +666,10 @@ function createModelValidators(model, options) {
666
666
  * @param queryFields - Array of field names allowed for querying
667
667
  * @returns Schema properties suitable for query validation
668
668
  */
669
- function buildQuerySchemaFromFields(model, queryFields) {
669
+ var buildQuerySchemaFromFields = function (model, queryFields) {
670
670
  var e_3, _a;
671
671
  if (queryFields === void 0) { queryFields = []; }
672
- var modelSchema = getSchemaFromModel(model);
672
+ var modelSchema = (0, exports.getSchemaFromModel)(model);
673
673
  var querySchema = {
674
674
  limit: { type: "number" },
675
675
  page: { type: "number" },
@@ -697,4 +697,5 @@ function buildQuerySchemaFromFields(model, queryFields) {
697
697
  finally { if (e_3) throw e_3.error; }
698
698
  }
699
699
  return querySchema;
700
- }
700
+ };
701
+ exports.buildQuerySchemaFromFields = buildQuerySchemaFromFields;
package/dist/plugins.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type Document, type Schema, SchemaType, type SchemaTypeOptions } from "mongoose";
1
+ import mongoose, { type Document, type FilterQuery, type Schema, SchemaType, type SchemaTypeOptions } from "mongoose";
2
2
  import { type APIErrorConstructor } from "./errors";
3
3
  export interface BaseUser {
4
4
  admin: boolean;
@@ -31,6 +31,17 @@ export declare const firebaseJWTPlugin: (schema: Schema) => void;
31
31
  * @param schema Mongoose Schema
32
32
  */
33
33
  export declare const findOneOrNone: <T>(schema: Schema<T>) => void;
34
+ /**
35
+ * Helper that performs a `findOneOrNone` lookup against any Mongoose model. Returns the matching
36
+ * document, `null` if none match, or throws if more than one matches. If the model's schema has
37
+ * the {@link findOneOrNone} plugin applied, the plugin static is used; otherwise the lookup is
38
+ * performed directly via `model.find(...)`. Prefer this helper from framework code where the
39
+ * consumer's model may or may not have the plugin installed.
40
+ * @param model Mongoose Model
41
+ * @param query Mongoose query object
42
+ * @param errorArgs Optional overrides for the thrown {@link APIError} when multiple match
43
+ */
44
+ export declare const findOneOrNoneFor: <T>(model: mongoose.Model<T>, query: FilterQuery<T>, errorArgs?: Partial<APIErrorConstructor>) => Promise<(Document & T) | null>;
34
45
  /**
35
46
  * This adds a static method `Model.findExactlyOne` to the schema. This or findOneOrNone should replace `Model.findOne`
36
47
  * in most instances.
package/dist/plugins.js CHANGED
@@ -95,7 +95,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
95
95
  }
96
96
  };
97
97
  Object.defineProperty(exports, "__esModule", { value: true });
98
- exports.DateOnly = exports.upsertPlugin = exports.findExactlyOne = exports.findOneOrNone = exports.firebaseJWTPlugin = exports.createdUpdatedPlugin = exports.isDisabledPlugin = exports.isDeletedPlugin = exports.baseUserPlugin = void 0;
98
+ exports.DateOnly = exports.upsertPlugin = exports.findExactlyOne = exports.findOneOrNoneFor = exports.findOneOrNone = exports.firebaseJWTPlugin = exports.createdUpdatedPlugin = exports.isDisabledPlugin = exports.isDeletedPlugin = exports.baseUserPlugin = void 0;
99
99
  var luxon_1 = require("luxon");
100
100
  var mongoose_1 = __importStar(require("mongoose"));
101
101
  var errors_1 = require("./errors");
@@ -199,6 +199,39 @@ var findOneOrNone = function (schema) {
199
199
  };
200
200
  };
201
201
  exports.findOneOrNone = findOneOrNone;
202
+ /**
203
+ * Helper that performs a `findOneOrNone` lookup against any Mongoose model. Returns the matching
204
+ * document, `null` if none match, or throws if more than one matches. If the model's schema has
205
+ * the {@link findOneOrNone} plugin applied, the plugin static is used; otherwise the lookup is
206
+ * performed directly via `model.find(...)`. Prefer this helper from framework code where the
207
+ * consumer's model may or may not have the plugin installed.
208
+ * @param model Mongoose Model
209
+ * @param query Mongoose query object
210
+ * @param errorArgs Optional overrides for the thrown {@link APIError} when multiple match
211
+ */
212
+ var findOneOrNoneFor = function (model, query, errorArgs) { return __awaiter(void 0, void 0, void 0, function () {
213
+ var withStatic, results;
214
+ return __generator(this, function (_a) {
215
+ switch (_a.label) {
216
+ case 0:
217
+ withStatic = model;
218
+ if (typeof withStatic.findOneOrNone === "function") {
219
+ return [2 /*return*/, withStatic.findOneOrNone(query, errorArgs)];
220
+ }
221
+ return [4 /*yield*/, model.find(query)];
222
+ case 1:
223
+ results = _a.sent();
224
+ if (results.length === 0) {
225
+ return [2 /*return*/, null];
226
+ }
227
+ if (results.length > 1) {
228
+ throw new errors_1.APIError(__assign({ detail: "query: ".concat(JSON.stringify(query)), status: 500, title: "".concat(model.modelName, ".findOne query returned multiple documents") }, errorArgs));
229
+ }
230
+ return [2 /*return*/, results[0]];
231
+ }
232
+ });
233
+ }); };
234
+ exports.findOneOrNoneFor = findOneOrNoneFor;
202
235
  /**
203
236
  * This adds a static method `Model.findExactlyOne` to the schema. This or findOneOrNone should replace `Model.findOne`
204
237
  * in most instances.
@@ -74,6 +74,28 @@ stuffSchema.plugin(plugins_1.findExactlyOne);
74
74
  stuffSchema.plugin(plugins_1.upsertPlugin);
75
75
  stuffSchema.plugin(plugins_1.createdUpdatedPlugin);
76
76
  var StuffModel = (0, mongoose_1.model)("Stuff", stuffSchema);
77
+ (0, bun_test_1.describe)("baseUserPlugin", function () {
78
+ (0, bun_test_1.it)("adds admin and email fields to the schema", function () {
79
+ var testSchema = new mongoose_1.Schema({});
80
+ // biome-ignore lint/suspicious/noExplicitAny: test schema
81
+ (0, plugins_1.baseUserPlugin)(testSchema);
82
+ var adminPath = testSchema.path("admin");
83
+ (0, bun_test_1.expect)(adminPath).toBeDefined();
84
+ (0, bun_test_1.expect)(adminPath.options.default).toBe(false);
85
+ var emailPath = testSchema.path("email");
86
+ (0, bun_test_1.expect)(emailPath).toBeDefined();
87
+ (0, bun_test_1.expect)(emailPath.options.index).toBe(true);
88
+ });
89
+ });
90
+ (0, bun_test_1.describe)("firebaseJWTPlugin", function () {
91
+ (0, bun_test_1.it)("adds firebaseId field to the schema", function () {
92
+ var testSchema = new mongoose_1.Schema({});
93
+ (0, plugins_1.firebaseJWTPlugin)(testSchema);
94
+ var firebaseIdPath = testSchema.path("firebaseId");
95
+ (0, bun_test_1.expect)(firebaseIdPath).toBeDefined();
96
+ (0, bun_test_1.expect)(firebaseIdPath.options.index).toBe(true);
97
+ });
98
+ });
77
99
  (0, bun_test_1.describe)("createdUpdate", function () {
78
100
  (0, bun_test_1.it)("sets created and updated on save", function () { return __awaiter(void 0, void 0, void 0, function () {
79
101
  var stuff;
@@ -256,6 +278,188 @@ var StuffModel = (0, mongoose_1.model)("Stuff", stuffSchema);
256
278
  });
257
279
  }); });
258
280
  });
281
+ var bareThingSchema = new mongoose_1.Schema({
282
+ name: { description: "The name of the bare item", type: String },
283
+ ownerId: { description: "The owner of the bare item", type: String },
284
+ });
285
+ var BareThingModel = (0, mongoose_1.model)("BareThing", bareThingSchema);
286
+ (0, bun_test_1.describe)("findOneOrNoneFor", function () {
287
+ (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
288
+ return __generator(this, function (_a) {
289
+ switch (_a.label) {
290
+ case 0: return [4 /*yield*/, StuffModel.deleteMany({})];
291
+ case 1:
292
+ _a.sent();
293
+ return [4 /*yield*/, BareThingModel.deleteMany({})];
294
+ case 2:
295
+ _a.sent();
296
+ return [4 /*yield*/, (0, tests_1.setupDb)()];
297
+ case 3:
298
+ _a.sent();
299
+ return [2 /*return*/];
300
+ }
301
+ });
302
+ }); });
303
+ (0, bun_test_1.describe)("when the schema has the findOneOrNone plugin", function () {
304
+ var things;
305
+ (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
306
+ var _a;
307
+ return __generator(this, function (_b) {
308
+ switch (_b.label) {
309
+ case 0: return [4 /*yield*/, Promise.all([
310
+ StuffModel.create({ name: "Things", ownerId: "123" }),
311
+ StuffModel.create({ name: "StuffNThings", ownerId: "123" }),
312
+ ])];
313
+ case 1:
314
+ _a = __read.apply(void 0, [_b.sent(), 1]), things = _a[0];
315
+ return [2 /*return*/];
316
+ }
317
+ });
318
+ }); });
319
+ (0, bun_test_1.it)("returns null with no matches", function () { return __awaiter(void 0, void 0, void 0, function () {
320
+ var result;
321
+ return __generator(this, function (_a) {
322
+ switch (_a.label) {
323
+ case 0: return [4 /*yield*/, (0, plugins_1.findOneOrNoneFor)(StuffModel, { name: "OtherStuff" })];
324
+ case 1:
325
+ result = _a.sent();
326
+ (0, bun_test_1.expect)(result).toBeNull();
327
+ return [2 /*return*/];
328
+ }
329
+ });
330
+ }); });
331
+ (0, bun_test_1.it)("returns a single match", function () { return __awaiter(void 0, void 0, void 0, function () {
332
+ var result;
333
+ return __generator(this, function (_a) {
334
+ switch (_a.label) {
335
+ case 0: return [4 /*yield*/, (0, plugins_1.findOneOrNoneFor)(StuffModel, { name: "Things" })];
336
+ case 1:
337
+ result = _a.sent();
338
+ (0, bun_test_1.expect)(result).not.toBeNull();
339
+ (0, bun_test_1.expect)(result === null || result === void 0 ? void 0 : result._id.toString()).toBe(things._id.toString());
340
+ return [2 /*return*/];
341
+ }
342
+ });
343
+ }); });
344
+ (0, bun_test_1.it)("throws when multiple documents match", function () { return __awaiter(void 0, void 0, void 0, function () {
345
+ var fn;
346
+ return __generator(this, function (_a) {
347
+ switch (_a.label) {
348
+ case 0:
349
+ fn = function () { return (0, plugins_1.findOneOrNoneFor)(StuffModel, { ownerId: "123" }); };
350
+ return [4 /*yield*/, (0, bun_test_1.expect)(fn()).rejects.toThrow(/Stuff\.findOne query returned multiple documents/)];
351
+ case 1:
352
+ _a.sent();
353
+ return [2 /*return*/];
354
+ }
355
+ });
356
+ }); });
357
+ (0, bun_test_1.it)("forwards errorArgs to the thrown APIError", function () { return __awaiter(void 0, void 0, void 0, function () {
358
+ var fn, error_2;
359
+ return __generator(this, function (_a) {
360
+ switch (_a.label) {
361
+ case 0:
362
+ fn = function () {
363
+ return (0, plugins_1.findOneOrNoneFor)(StuffModel, { ownerId: "123" }, { status: 400, title: "Oh no!" });
364
+ };
365
+ _a.label = 1;
366
+ case 1:
367
+ _a.trys.push([1, 3, , 4]);
368
+ return [4 /*yield*/, fn()];
369
+ case 2:
370
+ _a.sent();
371
+ throw new Error("Expected promise to reject");
372
+ case 3:
373
+ error_2 = _a.sent();
374
+ (0, bun_test_1.expect)(error_2.title).toBe("Oh no!");
375
+ (0, bun_test_1.expect)(error_2.status).toBe(400);
376
+ return [3 /*break*/, 4];
377
+ case 4: return [2 /*return*/];
378
+ }
379
+ });
380
+ }); });
381
+ });
382
+ (0, bun_test_1.describe)("when the schema does NOT have the findOneOrNone plugin", function () {
383
+ var bareThings;
384
+ (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
385
+ var _a;
386
+ return __generator(this, function (_b) {
387
+ switch (_b.label) {
388
+ case 0: return [4 /*yield*/, Promise.all([
389
+ BareThingModel.create({ name: "Things", ownerId: "123" }),
390
+ BareThingModel.create({ name: "StuffNThings", ownerId: "123" }),
391
+ ])];
392
+ case 1:
393
+ _a = __read.apply(void 0, [_b.sent(), 1]), bareThings = _a[0];
394
+ return [2 /*return*/];
395
+ }
396
+ });
397
+ }); });
398
+ (0, bun_test_1.it)("returns null with no matches", function () { return __awaiter(void 0, void 0, void 0, function () {
399
+ var result;
400
+ return __generator(this, function (_a) {
401
+ switch (_a.label) {
402
+ case 0: return [4 /*yield*/, (0, plugins_1.findOneOrNoneFor)(BareThingModel, { name: "OtherStuff" })];
403
+ case 1:
404
+ result = _a.sent();
405
+ (0, bun_test_1.expect)(result).toBeNull();
406
+ return [2 /*return*/];
407
+ }
408
+ });
409
+ }); });
410
+ (0, bun_test_1.it)("returns a single match", function () { return __awaiter(void 0, void 0, void 0, function () {
411
+ var result;
412
+ var _a, _b;
413
+ return __generator(this, function (_c) {
414
+ switch (_c.label) {
415
+ case 0: return [4 /*yield*/, (0, plugins_1.findOneOrNoneFor)(BareThingModel, { name: "Things" })];
416
+ case 1:
417
+ result = _c.sent();
418
+ (0, bun_test_1.expect)(result).not.toBeNull();
419
+ (0, bun_test_1.expect)((_a = result === null || result === void 0 ? void 0 : result._id) === null || _a === void 0 ? void 0 : _a.toString()).toBe((_b = bareThings._id) === null || _b === void 0 ? void 0 : _b.toString());
420
+ return [2 /*return*/];
421
+ }
422
+ });
423
+ }); });
424
+ (0, bun_test_1.it)("throws when multiple documents match", function () { return __awaiter(void 0, void 0, void 0, function () {
425
+ var fn;
426
+ return __generator(this, function (_a) {
427
+ switch (_a.label) {
428
+ case 0:
429
+ fn = function () { return (0, plugins_1.findOneOrNoneFor)(BareThingModel, { ownerId: "123" }); };
430
+ return [4 /*yield*/, (0, bun_test_1.expect)(fn()).rejects.toThrow(/BareThing\.findOne query returned multiple documents/)];
431
+ case 1:
432
+ _a.sent();
433
+ return [2 /*return*/];
434
+ }
435
+ });
436
+ }); });
437
+ (0, bun_test_1.it)("forwards errorArgs to the thrown APIError", function () { return __awaiter(void 0, void 0, void 0, function () {
438
+ var fn, error_3;
439
+ return __generator(this, function (_a) {
440
+ switch (_a.label) {
441
+ case 0:
442
+ fn = function () {
443
+ return (0, plugins_1.findOneOrNoneFor)(BareThingModel, { ownerId: "123" }, { status: 400, title: "Oh no!" });
444
+ };
445
+ _a.label = 1;
446
+ case 1:
447
+ _a.trys.push([1, 3, , 4]);
448
+ return [4 /*yield*/, fn()];
449
+ case 2:
450
+ _a.sent();
451
+ throw new Error("Expected promise to reject");
452
+ case 3:
453
+ error_3 = _a.sent();
454
+ (0, bun_test_1.expect)(error_3.title).toBe("Oh no!");
455
+ (0, bun_test_1.expect)(error_3.status).toBe(400);
456
+ return [3 /*break*/, 4];
457
+ case 4: return [2 /*return*/];
458
+ }
459
+ });
460
+ }); });
461
+ });
462
+ });
259
463
  (0, bun_test_1.describe)("findExactlyOne", function () {
260
464
  var things;
261
465
  (0, bun_test_1.beforeEach)(function () { return __awaiter(void 0, void 0, void 0, function () {
@@ -323,7 +527,7 @@ var StuffModel = (0, mongoose_1.model)("Stuff", stuffSchema);
323
527
  });
324
528
  }); });
325
529
  (0, bun_test_1.it)("throws custom error with two matches.", function () { return __awaiter(void 0, void 0, void 0, function () {
326
- var fn, error_2;
530
+ var fn, error_4;
327
531
  return __generator(this, function (_a) {
328
532
  switch (_a.label) {
329
533
  case 0:
@@ -337,11 +541,11 @@ var StuffModel = (0, mongoose_1.model)("Stuff", stuffSchema);
337
541
  // If the promise doesn't reject, the test should fail
338
542
  throw new Error("Expected promise to reject");
339
543
  case 3:
340
- error_2 = _a.sent();
544
+ error_4 = _a.sent();
341
545
  // Check if the error has title and status properties
342
- (0, bun_test_1.expect)(error_2.title).toBe("Oh no!");
343
- (0, bun_test_1.expect)(error_2.status).toBe(400);
344
- (0, bun_test_1.expect)(error_2.detail).toBe('query: {"ownerId":"123"}');
546
+ (0, bun_test_1.expect)(error_4.title).toBe("Oh no!");
547
+ (0, bun_test_1.expect)(error_4.status).toBe(400);
548
+ (0, bun_test_1.expect)(error_4.detail).toBe('query: {"ownerId":"123"}');
345
549
  return [3 /*break*/, 4];
346
550
  case 4: return [2 /*return*/];
347
551
  }
@@ -504,7 +708,7 @@ var StuffModel = (0, mongoose_1.model)("Stuff", stuffSchema);
504
708
  });
505
709
  (0, bun_test_1.describe)("DateOnly", function () {
506
710
  (0, bun_test_1.it)("throws error with invalid date", function () { return __awaiter(void 0, void 0, void 0, function () {
507
- var error_3;
711
+ var error_5;
508
712
  return __generator(this, function (_a) {
509
713
  switch (_a.label) {
510
714
  case 0:
@@ -518,8 +722,8 @@ var StuffModel = (0, mongoose_1.model)("Stuff", stuffSchema);
518
722
  _a.sent();
519
723
  return [3 /*break*/, 3];
520
724
  case 2:
521
- error_3 = _a.sent();
522
- (0, bun_test_1.expect)(error_3.message).toMatch(/Cast to DateOnly failed/);
725
+ error_5 = _a.sent();
726
+ (0, bun_test_1.expect)(error_5.message).toMatch(/Cast to DateOnly failed/);
523
727
  return [2 /*return*/];
524
728
  case 3: throw new Error("Expected error was not thrown");
525
729
  }