@oneuptime/common 7.0.4313 → 7.0.4337

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 (76) hide show
  1. package/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.ts +3 -3
  2. package/Server/Services/ProjectService.ts +10 -0
  3. package/Server/Utils/OpenAPI.ts +173 -105
  4. package/Types/Billing/SubscriptionStatus.ts +29 -1
  5. package/Types/Color.ts +15 -0
  6. package/Types/Database/DatabaseProperty.ts +5 -0
  7. package/Types/Domain.ts +15 -0
  8. package/Types/Email/EmailTemplateType.ts +2 -0
  9. package/Types/Email.ts +16 -0
  10. package/Types/IP/IP.ts +15 -0
  11. package/Types/Monitor/CriteriaAlert.ts +11 -0
  12. package/Types/Monitor/CriteriaFilter.ts +20 -0
  13. package/Types/Monitor/CriteriaIncident.ts +11 -0
  14. package/Types/Monitor/MonitorCriteria.ts +24 -0
  15. package/Types/Monitor/MonitorCriteriaInstance.ts +51 -2
  16. package/Types/Monitor/MonitorStep.ts +43 -0
  17. package/Types/Monitor/MonitorSteps.ts +27 -0
  18. package/Types/Name.ts +15 -0
  19. package/Types/ObjectID.ts +18 -0
  20. package/Types/Phone.ts +15 -0
  21. package/Types/Port.ts +15 -0
  22. package/Types/Version.ts +15 -0
  23. package/UI/Utils/Project.ts +15 -2
  24. package/Utils/Schema/ModelSchema.ts +215 -70
  25. package/Utils/Schema/Zod.ts +20 -0
  26. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js +3 -3
  27. package/build/dist/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel.js.map +1 -1
  28. package/build/dist/Server/Services/ProjectService.js +11 -0
  29. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  30. package/build/dist/Server/Utils/OpenAPI.js +137 -92
  31. package/build/dist/Server/Utils/OpenAPI.js.map +1 -1
  32. package/build/dist/Types/Billing/SubscriptionStatus.js +19 -1
  33. package/build/dist/Types/Billing/SubscriptionStatus.js.map +1 -1
  34. package/build/dist/Types/Color.js +14 -0
  35. package/build/dist/Types/Color.js.map +1 -1
  36. package/build/dist/Types/Database/DatabaseProperty.js +3 -0
  37. package/build/dist/Types/Database/DatabaseProperty.js.map +1 -1
  38. package/build/dist/Types/Domain.js +14 -0
  39. package/build/dist/Types/Domain.js.map +1 -1
  40. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  41. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  42. package/build/dist/Types/Email.js +15 -0
  43. package/build/dist/Types/Email.js.map +1 -1
  44. package/build/dist/Types/IP/IP.js +14 -0
  45. package/build/dist/Types/IP/IP.js.map +1 -1
  46. package/build/dist/Types/Monitor/CriteriaAlert.js +10 -1
  47. package/build/dist/Types/Monitor/CriteriaAlert.js.map +1 -1
  48. package/build/dist/Types/Monitor/CriteriaFilter.js +18 -0
  49. package/build/dist/Types/Monitor/CriteriaFilter.js.map +1 -1
  50. package/build/dist/Types/Monitor/CriteriaIncident.js +10 -1
  51. package/build/dist/Types/Monitor/CriteriaIncident.js.map +1 -1
  52. package/build/dist/Types/Monitor/MonitorCriteria.js +21 -0
  53. package/build/dist/Types/Monitor/MonitorCriteria.js.map +1 -1
  54. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js +50 -1
  55. package/build/dist/Types/Monitor/MonitorCriteriaInstance.js.map +1 -1
  56. package/build/dist/Types/Monitor/MonitorStep.js +42 -0
  57. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  58. package/build/dist/Types/Monitor/MonitorSteps.js +26 -0
  59. package/build/dist/Types/Monitor/MonitorSteps.js.map +1 -1
  60. package/build/dist/Types/Name.js +14 -0
  61. package/build/dist/Types/Name.js.map +1 -1
  62. package/build/dist/Types/ObjectID.js +17 -0
  63. package/build/dist/Types/ObjectID.js.map +1 -1
  64. package/build/dist/Types/Phone.js +14 -0
  65. package/build/dist/Types/Phone.js.map +1 -1
  66. package/build/dist/Types/Port.js +14 -0
  67. package/build/dist/Types/Port.js.map +1 -1
  68. package/build/dist/Types/Version.js +14 -0
  69. package/build/dist/Types/Version.js.map +1 -1
  70. package/build/dist/UI/Utils/Project.js +5 -2
  71. package/build/dist/UI/Utils/Project.js.map +1 -1
  72. package/build/dist/Utils/Schema/ModelSchema.js +228 -46
  73. package/build/dist/Utils/Schema/ModelSchema.js.map +1 -1
  74. package/build/dist/Utils/Schema/Zod.js +6 -0
  75. package/build/dist/Utils/Schema/Zod.js.map +1 -0
  76. package/package.json +1 -1
