@common-grants/core 0.2.2 → 0.3.1-alpha.1

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.
package/lib/api.tsp CHANGED
@@ -31,9 +31,17 @@ using Versioning;
31
31
  }
32
32
  )
33
33
  @tagMetadata("Forms", #{ description: "Endpoints related to forms" })
34
+ @tagMetadata(
35
+ "Application Reviews",
36
+ #{
37
+ description: "Endpoints related to reviewing applications for a given competition",
38
+ }
39
+ )
34
40
  @tagMetadata(
35
41
  "Applications",
36
- #{ description: "Endpoints related to applications for a given competition" }
42
+ #{
43
+ description: "Endpoints related to submitting applications for a given competition",
44
+ }
37
45
  )
38
46
  @tagMetadata(
39
47
  "Competitions",
@@ -122,6 +130,14 @@ namespace Applications {
122
130
 
123
131
  @added(Versions.v0_2)
124
132
  op submitApplication is ApplicationRouter.submitApplication;
133
+
134
+ // ################################
135
+ // Search applications
136
+ // ################################
137
+
138
+ @added(Versions.v0_3)
139
+ @tag("Application Reviews")
140
+ op searchApplications is ApplicationRouter.searchApplications;
125
141
  }
126
142
 
127
143
  // #########################################################
@@ -47,4 +47,24 @@ namespace Examples.File {
47
47
  createdAt: utcDateTime.fromISO("2025-01-01T17:01:01"),
48
48
  lastModifiedAt: utcDateTime.fromISO("2025-01-02T17:30:00"),
49
49
  };
50
+
51
+ const excelFile = #{
52
+ downloadUrl: "https://example.com/excel.xlsx",
53
+ name: "excel.xlsx",
54
+ description: "The excel file for the application",
55
+ sizeInBytes: 1000,
56
+ mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
57
+ createdAt: utcDateTime.fromISO("2025-01-01T17:01:01"),
58
+ lastModifiedAt: utcDateTime.fromISO("2025-01-02T17:30:00"),
59
+ };
60
+
61
+ const zipFile = #{
62
+ downloadUrl: "https://example.com/application.zip",
63
+ name: "application.zip",
64
+ description: "The zip file for the application",
65
+ sizeInBytes: 50000,
66
+ mimeType: "application/zip",
67
+ createdAt: utcDateTime.fromISO("2025-01-01T17:01:01"),
68
+ lastModifiedAt: utcDateTime.fromISO("2025-01-02T17:30:00"),
69
+ };
50
70
  }
