@terreno/api 0.13.2 → 0.14.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.
Files changed (175) hide show
  1. package/dist/__tests__/versionCheckPlugin.test.js +53 -3
  2. package/dist/api.arrayOperations.test.js +1 -0
  3. package/dist/api.asyncHandler.test.d.ts +1 -0
  4. package/dist/api.asyncHandler.test.js +236 -0
  5. package/dist/api.d.ts +15 -4
  6. package/dist/api.errors.test.js +1 -0
  7. package/dist/api.hooks.test.js +1 -0
  8. package/dist/api.js +153 -104
  9. package/dist/api.query.test.js +1 -0
  10. package/dist/api.test.js +174 -0
  11. package/dist/auth.d.ts +10 -5
  12. package/dist/auth.js +163 -90
  13. package/dist/auth.test.js +159 -0
  14. package/dist/betterAuthApp.test.js +1 -0
  15. package/dist/betterAuthSetup.d.ts +5 -6
  16. package/dist/betterAuthSetup.js +17 -14
  17. package/dist/betterAuthSetup.test.js +1 -0
  18. package/dist/config.d.ts +48 -0
  19. package/dist/config.js +248 -0
  20. package/dist/config.test.d.ts +1 -0
  21. package/dist/config.test.js +328 -0
  22. package/dist/configuration.test.js +1 -0
  23. package/dist/configurationApp.d.ts +1 -1
  24. package/dist/configurationApp.js +17 -13
  25. package/dist/configurationPlugin.test.js +1 -0
  26. package/dist/consentApp.test.js +1 -0
  27. package/dist/envConfigurationPlugin.d.ts +2 -0
  28. package/dist/envConfigurationPlugin.js +173 -0
  29. package/dist/envConfigurationPlugin.test.d.ts +1 -0
  30. package/dist/envConfigurationPlugin.test.js +322 -0
  31. package/dist/errors.d.ts +18 -7
  32. package/dist/errors.js +106 -10
  33. package/dist/errors.test.js +16 -1
  34. package/dist/example.js +16 -7
  35. package/dist/expressServer.d.ts +10 -9
  36. package/dist/expressServer.js +62 -53
  37. package/dist/expressServer.test.js +53 -2
  38. package/dist/githubAuth.d.ts +2 -1
  39. package/dist/githubAuth.js +41 -26
  40. package/dist/githubAuth.test.js +1 -0
  41. package/dist/index.d.ts +4 -0
  42. package/dist/index.js +4 -0
  43. package/dist/logger.d.ts +1 -1
  44. package/dist/logger.js +42 -20
  45. package/dist/models/versionConfig.d.ts +2 -0
  46. package/dist/models/versionConfig.js +8 -0
  47. package/dist/notifiers/googleChatNotifier.js +14 -16
  48. package/dist/notifiers/googleChatNotifier.test.js +1 -0
  49. package/dist/notifiers/slackNotifier.js +16 -14
  50. package/dist/notifiers/slackNotifier.test.js +41 -3
  51. package/dist/notifiers/zoomNotifier.js +7 -10
  52. package/dist/notifiers/zoomNotifier.test.js +1 -0
  53. package/dist/openApi.d.ts +1 -1
  54. package/dist/openApi.test.js +1 -0
  55. package/dist/openApiBuilder.d.ts +39 -6
  56. package/dist/openApiBuilder.js +1 -31
  57. package/dist/openApiBuilder.test.js +1 -0
  58. package/dist/openApiValidator.js +1 -0
  59. package/dist/openApiValidator.test.js +65 -0
  60. package/dist/permissions.d.ts +4 -4
  61. package/dist/permissions.js +67 -65
  62. package/dist/permissions.middleware.test.js +1 -0
  63. package/dist/permissions.test.js +1 -0
  64. package/dist/plugins.d.ts +5 -5
  65. package/dist/plugins.js +18 -9
  66. package/dist/plugins.test.js +1 -1
  67. package/dist/populate.d.ts +15 -8
  68. package/dist/populate.js +23 -24
  69. package/dist/populate.test.js +1 -0
  70. package/dist/realtime/changeStreamWatcher.d.ts +73 -0
  71. package/dist/realtime/changeStreamWatcher.js +720 -0
  72. package/dist/realtime/index.d.ts +6 -0
  73. package/dist/realtime/index.js +27 -0
  74. package/dist/realtime/queryMatcher.d.ts +14 -0
  75. package/dist/realtime/queryMatcher.js +250 -0
  76. package/dist/realtime/queryStore.d.ts +37 -0
  77. package/dist/realtime/queryStore.js +195 -0
  78. package/dist/realtime/realtime.test.d.ts +10 -0
  79. package/dist/realtime/realtime.test.js +2158 -0
  80. package/dist/realtime/realtimeApp.d.ts +93 -0
  81. package/dist/realtime/realtimeApp.js +560 -0
  82. package/dist/realtime/registry.d.ts +40 -0
  83. package/dist/realtime/registry.js +38 -0
  84. package/dist/realtime/socketUser.d.ts +10 -0
  85. package/dist/realtime/socketUser.js +17 -0
  86. package/dist/realtime/types.d.ts +100 -0
  87. package/dist/realtime/types.js +2 -0
  88. package/dist/requestContext.d.ts +37 -0
  89. package/dist/requestContext.js +344 -0
  90. package/dist/requestContext.test.d.ts +1 -0
  91. package/dist/requestContext.test.js +241 -0
  92. package/dist/terrenoApp.d.ts +8 -0
  93. package/dist/terrenoApp.js +50 -13
  94. package/dist/terrenoApp.test.js +194 -21
  95. package/dist/terrenoPlugin.d.ts +11 -0
  96. package/dist/tests/bunSetup.js +1 -0
  97. package/dist/tests.js +1 -1
  98. package/dist/transformers.d.ts +2 -2
  99. package/dist/transformers.js +5 -3
  100. package/dist/transformers.test.js +90 -0
  101. package/dist/types/consentResponse.d.ts +6 -3
  102. package/dist/versionCheckPlugin.d.ts +2 -0
  103. package/dist/versionCheckPlugin.js +18 -12
  104. package/package.json +4 -2
  105. package/src/__tests__/versionCheckPlugin.test.ts +37 -3
  106. package/src/api.arrayOperations.test.ts +1 -0
  107. package/src/api.asyncHandler.test.ts +177 -0
  108. package/src/api.errors.test.ts +1 -0
  109. package/src/api.hooks.test.ts +1 -0
  110. package/src/api.query.test.ts +1 -0
  111. package/src/api.test.ts +132 -0
  112. package/src/api.ts +199 -84
  113. package/src/auth.test.ts +160 -0
  114. package/src/auth.ts +120 -50
  115. package/src/betterAuthApp.test.ts +1 -0
  116. package/src/betterAuthSetup.test.ts +1 -0
  117. package/src/betterAuthSetup.ts +46 -19
  118. package/src/config.test.ts +255 -0
  119. package/src/config.ts +206 -0
  120. package/src/configuration.test.ts +1 -0
  121. package/src/configurationApp.ts +59 -24
  122. package/src/configurationPlugin.test.ts +1 -0
  123. package/src/consentApp.test.ts +1 -0
  124. package/src/envConfigurationPlugin.test.ts +143 -0
  125. package/src/envConfigurationPlugin.ts +100 -0
  126. package/src/errors.test.ts +19 -1
  127. package/src/errors.ts +94 -20
  128. package/src/example.ts +46 -21
  129. package/src/express.d.ts +18 -1
  130. package/src/expressServer.test.ts +50 -2
  131. package/src/expressServer.ts +80 -50
  132. package/src/githubAuth.test.ts +1 -0
  133. package/src/githubAuth.ts +59 -38
  134. package/src/index.ts +4 -0
  135. package/src/logger.ts +47 -17
  136. package/src/models/versionConfig.ts +13 -2
  137. package/src/notifiers/googleChatNotifier.test.ts +1 -0
  138. package/src/notifiers/googleChatNotifier.ts +7 -9
  139. package/src/notifiers/slackNotifier.test.ts +29 -3
  140. package/src/notifiers/slackNotifier.ts +9 -7
  141. package/src/notifiers/zoomNotifier.test.ts +1 -0
  142. package/src/notifiers/zoomNotifier.ts +8 -11
  143. package/src/openApi.test.ts +1 -0
  144. package/src/openApi.ts +4 -4
  145. package/src/openApiBuilder.test.ts +1 -0
  146. package/src/openApiBuilder.ts +14 -11
  147. package/src/openApiValidator.test.ts +59 -0
  148. package/src/openApiValidator.ts +3 -2
  149. package/src/permissions.middleware.test.ts +1 -0
  150. package/src/permissions.test.ts +1 -0
  151. package/src/permissions.ts +30 -25
  152. package/src/plugins.test.ts +1 -1
  153. package/src/plugins.ts +21 -14
  154. package/src/populate.test.ts +1 -0
  155. package/src/populate.ts +44 -36
  156. package/src/realtime/changeStreamWatcher.ts +568 -0
  157. package/src/realtime/index.ts +34 -0
  158. package/src/realtime/queryMatcher.ts +179 -0
  159. package/src/realtime/queryStore.ts +132 -0
  160. package/src/realtime/realtime.test.ts +1755 -0
  161. package/src/realtime/realtimeApp.ts +478 -0
  162. package/src/realtime/registry.ts +64 -0
  163. package/src/realtime/socketUser.ts +25 -0
  164. package/src/realtime/types.ts +112 -0
  165. package/src/requestContext.test.ts +196 -0
  166. package/src/requestContext.ts +368 -0
  167. package/src/terrenoApp.test.ts +137 -11
  168. package/src/terrenoApp.ts +64 -17
  169. package/src/terrenoPlugin.ts +12 -0
  170. package/src/tests/bunSetup.ts +1 -0
  171. package/src/tests.ts +7 -2
  172. package/src/transformers.test.ts +70 -2
  173. package/src/transformers.ts +15 -7
  174. package/src/types/consentResponse.ts +8 -10
  175. package/src/versionCheckPlugin.ts +15 -7