@@ -61,7 +61,7 @@ export default class DatabaseBaseModel extends BaseEntity {
61
61
  public _id?: string = undefined;
62
62
 
63
63
  @TableColumn({
64
- title: "Created",
64
+ title: "Created At",
65
65
  type: TableColumnType.Date,
66
66
  description: "Date and Time when the object was created.",
67
67
  })
@@ -71,7 +71,7 @@ export default class DatabaseBaseModel extends BaseEntity {
71
71
  public createdAt?: Date = undefined;
72
72
 
73
73
  @TableColumn({
74
- title: "Updated",
74
+ title: "Updated At",
75
75
  type: TableColumnType.Date,
76
76
  description: "Date and Time when the object was updated.",
77
77
  })
@@ -81,7 +81,7 @@ export default class DatabaseBaseModel extends BaseEntity {
81
81
  public updatedAt?: Date = undefined;
82
82
 
83
83
  @TableColumn({
84
- title: "Deleted",
84
+ title: "Deleted At",
85
85
  type: TableColumnType.Date,
86
86
  description: "Date and Time when the object was deleted.",
87
87
  })
@@ -71,6 +71,7 @@ import SlackUtil from "../Utils/Workspace/Slack/Slack";
71
71
  import URL from "../../Types/API/URL";
72
72
  import Exception from "../../Types/Exception/Exception";
73
73
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
74
+ import DatabaseConfig from "../DatabaseConfig";
74
75
 
75
76
  export interface CurrentPlan {
76
77
  plan: PlanType | null;
@@ -1415,6 +1416,15 @@ export class ProjectService extends DatabaseService<Model> {
1415
1416
  };
1416
1417
  }
1417
1418
 
1419
+ @CaptureSpan()
1420
+ public async getProjectLinkInDashboard(projectId: ObjectID): Promise<URL> {
1421
+ const dashboardUrl: URL = await DatabaseConfig.getDashboardUrl();
1422
+
1423
+ return URL.fromString(dashboardUrl.toString()).addRoute(
1424
+ `/${projectId.toString()}`,
1425
+ );
1426
+ }
1427
+
1418
1428
  @CaptureSpan()
1419
1429
  public async isSMSNotificationsEnabled(
1420
1430
  projectId: ObjectID,
@@ -4,107 +4,120 @@ import {
4
4
  } from "@asteasolutions/zod-to-openapi";
5
5
  import DatabaseBaseModel from "../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
6
6
  import Models from "../../Models/DatabaseModels/Index";
7
- import { JSONObject } from "../../Types/JSON";
7
+ import { JSONObject, JSONValue } from "../../Types/JSON";
8
+ import logger from "./Logger";
9
+ import { ModelSchema, ModelSchemaType } from "../../Utils/Schema/ModelSchema";
10
+ import LocalCache from "../Infrastructure/LocalCache";
11
+ import { Host, HttpProtocol } from "../EnvironmentConfig";
8
12
 
9
13
  export default class OpenAPIUtil {
10
14
  public static generateOpenAPISpec(): JSONObject {
15
+ // check if the cache is already in LocalCache
16
+ const cachedSpec: JSONValue | undefined = LocalCache.getJSON(
17
+ "openapi",
18
+ "spec",
19
+ );
20
+
21
+ if (cachedSpec) {
22
+ logger.debug("Returning cached OpenAPI spec");
23
+ return cachedSpec as JSONObject;
24
+ }
25
+
11
26
  const registry: OpenAPIRegistry = new OpenAPIRegistry();
12
27
 
13
28
  // Register schemas and paths for all models
14
29
  for (const ModelClass of Models) {
15
30
  const model: DatabaseBaseModel = new ModelClass();
16
- const modelName: string = model.constructor.name;
17
- const basePath: string = `/api/${modelName.toLowerCase()}`;
18
- // Use a plain object for paths
19
- const paths: Record<string, Record<string, any>> = {};
31
+ const modelName: string | null = model.tableName;
20
32
 
21
- // List endpoints (POST and GET)
22
- paths[`${basePath}/get-list`] = {
23
- post: this.generateListApiSpec({ modelType: ModelClass }),
24
- get: this.generateListApiSpec({ modelType: ModelClass }),
25
- };
26
- // Count endpoint
27
- paths[`${basePath}/count`] = {
28
- post: this.generateCountApiSpec({ modelType: ModelClass }),
29
- };
30
- // Create endpoint
31
- paths[basePath] = {
32
- post: this.generateCreateApiSpec({ modelType: ModelClass }),
33
- };
34
- // Get item endpoints (POST and GET)
35
- paths[`${basePath}/{id}/get-item`] = {
36
- post: this.generateGetApiSpec({ modelType: ModelClass }),
37
- get: this.generateGetApiSpec({ modelType: ModelClass }),
38
- };
39
- // Update endpoints (PUT, POST, GET)
40
- if (!paths[`${basePath}/{id}`]) {
41
- paths[`${basePath}/{id}`] = {};
33
+ if (!modelName) {
34
+ continue;
42
35
  }
43
36
 
44
- paths[`${basePath}/{id}`]!["put"] = this.generateUpdateApiSpec({
45
- modelType: ModelClass,
46
- });
47
- paths[`${basePath}/{id}/update-item`] = {
48
- post: this.generateUpdateApiSpec({ modelType: ModelClass }),
49
- get: this.generateUpdateApiSpec({ modelType: ModelClass }),
50
- };
51
- // Delete endpoints (DELETE, POST, GET)
52
- if (!paths[`${basePath}/{id}`]) {
53
- paths[`${basePath}/{id}`] = {};
37
+ // check if enable documentation is enabled
38
+
39
+ if (!model.enableDocumentation) {
40
+ logger.debug(
41
+ `Skipping OpenAPI documentation for model ${modelName} as it is disabled.`,
42
+ );
43
+ continue;
54
44
  }
55
- paths[`${basePath}/{id}`]!["delete"] = this.generateDeleteApiSpec({
45
+
46
+ if (!model.crudApiPath) {
47
+ logger.debug(
48
+ `Skipping OpenAPI documentation for model ${modelName} as it does not have a CRUD API path defined.`,
49
+ );
50
+ continue;
51
+ }
52
+
53
+ // register the model schema
54
+ OpenAPIUtil.registerModelSchemas(registry, model);
55
+
56
+ this.generateListApiSpec({
56
57
  modelType: ModelClass,
58
+ registry,
57
59
  });
58
- paths[`${basePath}/{id}/delete-item`] = {
59
- post: this.generateDeleteApiSpec({ modelType: ModelClass }),
60
- get: this.generateDeleteApiSpec({ modelType: ModelClass }),
61
- };
62
60
 
63
- // Register the paths in the registry
64
- for (const path in paths) {
65
- if (paths[path]) {
66
- const methods: Record<string, any> | undefined = paths[path];
67
- if (typeof methods === "object" && methods !== null) {
68
- for (const method in methods) {
69
- if (methods[method]) {
70
- const spec: any = methods[method];
71
- registry.registerPath({
72
- method: method as any,
73
- path,
74
- ...spec,
75
- });
76
- }
77
- }
78
- }
79
- }
80
- }
61
+ this.generateCountApiSpec({
62
+ modelType: ModelClass,
63
+ registry,
64
+ });
65
+ this.generateCreateApiSpec({
66
+ modelType: ModelClass,
67
+ registry,
68
+ });
69
+ this.generateGetApiSpec({
70
+ modelType: ModelClass,
71
+ registry,
72
+ });
73
+ this.generateUpdateApiSpec({
74
+ modelType: ModelClass,
75
+ registry,
76
+ });
77
+ this.generateDeleteApiSpec({
78
+ modelType: ModelClass,
79
+ registry,
80
+ });
81
81
  }
82
82
 
83
83
  const generator: OpenApiGeneratorV3 = new OpenApiGeneratorV3(
84
84
  registry.definitions,
85
85
  );
86
86
 
87
- const components: Pick<any, "components"> = generator.generateComponents();
88
-
89
- return {
87
+ const spec: JSONObject = generator.generateDocument({
90
88
  openapi: "3.0.0",
91
89
  info: {
92
- title: "API Documentation",
90
+ title: "OneUptime OpenAPI Specification",
93
91
  version: "1.0.0",
94
- description: "API documentation generated from models",
92
+ description:
93
+ "OpenAPI specification for OneUptime. This document describes the API endpoints, request and response formats, and other details necessary for developers to interact with the OneUptime API.",
95
94
  },
96
- components: components,
97
- } as unknown as JSONObject;
95
+ servers: [
96
+ {
97
+ url: `${HttpProtocol.toString()}${Host.toString()}/api`,
98
+ description: "API Server",
99
+ },
100
+ ],
101
+ }) as unknown as JSONObject;
102
+
103
+ LocalCache.setJSON("openapi", "spec", spec as JSONObject);
104
+
105
+ return spec;
98
106
  }
99
107
 
100
108
  public static generateListApiSpec(data: {
101
109
  modelType: new () => DatabaseBaseModel;
102
- }): JSONObject {
110
+ registry: OpenAPIRegistry;
111
+ }): void {
103
112
  const modelType: new () => DatabaseBaseModel = data.modelType;
104
113
  const model: DatabaseBaseModel = new modelType();
105
- return {
106
- summary: `List ${model.constructor.name}`,
107
- description: `Endpoint to list all ${model.constructor.name} items`,
114
+ const tableName: string = model.tableName || "UnknownModel";
115
+
116
+ data.registry.registerPath({
117
+ method: "post",
118
+ path: `${model.crudApiPath}/get-list`,
119
+ summary: `List ${tableName}`,
120
+ description: `Endpoint to list all ${tableName} items`,
108
121
  requestBody: {
109
122
  required: false,
110
123
  content: {
@@ -132,7 +145,7 @@ export default class OpenAPIUtil {
132
145
  data: {
133
146
  type: "array",
134
147
  items: {
135
- $ref: `#/components/schemas/${model.constructor.name}`,
148
+ $ref: `#/components/schemas/${tableName}`,
136
149
  },
137
150
  },
138
151
  count: { type: "number" },
@@ -142,17 +155,21 @@ export default class OpenAPIUtil {
142
155
  },
143
156
  },
144
157
  },
145
- };
158
+ });
146
159
  }
147
160
 
148
161
  public static generateCountApiSpec(data: {
149
162
  modelType: new () => DatabaseBaseModel;
150
- }): JSONObject {
163
+ registry: OpenAPIRegistry;
164
+ }): void {
151
165
  const modelType: new () => DatabaseBaseModel = data.modelType;
152
166
  const model: DatabaseBaseModel = new modelType();
153
- return {
154
- summary: `Count ${model.constructor.name}`,
155
- description: `Endpoint to count ${model.constructor.name} items`,
167
+ const tableName: string = model.tableName || "UnknownModel";
168
+ data.registry.registerPath({
169
+ method: "post",
170
+ path: `${model.crudApiPath}/count`,
171
+ summary: `Count ${tableName}`,
172
+ description: `Endpoint to count ${tableName} items`,
156
173
  requestBody: {
157
174
  required: false,
158
175
  content: {
@@ -181,17 +198,21 @@ export default class OpenAPIUtil {
181
198
  },
182
199
  },
183
200
  },
184
- };
201
+ });
185
202
  }
186
203
 
187
204
  public static generateCreateApiSpec(data: {
188
205
  modelType: new () => DatabaseBaseModel;
189
- }): JSONObject {
206
+ registry: OpenAPIRegistry;
207
+ }): void {
190
208
  const modelType: new () => DatabaseBaseModel = data.modelType;
191
209
  const model: DatabaseBaseModel = new modelType();
192
- return {
193
- summary: `Create ${model.constructor.name}`,
194
- description: `Endpoint to create a new ${model.constructor.name}`,
210
+ const tableName: string = model.tableName || "UnknownModel";
211
+ data.registry.registerPath({
212
+ method: "post",
213
+ path: `${model.crudApiPath}`,
214
+ summary: `Create ${tableName}`,
215
+ description: `Endpoint to create a new ${tableName}`,
195
216
  requestBody: {
196
217
  required: true,
197
218
  content: {
@@ -200,7 +221,7 @@ export default class OpenAPIUtil {
200
221
  type: "object",
201
222
  properties: {
202
223
  data: {
203
- $ref: `#/components/schemas/${model.constructor.name}Input`,
224
+ $ref: `#/components/schemas/${tableName}Input`,
204
225
  },
205
226
  miscDataProps: { type: "object" },
206
227
  },
@@ -218,7 +239,7 @@ export default class OpenAPIUtil {
218
239
  type: "object",
219
240
  properties: {
220
241
  data: {
221
- $ref: `#/components/schemas/${model.constructor.name}`,
242
+ $ref: `#/components/schemas/${tableName}`,
222
243
  },
223
244
  },
224
245
  },
@@ -229,18 +250,23 @@ export default class OpenAPIUtil {
229
250
  description: "Bad request",
230
251
  },
231
252
  },
232
- };
253
+ });
233
254
  }
234
255
 
235
256
  public static generateGetApiSpec(data: {
236
257
  modelType: new () => DatabaseBaseModel;
237
- }): JSONObject {
258
+ registry: OpenAPIRegistry;
259
+ }): void {
238
260
  const modelType: new () => DatabaseBaseModel = data.modelType;
239
261
  const model: DatabaseBaseModel = new modelType();
240
- return {
241
- summary: `Get ${model.constructor.name}`,
242
- description: `Endpoint to retrieve a single ${model.constructor.name} by ID`,
262
+ const tableName: string = model.tableName || "UnknownModel";
263
+ data.registry.registerPath({
264
+ method: "post",
265
+ path: `${model.crudApiPath}/{id}`,
266
+ summary: `Get ${tableName}`,
267
+ description: `Endpoint to retrieve a single ${tableName} by ID`,
243
268
  parameters: [
269
+ ...(OpenAPIUtil.getDefaultApiHeaders() as Array<any>),
244
270
  {
245
271
  name: "id",
246
272
  in: "path",
@@ -249,7 +275,7 @@ export default class OpenAPIUtil {
249
275
  type: "string",
250
276
  format: "uuid",
251
277
  },
252
- description: `ID of the ${model.constructor.name} to retrieve`,
278
+ description: `ID of the ${tableName} to retrieve`,
253
279
  },
254
280
  ],
255
281
  responses: {
@@ -261,7 +287,7 @@ export default class OpenAPIUtil {
261
287
  type: "object",
262
288
  properties: {
263
289
  data: {
264
- $ref: `#/components/schemas/${model.constructor.name}`,
290
+ $ref: `#/components/schemas/${tableName}`,
265
291
  },
266
292
  },
267
293
  },
@@ -272,18 +298,44 @@ export default class OpenAPIUtil {
272
298
  description: "Resource not found",
273
299
  },
274
300
  },
275
- };
301
+ });
302
+ }
303
+
304
+ public static getDefaultApiHeaders(): Array<JSONObject> {
305
+ return [
306
+ {
307
+ name: "Content-Type",
308
+ in: "header",
309
+ required: true,
310
+ schema: { type: "string" },
311
+ description: "Content type of the request",
312
+ example: "application/json",
313
+ },
314
+ {
315
+ name: "APIKey",
316
+ in: "header",
317
+ required: true,
318
+ schema: { type: "string" },
319
+ description: "API key for authentication",
320
+ example: "{{apiKey}}",
321
+ },
322
+ ];
276
323
  }
277
324
 
278
325
  public static generateUpdateApiSpec(data: {
279
326
  modelType: new () => DatabaseBaseModel;
280
- }): JSONObject {
327
+ registry: OpenAPIRegistry;
328
+ }): void {
281
329
  const modelType: new () => DatabaseBaseModel = data.modelType;
282
330
  const model: DatabaseBaseModel = new modelType();
283
- return {
284
- summary: `Update ${model.constructor.name}`,
285
- description: `Endpoint to update an existing ${model.constructor.name}`,
331
+ const tableName: string = model.tableName || "UnknownModel";
332
+ data.registry.registerPath({
333
+ method: "put",
334
+ path: `${model.crudApiPath}/{id}`,
335
+ summary: `Update ${tableName}`,
336
+ description: `Endpoint to update an existing ${tableName}`,
286
337
  parameters: [
338
+ ...(OpenAPIUtil.getDefaultApiHeaders() as Array<any>),
287
339
  {
288
340
  name: "id",
289
341
  in: "path",
@@ -292,7 +344,7 @@ export default class OpenAPIUtil {
292
344
  type: "string",
293
345
  format: "uuid",
294
346
  },
295
- description: `ID of the ${model.constructor.name} to update`,
347
+ description: `ID of the ${tableName} to update`,
296
348
  },
297
349
  ],
298
350
  requestBody: {
@@ -303,7 +355,7 @@ export default class OpenAPIUtil {
303
355
  type: "object",
304
356
  properties: {
305
357
  data: {
306
- $ref: `#/components/schemas/${model.constructor.name}UpdateInput`,
358
+ $ref: `#/components/schemas/${tableName}UpdateInput`,
307
359
  },
308
360
  },
309
361
  required: ["data"],
@@ -320,7 +372,7 @@ export default class OpenAPIUtil {
320
372
  type: "object",
321
373
  properties: {
322
374
  data: {
323
- $ref: `#/components/schemas/${model.constructor.name}`,
375
+ $ref: `#/components/schemas/${tableName}`,
324
376
  },
325
377
  },
326
378
  },
@@ -334,18 +386,23 @@ export default class OpenAPIUtil {
334
386
  description: "Bad request",
335
387
  },
336
388
  },
337
- };
389
+ });
338
390
  }
339
391
 
340
392
  public static generateDeleteApiSpec(data: {
341
393
  modelType: new () => DatabaseBaseModel;
342
- }): JSONObject {
394
+ registry: OpenAPIRegistry;
395
+ }): void {
343
396
  const modelType: new () => DatabaseBaseModel = data.modelType;
344
397
  const model: DatabaseBaseModel = new modelType();
345
- return {
346
- summary: `Delete ${model.constructor.name}`,
347
- description: `Endpoint to delete a ${model.constructor.name}`,
398
+ const tableName: string = model.tableName || "UnknownModel";
399
+ data.registry.registerPath({
400
+ method: "delete",
401
+ path: `${model.crudApiPath}/{id}`,
402
+ summary: `Delete ${tableName}`,
403
+ description: `Endpoint to delete a ${tableName}`,
348
404
  parameters: [
405
+ ...(OpenAPIUtil.getDefaultApiHeaders() as Array<any>),
349
406
  {
350
407
  name: "id",
351
408
  in: "path",
@@ -354,7 +411,7 @@ export default class OpenAPIUtil {
354
411
  type: "string",
355
412
  format: "uuid",
356
413
  },
357
- description: `ID of the ${model.constructor.name} to delete`,
414
+ description: `ID of the ${tableName} to delete`,
358
415
  },
359
416
  ],
360
417
  responses: {
@@ -365,6 +422,17 @@ export default class OpenAPIUtil {
365
422
  description: "Resource not found",
366
423
  },
367
424
  },
368
- };
425
+ });
426
+ }
427
+
428
+ private static registerModelSchemas(
429
+ registry: OpenAPIRegistry,
430
+ model: DatabaseBaseModel,
431
+ ): void {
432
+ const tableName: string = model.tableName || "UnknownModel";
433
+ const modelSchema: ModelSchemaType = ModelSchema.getModelSchema({
434
+ modelType: model.constructor as new () => DatabaseBaseModel,
435
+ });
436
+ registry.register(tableName, modelSchema);
369
437
  }
370
438
  }
@@ -7,6 +7,7 @@ enum SubscriptionStatus {
7
7
  Canceled = "canceled",
8
8
  Unpaid = "unpaid",
9
9
  Expired = "expired",
10
+ Paused = "paused",
10
11
  }
11
12
 
12
13
  export class SubscriptionStatusUtil {
@@ -19,7 +20,8 @@ export class SubscriptionStatusUtil {
19
20
 
20
21
  return (
21
22
  status === SubscriptionStatus.Active ||
22
- status === SubscriptionStatus.Trialing
23
+ status === SubscriptionStatus.Trialing ||
24
+ status === SubscriptionStatus.PastDue
23
25
  );
24
26
  }
25
27
 
@@ -28,6 +30,32 @@ export class SubscriptionStatusUtil {
28
30
  ): boolean {
29
31
  return !SubscriptionStatusUtil.isSubscriptionActive(status);
30
32
  }
33
+
34
+ public static isSubscriptionOverdue(
35
+ status?: SubscriptionStatus | undefined,
36
+ ): boolean {
37
+ if (!status) {
38
+ return false;
39
+ }
40
+
41
+ return status === SubscriptionStatus.PastDue;
42
+ }
43
+
44
+ // is subscription canclled.
45
+ public static isSubscriptionCancelled(
46
+ status?: SubscriptionStatus | undefined,
47
+ ): boolean {
48
+ if (!status) {
49
+ return false;
50
+ }
51
+
52
+ return (
53
+ status === SubscriptionStatus.Canceled ||
54
+ status === SubscriptionStatus.Unpaid ||
55
+ status === SubscriptionStatus.Expired ||
56
+ status === SubscriptionStatus.IncompleteExpired
57
+ );
58
+ }
31
59
  }
32
60
 
33
61
  export default SubscriptionStatus;
package/Types/Color.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import Zod, { ZodSchema } from "../Utils/Schema/Zod";
1
2
  import DatabaseProperty from "./Database/DatabaseProperty";
2
3
  import BadDataException from "./Exception/BadDataException";
3
4
  import { JSONObject, ObjectType } from "./JSON";
@@ -105,4 +106,18 @@ export default class Color extends DatabaseProperty {
105
106
  }
106
107
  return false;
107
108
  }
109
+
110
+ public static override getSchema(): ZodSchema {
111
+ return Zod.object({
112
+ _type: Zod.literal(ObjectType.Color),
113
+ value: Zod.string().openapi({
114
+ type: "string",
115
+ example: "#ff0000",
116
+ }),
117
+ }).openapi({
118
+ type: "object",
119
+ description: "Color object",
120
+ example: { _type: ObjectType.Color, value: "#ff0000" },
121
+ });
122
+ }
108
123
  }
@@ -1,3 +1,4 @@
1
+ import { ZodSchema } from "zod";
1
2
  import NotImplementedException from "../Exception/NotImplementedException";
2
3
  import { JSONArray, JSONObject } from "../JSON";
3
4
  import SerializableObject from "../SerializableObject";
@@ -51,4 +52,8 @@ export default class DatabaseProperty extends SerializableObject {
51
52
  },
52
53
  };
53
54
  }
55
+
56
+ public static getSchema(): ZodSchema {
57
+ throw new NotImplementedException();
58
+ }
54
59
  }
package/Types/Domain.ts CHANGED
@@ -2,6 +2,7 @@ import DatabaseProperty from "./Database/DatabaseProperty";
2
2
  import BadDataException from "./Exception/BadDataException";
3
3
  import { JSONObject, ObjectType } from "./JSON";
4
4
  import { FindOperator } from "typeorm/find-options/FindOperator";
5
+ import Zod, { ZodSchema } from "../Utils/Schema/Zod";
5
6
 
6
7
  export default class Domain extends DatabaseProperty {
7
8
  private _domain: string = "";
@@ -91,4 +92,18 @@ export default class Domain extends DatabaseProperty {
91
92
 
92
93
  return null;
93
94
  }
95
+
96
+ public static override getSchema(): ZodSchema {
97
+ return Zod.object({
98
+ _type: Zod.literal(ObjectType.Domain),
99
+ value: Zod.string().openapi({
100
+ type: "string",
101
+ example: "example.com",
102
+ }),
103
+ }).openapi({
104
+ type: "object",
105
+ description: "Domain object",
106
+ example: { _type: ObjectType.Domain, value: "example.com" },
107
+ });
108
+ }
94
109
  }
@@ -55,6 +55,8 @@ enum EmailTemplateType {
55
55
  UserCurrentlyOnOnCallRoster = "UserCurrentlyOnOnCallRoster.hbs",
56
56
  UserNextOnOnCallRoster = "UserNextOnOnCallRoster.hbs",
57
57
  UserNoLongerActiveOnOnCallRoster = "UserNoLongerActiveOnOnCallRoster.hbs",
58
+
59
+ ProjectSubscriptionOverdue = "ProjectSubscriptionOverdue.hbs",
58
60
  }
59
61
 
60
62
  export default EmailTemplateType;
package/Types/Email.ts CHANGED
@@ -3,6 +3,7 @@ import DatabaseProperty from "./Database/DatabaseProperty";
3
3
  import BadDataException from "./Exception/BadDataException";
4
4
  import { JSONObject, ObjectType } from "./JSON";
5
5
  import { FindOperator } from "typeorm";
6
+ import Zod, { ZodSchema } from "../Utils/Schema/Zod";
6
7
 
7
8
  const nonBusinessEmailDomains: Array<string> = [
8
9
  "gmail",
@@ -123,4 +124,19 @@ export default class Email extends DatabaseProperty {
123
124
 
124
125
  return null;
125
126
  }
127
+
128
+ public static override getSchema(): ZodSchema {
129
+ return Zod.object({
130
+ _type: Zod.literal(ObjectType.Email),
131
+ value: Zod.string().email().openapi({
132
+ type: "string",
133
+ format: "email",
134
+ example: "user@example.com",
135
+ }),
136
+ }).openapi({
137
+ type: "object",
138
+ description: "Email object",
139
+ example: { _type: ObjectType.Email, value: "user@example.com" },
140
+ });
141
+ }
126
142
  }
package/Types/IP/IP.ts CHANGED
@@ -4,6 +4,7 @@ import { JSONObject, ObjectType } from "../JSON";
4
4
  import Typeof from "../Typeof";
5
5
  import IPType from "./IPType";
6
6
  import { FindOperator } from "typeorm";
7
+ import Zod, { ZodSchema } from "../../Utils/Schema/Zod";
7
8
 
8
9
  export default class IP extends DatabaseProperty {
9
10
  private _ip: string = "";
@@ -199,4 +200,18 @@ export default class IP extends DatabaseProperty {
199
200
  }
200
201
  return null;
201
202
  }
203
+
204
+ public static override getSchema(): ZodSchema {
205
+ return Zod.object({
206
+ _type: Zod.literal(ObjectType.IP),
207
+ value: Zod.string().openapi({
208
+ type: "string",
209
+ example: "192.168.1.1",
210
+ }),
211
+ }).openapi({
212
+ type: "object",
213
+ description: "IP object",
214
+ example: { _type: ObjectType.IP, value: "192.168.1.1" },
215
+ });
216
+ }
202
217
  }