@@ -13,6 +13,10 @@ model ApplicationBase {
13
13
  /** The unique identifier for the competition */
14
14
  competitionId: Types.uuid;
15
15
 
16
+ /** The unique identifier for the opportunity being applied to */
17
+ @Versioning.added(CommonGrants.Versions.v0_3)
18
+ opportunityId: Types.uuid;
19
+
16
20
  /** The form responses for the application */
17
21
  formResponses: Record<AppFormResponse>;
18
22
 
@@ -84,6 +88,79 @@ model AppFormResponse {
84
88
  ...FormResponseBase;
85
89
  }
86
90
 
91
+ // #########################################################
92
+ // AppFilters
93
+ // #########################################################
94
+
95
+ /** Filters to apply when searching for applications */
96
+ @Versioning.added(CommonGrants.Versions.v0_3)
97
+ model AppFilters {
98
+ /** The default filters to apply to the search */
99
+ ...AppDefaultFilters;
100
+
101
+ /** Additional implementation-defined filters to apply to the search */
102
+ customFilters?: Record<Filters.DefaultFilter>;
103
+ }
104
+
105
+ /** The standard set of filters supported for application searches */
106
+ @Versioning.added(CommonGrants.Versions.v0_3)
107
+ model AppDefaultFilters extends Record<Filters.DefaultFilter> {
108
+ /** `opportunityId` matches one of the following values */
109
+ @example(#{
110
+ operator: Filters.ArrayOperators.in,
111
+ value: #["ad3b469a-d89a-42d3-c439-6c1234567890"],
112
+ })
113
+ opportunityId?: Filters.StringArrayFilter;
114
+
115
+ /** `competitionId` matches one of the following values */
116
+ @example(#{
117
+ operator: Filters.ArrayOperators.in,
118
+ value: #["123e4567-e89b-12d3-a456-426614174000"],
119
+ })
120
+ competitionId?: Filters.StringArrayFilter;
121
+
122
+ /** `submittedAt` is between the given range */
123
+ @example(#{
124
+ operator: Filters.RangeOperators.between,
125
+ value: #{
126
+ min: Types.isoDate.fromISO("2025-01-01"),
127
+ max: Types.isoDate.fromISO("2025-01-30"),
128
+ },
129
+ })
130
+ submittedAtRange?: Filters.DateRangeFilter;
131
+
132
+ /** `status.value` matches one of the following values */
133
+ @example(#{
134
+ operator: Filters.ArrayOperators.in,
135
+ value: #["submitted", "accepted"],
136
+ })
137
+ status?: Filters.StringArrayFilter;
138
+ }
139
+
140
+ // #########################################################
141
+ // AppSorting
142
+ // #########################################################
143
+
144
+ /** The fields that can be used to sort applications */
145
+ @Versioning.added(CommonGrants.Versions.v0_3)
146
+ enum AppSortBy {
147
+ lastModifiedAt,
148
+ createdAt,
149
+ submittedAt,
150
+ status: "status.value",
151
+ opportunityId,
152
+ competitionId,
153
+ custom,
154
+ }
155
+
156
+ /** Sorting parameters for applications */
157
+ @Versioning.added(CommonGrants.Versions.v0_3)
158
+ model AppSorting extends Sorting.SortBodyParams {
159
+ /** The field to sort by */
160
+ @example(AppSortBy.opportunityId)
161
+ sortBy: AppSortBy;
162
+ }
163
+
87
164
  // #########################################################
88
165
  // Examples
89
166
  // #########################################################
@@ -110,14 +187,36 @@ namespace Examples.Application {
110
187
  ...Examples.FormResponse.formResponse,
111
188
  };
112
189
 
190
+ const attachmentsCustomField = #{
191
+ name: "attachments",
192
+ fieldType: Fields.CustomFieldType.object,
193
+ value: #{
194
+ contacts: Fields.Examples.File.pdfFile,
195
+ budget: Fields.Examples.File.excelFile,
196
+ },
197
+ description: "The attachments for the application",
198
+ };
199
+
200
+ const applicationZipFileCustomField = #{
201
+ name: "applicationZipFile",
202
+ fieldType: Fields.CustomFieldType.object,
203
+ value: Fields.Examples.File.zipFile,
204
+ description: "The zip file for the application",
205
+ };
206
+
113
207
  const applicationBase = #{
114
208
  id: "123e4567-e89b-12d3-a456-426614174000",
115
209
  name: "My Application",
116
210
  competitionId: "123e4567-e89b-12d3-a456-426614174000",
211
+ opportunityId: "ad3b469a-d89a-42d3-c439-6c1234567890",
117
212
  formResponses: #{ formA: formResponse },
118
213
  status: inProgressStatus,
119
214
  submittedAt: null,
120
215
  createdAt: utcDateTime.fromISO("2021-01-01T00:00:00Z"),
121
216
  lastModifiedAt: utcDateTime.fromISO("2021-01-01T00:00:00Z"),
217
+ customFields: #{
218
+ attachments: attachmentsCustomField,
219
+ applicationZipFile: applicationZipFileCustomField,
220
+ },
122
221
  };
123
222
  }