package/src/populate.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import isArray from "lodash/isArray";
2
- import type {Document} from "mongoose";
2
+ import type {Document, Schema} from "mongoose";
3
3
  import m2s from "mongoose-to-swagger";
4
4
 
5
5
  import {APIError} from "./errors";
@@ -8,7 +8,19 @@ const m2sOptions = {
8
8
  props: ["readOnly", "required", "enum", "default"],
9
9
  };
10
10
 
11
- export type PopulatePath = {
11
+ interface OpenApiSchemaNode {
12
+ description?: string;
13
+ items?: OpenApiSchemaNode;
14
+ properties?: Record<string, OpenApiSchemaNode>;
15
+ type?: string;
16
+ }
17
+
18
+ interface SchemaPathInfo {
19
+ instance: string;
20
+ schema?: Schema;
21
+ }
22
+
23
+ export interface PopulatePath {
12
24
  // Mongoose style path population.
13
25
  // "ownerId" // populates the User that matches `ownerId`
14
26
  // "ownerId.organizationId" Nested. Populates the User that matches `ownerId`, as well as their organization.
@@ -17,28 +29,25 @@ export type PopulatePath = {
17
29
  // If not provided and path is provided, will use the path and optionally fields to
18
30
  // automatically generate the types. If only generatePathFields is provided, the type will be
19
31
  // any.
20
- openApiComponent?: any;
32
+ openApiComponent?: string;
21
33
  // An array of strings to filter on the populated objects, following Mongoose's select
22
34
  // rules. If each field starts a preceding "-", will act as a block list and only remove those
23
35
  // fields. If each field does not start with a "-", will act as an allow list and only
24
36
  // return those fields.
25
37
  fields?: string[];
26
- };
38
+ }
27
39
 
28
- // This function filters an object to only include specified keys.
29
- // It supports nested keys using dot notation (e.g., 'user.name').
30
- // If no keys are provided, it returns the original object.
31
- // The function recursively traverses the object structure to handle nested properties.
32
- const filterKeys = (obj: Record<string, any>, keysToKeep?: string[]): Record<string, any> => {
40
+ // Keeps only the specified dot-notation keys from an object.
41
+ const filterKeys = (obj: Record<string, unknown>, keysToKeep?: string[]): Record<string, unknown> => {
33
42
  if (!keysToKeep) {
34
43
  return obj;
35
44
  }
36
45
 
37
- const result: Record<string, any> = {};
46
+ const result: Record<string, unknown> = {};
38
47
 
39
48
  const filterNestedKeys = (
40
- currentObj: Record<string, any>,
41
- currentResult: Record<string, any>,
49
+ currentObj: Record<string, unknown>,
50
+ currentResult: Record<string, unknown>,
42
51
  remainingKeys: string[]
43
52
  ) => {
44
53
  const currentKey = remainingKeys[0];
@@ -52,7 +61,7 @@ const filterKeys = (obj: Record<string, any>, keysToKeep?: string[]): Record<str
52
61
  if (!currentResult[firstKey]) {
53
62
  currentResult[firstKey] = {};
54
63
  }
55
- filterNestedKeys(currentObj[firstKey], currentResult[firstKey], [
64
+ filterNestedKeys(currentObj[firstKey] as Record<string, unknown>, currentResult[firstKey] as Record<string, unknown>, [
56
65
  rest.join("."),
57
66
  ...remainingKeys.slice(1),
58
67
  ]);
@@ -73,7 +82,7 @@ const filterKeys = (obj: Record<string, any>, keysToKeep?: string[]): Record<str
73
82
 
74
83
  // Helper function to get the path in the OpenAPI schema, so we can swap out the type for the
75
84
  // populated model component or generated type.
76
- function getPathInSchema(schema: any, path: string): string {
85
+ const getPathInSchema = (schema: OpenApiSchemaNode, path: string): string => {
77
86
  const keys = path.split(".");
78
87
  let currentSchema = schema;
79
88
  let fullPath = "";
@@ -94,52 +103,50 @@ function getPathInSchema(schema: any, path: string): string {
94
103
  // If we're at the last key and it's an array, we don't need to add anything
95
104
  break;
96
105
  } else {
97
- throw new Error(`Path ${path} not found in schema at key ${key}`);
106
+ throw new APIError({status: 500, title: `Path ${path} not found in schema at key ${key}`});
98
107
  }
99
108
  }
100
109
 
101
110
  return fullPath;
102
- }
111
+ };
103
112
 
104
- // Replaces populated properties with the populated schema.
105
- // Recursively walks a Mongoose schema and fixes any Mixed fields in the
106
- // OpenAPI properties so they use an empty schema (accepts any type) instead
107
- // of the `{type: "object", properties: {}}` that mongoose-to-swagger emits.
108
- export const fixMixedFields = (schema: any, properties: Record<string, any>): void => {
113
+ // Corrects Mixed-type fields in OpenAPI properties so they accept any value.
114
+ export const fixMixedFields = (schema: Schema | null, properties: Record<string, OpenApiSchemaNode> | Record<string, unknown> | null): void => {
109
115
  if (!properties || !schema) {
110
116
  return;
111
117
  }
112
118
 
113
- for (const key of Object.keys(properties)) {
114
- const schemaPath = schema.path(key);
119
+ const props = properties as Record<string, OpenApiSchemaNode>;
120
+ for (const key of Object.keys(props)) {
121
+ const schemaPath = schema.path(key) as unknown as SchemaPathInfo | undefined;
115
122
  if (!schemaPath) {
116
123
  continue;
117
124
  }
118
125
 
119
126
  // Direct Mixed field
120
127
  if (schemaPath.instance === "Mixed") {
121
- properties[key] = {description: properties[key]?.description};
128
+ props[key] = {description: props[key]?.description};
122
129
  continue;
123
130
  }
124
131
 
125
132
  // Array of sub-documents — check each sub-field for Mixed
126
- if (
127
- schemaPath.instance === "Array" &&
128
- schemaPath.schema &&
129
- properties[key]?.items?.properties
130
- ) {
131
- fixMixedFields(schemaPath.schema, properties[key].items.properties);
133
+ if (schemaPath.instance === "Array" && schemaPath.schema) {
134
+ const itemProperties = props[key]?.items?.properties;
135
+ if (itemProperties) {
136
+ fixMixedFields(schemaPath.schema, itemProperties);
137
+ }
132
138
  }
133
139
  }
134
140
  };
135
141
 
136
- export function getOpenApiSpecForModel(
142
+ export const getOpenApiSpecForModel = (
143
+ // biome-ignore lint/suspicious/noExplicitAny: noExplicitAny: Mongoose Model param uses deep internal APIs (schema.path().options.ref, schema.virtuals, schema.childSchemas, db.model) that are not exposed in public type definitions
137
144
  model: any,
138
145
  {
139
146
  populatePaths,
140
147
  extraModelProperties,
141
148
  }: {populatePaths?: PopulatePath[]; extraModelProperties?: Record<string, unknown>} = {}
142
- ): {properties: Record<string, unknown>; required: string[]} {
149
+ ): {properties: Record<string, unknown>; required: string[]} => {
143
150
  const modelSwagger = m2s(model, {
144
151
  props: ["required", "enum"],
145
152
  });
@@ -241,19 +248,20 @@ export function getOpenApiSpecForModel(
241
248
  properties: {...modelSwagger.properties, ...extraModelProperties},
242
249
  required: modelSwagger.required ?? [],
243
250
  };
244
- }
251
+ };
245
252
 
246
253
  // Helper function to unpopulate a document that has been populated.
247
254
  // This is helpful for supporting backwards compatibility. E.g. you use populatePaths
248
255
  // to populate a document but if the version header for the request is below the version
249
256
  // that the populatePath was added, we remove the population and just return the _id.
250
- export function unpopulate<T>(doc: Document<T>, path: string): Document<T> {
257
+ export const unpopulate = <T>(doc: Document<T>, path: string): Document<T> => {
251
258
  if (!path) {
252
259
  throw new APIError({status: 500, title: "path is required for unpopulate"});
253
260
  }
254
261
  const pathParts = path.split(".");
255
262
 
256
263
  // Recursive because we need to support nested paths.
264
+ // biome-ignore lint/suspicious/noExplicitAny: noExplicitAny: recursive document traversal uses bracket-notation indexing on arbitrary nested document shapes that Mongoose Document types do not expose
257
265
  const recursiveUnpopulate = (current: any, parts: string[]): any => {
258
266
  const part = parts[0];
259
267
 
@@ -266,7 +274,7 @@ export function unpopulate<T>(doc: Document<T>, path: string): Document<T> {
266
274
  // Base case: we've reached the last part of the path
267
275
  if (Array.isArray(current[part])) {
268
276
  // If the field is an array, recursively unpopulate each element
269
- current[part] = current[part].map((item: any) => {
277
+ current[part] = current[part].map((item) => {
270
278
  return item?._id ? item._id : item;
271
279
  });
272
280
  } else if (current[part]?._id) {
@@ -288,4 +296,4 @@ export function unpopulate<T>(doc: Document<T>, path: string): Document<T> {
288
296
  };
289
297
 
290
298
  return recursiveUnpopulate(doc, pathParts);
291
- }
299
+ };