@@ -83,7 +83,7 @@ enum CompetitionStatusOptions {
83
83
  @example(Examples.Competition.forms)
84
84
  model CompetitionForms {
85
85
  /** The forms for the competition */
86
- forms: Record<Models.Form>;
86
+ forms: Record<Models.FormBase>;
87
87
 
88
88
  /** The validation rules for the competition forms */
89
89
  validation?: Record<unknown>;
@@ -9,7 +9,8 @@ namespace CommonGrants.Models;
9
9
  /** A form for collecting data from a user. */
10
10
  @example(Examples.Form.form)
11
11
  @Versioning.added(CommonGrants.Versions.v0_2)
12
- model Form {
12
+ @Versioning.renamedFrom(CommonGrants.Versions.v0_3, "Form")
13
+ model FormBase {
13
14
  /** The form's unique identifier. */
14
15
  id: Types.uuid;
15
16
 
@@ -19,6 +20,9 @@ model Form {
19
20
  /** The form's description. */
20
21
  description?: string;
21
22
 
23
+ @Versioning.added(CommonGrants.Versions.v0_3)
24
+ version?: string;
25
+
22
26
  /** The form's instructions. */
23
27
  instructions?: string | Fields.File[];
24
28
 
@@ -36,6 +40,9 @@ model Form {
36
40
 
37
41
  /** Custom attributes about the form itself, not custom fields within the form. */
38
42
  customFields?: Record<Fields.CustomField>;
43
+
44
+ /** The system metadata for the form. */
45
+ ...Fields.SystemMetadata;
39
46
  }
40
47
 
41
48
  // #########################################################
@@ -74,6 +81,8 @@ namespace Examples.Form {
74
81
  uiSchema: uiSchema,
75
82
  mappingToCommonGrants: mappingToCommonGrants,
76
83
  mappingFromCommonGrants: mappingFromCommonGrants,
84
+ createdAt: utcDateTime.fromISO("2025-01-01T17:01:01"),
85
+ lastModifiedAt: utcDateTime.fromISO("2025-01-02T17:30:00"),
77
86
  };
78
87
 
79
88
  const formSchema = #{
@@ -63,4 +63,20 @@ interface Applications {
63
63
  | Responses.ApplicationSubmissionError
64
64
  | Responses.NotFound
65
65
  | Responses.Unauthorized;
66
+
67
+ // ###############################
68
+ // Search applications
69
+ // ###############################
70
+
71
+ @summary("Search applications")
72
+ @doc("Search for applications. Note: The search results for a given query will depend on the scopes attached to the API token used to make the request.")
73
+ @get
74
+ @route("/search")
75
+ searchApplications(
76
+ /** The filters to apply to the search */
77
+ @query filters: Models.AppFilters,
78
+
79
+ /** The sorting to apply to the search */
80
+ @query sorting: Models.AppSorting,
81
+ ): Responses.Filtered<Models.ApplicationBase, Models.AppFilters>;
66
82
  }
@@ -22,7 +22,9 @@ interface Forms {
22
22
  @summary("List forms")
23
23
  @doc("Get a paginated list of forms, sorted by `lastModifiedAt` with most recent first.")
24
24
  @get
25
- list(...Pagination.PaginatedQueryParams): Responses.Paginated<Models.Form>;
25
+ list(
26
+ ...Pagination.PaginatedQueryParams,
27
+ ): Responses.Paginated<Models.FormBase>;
26
28
 
27
29
  // ###############################
28
30
  // View form details
@@ -34,5 +36,5 @@ interface Forms {
34
36
  read(
35
37
  /** The ID of the form to view */
36
38
  @path formId: Types.uuid,
37
- ): Responses.Ok<Models.Form>;
39
+ ): Responses.Ok<Models.FormBase>;
38
40
  }
package/lib/main.tsp CHANGED
@@ -18,4 +18,5 @@ namespace CommonGrants;
18
18
  enum Versions {
19
19
  v0_1: "0.1.0",
20
20
  v0_2: "0.2.0",
21
+ v0_3: "0.3.0",
21
22
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@common-grants/core",
3
- "version": "0.2.2",
3
+ "version": "0.3.1-alpha.1",
4
4
  "description": "TypeSpec library for defining grant opportunity data models and APIs",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",