@common-grants/core 0.2.4 → 0.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.
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
  // #########################################################
@@ -5,6 +5,7 @@ namespace CommonGrants.Fields;
5
5
  // ########################################
6
6
 
7
7
  /** The set of JSON schema types supported by a custom field */
8
+ @Versioning.added(CommonGrants.Versions.v0_1)
8
9
  enum CustomFieldType {
9
10
  string,
10
11
  number,
@@ -44,6 +45,7 @@ enum CustomFieldType {
44
45
  #{ title: "Array field for eligibility types" }
45
46
  )
46
47
  @doc("A custom field on a model")
48
+ @Versioning.added(CommonGrants.Versions.v0_1)
47
49
  model CustomField {
48
50
  /** Name of the custom field */
49
51
  name: string;
@@ -14,6 +14,7 @@ using Types;
14
14
  * - dateRange: A period of time with a start and end date
15
15
  * - other: Other event type (e.g., a recurring event)
16
16
  */
17
+ @Versioning.added(CommonGrants.Versions.v0_1)
17
18
  enum EventType {
18
19
  /** A single date with no time */
19
20
  singleDate,
@@ -30,6 +31,7 @@ enum EventType {
30
31
  // ########################################
31
32
 
32
33
  /** Union of all event types */
34
+ @Versioning.added(CommonGrants.Versions.v0_1)
33
35
  union Event {
34
36
  /** A single date event */
35
37
  singleDate: SingleDateEvent,
@@ -47,6 +49,7 @@ union Event {
47
49
 
48
50
  /** Base model for all events */
49
51
  @discriminator("eventType")
52
+ @Versioning.added(CommonGrants.Versions.v0_1)
50
53
  model EventBase {
51
54
  /** Human-readable name of the event (e.g., 'Application posted', 'Question deadline') */
52
55
  name: string;
@@ -65,6 +68,7 @@ model EventBase {
65
68
  /** Description of an event that has a date (and possible time) associated with it */
66
69
  @example(Examples.Event.postedDate, #{ title: "Opportunity posted date" })
67
70
  @example(Examples.Event.closeDate, #{ title: "Opportunity close date" })
71
+ @Versioning.added(CommonGrants.Versions.v0_1)
68
72
  model SingleDateEvent extends EventBase {
69
73
  /** Type of event */
70
74
  eventType: EventType.singleDate;
@@ -83,6 +87,7 @@ model SingleDateEvent extends EventBase {
83
87
  /** Description of an event that has a start and end date (and possible time) associated with it */
84
88
  @example(Examples.Event.performancePeriod, #{ title: "Period of performance" })
85
89
  @example(Examples.Event.applicationPeriod, #{ title: "Application period" })
90
+ @Versioning.added(CommonGrants.Versions.v0_1)
86
91
  model DateRangeEvent extends EventBase {
87
92
  /** Type of event */
88
93
  eventType: EventType.dateRange;
@@ -106,6 +111,7 @@ model DateRangeEvent extends EventBase {
106
111
 
107
112
  /** Description of an event that is not a single date or date range */
108
113
  @example(Examples.Event.infoSessions, #{ title: "Info sessions" })
114
+ @Versioning.added(CommonGrants.Versions.v0_1)
109
115
  model OtherEvent extends EventBase {
110
116
  /** Type of event */
111
117
  eventType: EventType.other;
@@ -134,7 +140,7 @@ namespace Examples.Event {
134
140
 
135
141
  /** An example of an opportunity posted date without a specific time */
136
142
  const postedDate = #{
137
- name: "Application posted date",
143
+ name: "Opportunity posted date",
138
144
  eventType: EventType.singleDate,
139
145
  date: isoDate.fromISO("2024-01-15"),
140
146
  description: "Opportunity is posted publicly",
@@ -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
  }
@@ -19,6 +19,7 @@ namespace CommonGrants.Fields;
19
19
  * ```
20
20
  * */
21
21
  @example(Examples.Metadata.system)
22
+ @Versioning.added(CommonGrants.Versions.v0_1)
22
23
  model SystemMetadata {
23
24
  /** The timestamp (in UTC) at which the record was created. */
24
25
  @visibility(Lifecycle.Read)
@@ -18,6 +18,7 @@ using Types;
18
18
  Examples.Money.usdNegative,
19
19
  #{ title: "A negative amount of US dollars and cents" }
20
20
  )
21
+ @Versioning.added(CommonGrants.Versions.v0_1)
21
22
  model Money {
22
23
  /** The amount of money */
23
24
  amount: decimalString;
@@ -3,6 +3,7 @@ namespace CommonGrants.Fields;
3
3
  /** A phone number. */
4
4
  @example(Examples.Phone.mobile)
5
5
  @example(Examples.Phone.withExtension)
6
+ @Versioning.added(CommonGrants.Versions.v0_2)
6
7
  model Phone {
7
8
  /** The international country code (e.g., "+1" for US/Canada). */
8
9
  @pattern("^\\+[1-9][0-9]{0,3}$")
@@ -25,6 +26,7 @@ model Phone {
25
26
  /** A collection of phone numbers for a person. */
26
27
  @example(Examples.Phone.personalCollection)
27
28
  @example(Examples.Phone.orgCollection)
29
+ @Versioning.added(CommonGrants.Versions.v0_2)
28
30
  model PhoneCollection {
29
31
  /** The person's primary phone number. */
30
32
  primary: Fields.Phone;
@@ -5,6 +5,7 @@ namespace CommonGrants.Filters;
5
5
  // ############################################################################
6
6
 
7
7
  /** Operators that filter a field based on an exact match to a value */
8
+ @Versioning.added(CommonGrants.Versions.v0_1)
8
9
  enum EquivalenceOperators {
9
10
  /** Equal to a value */
10
11
  eq,
@@ -14,6 +15,7 @@ enum EquivalenceOperators {
14
15
  }
15
16
 
16
17
  /** Operators that filter a field based on a comparison to a value */
18
+ @Versioning.added(CommonGrants.Versions.v0_1)
17
19
  enum ComparisonOperators {
18
20
  /** Greater than a value */
19
21
  gt,
@@ -29,6 +31,7 @@ enum ComparisonOperators {
29
31
  }
30
32
 
31
33
  /** Operators that filter a field based on an array of values */
34
+ @Versioning.added(CommonGrants.Versions.v0_1)
32
35
  enum ArrayOperators {
33
36
  /** In an array of values */
34
37
  in,
@@ -38,6 +41,7 @@ enum ArrayOperators {
38
41
  }
39
42
 
40
43
  /** Operators that filter a field based on a string value */
44
+ @Versioning.added(CommonGrants.Versions.v0_1)
41
45
  enum StringOperators {
42
46
  /** Like */
43
47
  like,
@@ -47,6 +51,7 @@ enum StringOperators {
47
51
  }
48
52
 
49
53
  /** Operators that filter a field based on a range of values */
54
+ @Versioning.added(CommonGrants.Versions.v0_1)
50
55
  enum RangeOperators {
51
56
  /** Between a range of values */
52
57
  between,
@@ -55,6 +60,7 @@ enum RangeOperators {
55
60
  outside,
56
61
  }
57
62
 
63
+ @Versioning.added(CommonGrants.Versions.v0_1)
58
64
  enum AllOperators {
59
65
  ...EquivalenceOperators,
60
66
  ...ComparisonOperators,
@@ -68,6 +74,7 @@ enum AllOperators {
68
74
  // ############################################################################
69
75
 
70
76
  /** A base filter model that can be used to create more specific filter models */
77
+ @Versioning.added(CommonGrants.Versions.v0_1)
71
78
  model DefaultFilter {
72
79
  /** The operator to apply to the filter value */
73
80
  operator:
@@ -8,6 +8,7 @@ namespace CommonGrants.Filters;
8
8
  // ############################################################################
9
9
 
10
10
  /** Filters by comparing a field to a date value */
11
+ @Versioning.added(CommonGrants.Versions.v0_1)
11
12
  model DateComparisonFilter {
12
13
  /** The operator to apply to the filter value */
13
14
  operator: ComparisonOperators;
@@ -22,6 +23,7 @@ model DateComparisonFilter {
22
23
  // ############################################################################
23
24
 
24
25
  /** Filters by comparing a field to a range of date values */
26
+ @Versioning.added(CommonGrants.Versions.v0_1)
25
27
  model DateRangeFilter {
26
28
  /** The operator to apply to the filter value */
27
29
  operator: RangeOperators;
@@ -8,6 +8,7 @@ namespace CommonGrants.Filters;
8
8
  // ############################################################################
9
9
 
10
10
  /** Filters by comparing a field to a monetary value */
11
+ @Versioning.added(CommonGrants.Versions.v0_1)
11
12
  model MoneyComparisonFilter {
12
13
  /** The operator to apply to the filter value */
13
14
  operator: ComparisonOperators;
@@ -22,6 +23,7 @@ model MoneyComparisonFilter {
22
23
  // ############################################################################
23
24
 
24
25
  /** Filters by comparing a field to a range of monetary values */
26
+ @Versioning.added(CommonGrants.Versions.v0_1)
25
27
  model MoneyRangeFilter {
26
28
  /** The operator to apply to the filter value */
27
29
  operator: RangeOperators;
@@ -9,9 +9,11 @@ namespace CommonGrants.Filters;
9
9
  // ############################################################################
10
10
 
11
11
  /** Filters by comparing a field to a numeric value */
12
+ @Versioning.added(CommonGrants.Versions.v0_1)
12
13
  model NumberComparisonFilter {
13
14
  /** The comparison operator to apply to the filter value */
14
- operator: ComparisonOperators;
15
+ @Versioning.typeChangedFrom(CommonGrants.Versions.v0_3, ComparisonOperators)
16
+ operator: ComparisonOperators | EquivalenceOperators;
15
17
 
16
18
  /** The value to use for the filter operation */
17
19
  @example(1000)
@@ -23,6 +25,7 @@ model NumberComparisonFilter {
23
25
  // ############################################################################
24
26
 
25
27
  /** Filters by comparing a field to a numeric range */
28
+ @Versioning.added(CommonGrants.Versions.v0_1)
26
29
  model NumberRangeFilter {
27
30
  /** The operator to apply to the filter value */
28
31
  operator: RangeOperators;
@@ -40,6 +43,7 @@ model NumberRangeFilter {
40
43
  // ############################################################################
41
44
 
42
45
  /** Filters by comparing a field to an array of numeric values */
46
+ @Versioning.added(CommonGrants.Versions.v0_1)
43
47
  model NumberArrayFilter {
44
48
  /** The operator to apply to the filter value */
45
49
  operator: ArrayOperators;
@@ -7,6 +7,7 @@ namespace CommonGrants.Filters;
7
7
  // ############################################################################
8
8
 
9
9
  /** A filter that applies a comparison to a string value */
10
+ @Versioning.added(CommonGrants.Versions.v0_1)
10
11
  model StringComparisonFilter {
11
12
  /** The operator to apply to the filter value */
12
13
  operator: EquivalenceOperators | StringOperators;
@@ -21,6 +22,7 @@ model StringComparisonFilter {
21
22
  // ############################################################################
22
23
 
23
24
  /** Filters by comparing a field to an array of string values */
25
+ @Versioning.added(CommonGrants.Versions.v0_1)
24
26
  model StringArrayFilter {
25
27
  /** The operator to apply to the filter value */
26
28
  operator: ArrayOperators;
@@ -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
 
@@ -61,6 +65,7 @@ model AppStatus {
61
65
  * - `rejected`: The application has been rejected
62
66
  * - `custom`: A custom status
63
67
  */
68
+ @Versioning.added(CommonGrants.Versions.v0_1)
64
69
  enum AppStatusOptions {
65
70
  inProgress,
66
71
  submitted,
@@ -84,6 +89,79 @@ model AppFormResponse {
84
89
  ...FormResponseBase;
85
90
  }
86
91
 
92
+ // #########################################################
93
+ // AppFilters
94
+ // #########################################################
95
+
96
+ /** Filters to apply when searching for applications */
97
+ @Versioning.added(CommonGrants.Versions.v0_3)
98
+ model AppFilters {
99
+ /** The default filters to apply to the search */
100
+ ...AppDefaultFilters;
101
+
102
+ /** Additional implementation-defined filters to apply to the search */
103
+ customFilters?: Record<Filters.DefaultFilter>;
104
+ }
105
+
106
+ /** The standard set of filters supported for application searches */
107
+ @Versioning.added(CommonGrants.Versions.v0_3)
108
+ model AppDefaultFilters extends Record<Filters.DefaultFilter> {
109
+ /** `opportunityId` matches one of the following values */
110
+ @example(#{
111
+ operator: Filters.ArrayOperators.in,
112
+ value: #["ad3b469a-d89a-42d3-c439-6c1234567890"],
113
+ })
114
+ opportunityId?: Filters.StringArrayFilter;
115
+
116
+ /** `competitionId` matches one of the following values */
117
+ @example(#{
118
+ operator: Filters.ArrayOperators.in,
119
+ value: #["123e4567-e89b-12d3-a456-426614174000"],
120
+ })
121
+ competitionId?: Filters.StringArrayFilter;
122
+
123
+ /** `submittedAt` is between the given range */
124
+ @example(#{
125
+ operator: Filters.RangeOperators.between,
126
+ value: #{
127
+ min: Types.isoDate.fromISO("2025-01-01"),
128
+ max: Types.isoDate.fromISO("2025-01-30"),
129
+ },
130
+ })
131
+ submittedAtRange?: Filters.DateRangeFilter;
132
+
133
+ /** `status.value` matches one of the following values */
134
+ @example(#{
135
+ operator: Filters.ArrayOperators.in,
136
+ value: #["submitted", "accepted"],
137
+ })
138
+ status?: Filters.StringArrayFilter;
139
+ }
140
+
141
+ // #########################################################
142
+ // AppSorting
143
+ // #########################################################
144
+
145
+ /** The fields that can be used to sort applications */
146
+ @Versioning.added(CommonGrants.Versions.v0_3)
147
+ enum AppSortBy {
148
+ lastModifiedAt,
149
+ createdAt,
150
+ submittedAt,
151
+ status: "status.value",
152
+ opportunityId,
153
+ competitionId,
154
+ custom,
155
+ }
156
+
157
+ /** Sorting parameters for applications */
158
+ @Versioning.added(CommonGrants.Versions.v0_3)
159
+ model AppSorting extends Sorting.SortBodyParams {
160
+ /** The field to sort by */
161
+ @example(AppSortBy.opportunityId)
162
+ sortBy: AppSortBy;
163
+ }
164
+
87
165
  // #########################################################
88
166
  // Examples
89
167
  // #########################################################
@@ -110,14 +188,36 @@ namespace Examples.Application {
110
188
  ...Examples.FormResponse.formResponse,
111
189
  };
112
190
 
191
+ const attachmentsCustomField = #{
192
+ name: "attachments",
193
+ fieldType: Fields.CustomFieldType.object,
194
+ value: #{
195
+ contacts: Fields.Examples.File.pdfFile,
196
+ budget: Fields.Examples.File.excelFile,
197
+ },
198
+ description: "The attachments for the application",
199
+ };
200
+
201
+ const applicationZipFileCustomField = #{
202
+ name: "applicationZipFile",
203
+ fieldType: Fields.CustomFieldType.object,
204
+ value: Fields.Examples.File.zipFile,
205
+ description: "The zip file for the application",
206
+ };
207
+
113
208
  const applicationBase = #{
114
209
  id: "123e4567-e89b-12d3-a456-426614174000",
115
210
  name: "My Application",
116
211
  competitionId: "123e4567-e89b-12d3-a456-426614174000",
212
+ opportunityId: "ad3b469a-d89a-42d3-c439-6c1234567890",
117
213
  formResponses: #{ formA: formResponse },
118
214
  status: inProgressStatus,
119
215
  submittedAt: null,
120
216
  createdAt: utcDateTime.fromISO("2021-01-01T00:00:00Z"),
121
217
  lastModifiedAt: utcDateTime.fromISO("2021-01-01T00:00:00Z"),
218
+ customFields: #{
219
+ attachments: attachmentsCustomField,
220
+ applicationZipFile: applicationZipFileCustomField,
221
+ },
122
222
  };
123
223
  }
@@ -49,6 +49,7 @@ model CompetitionBase {
49
49
 
50
50
  /** The status of the competition */
51
51
  @example(Examples.Competition.status)
52
+ @Versioning.added(CommonGrants.Versions.v0_2)
52
53
  model CompetitionStatus {
53
54
  /** The status of the competition, from a predefined set of options */
54
55
  value: CompetitionStatusOptions;
@@ -69,6 +70,7 @@ model CompetitionStatus {
69
70
  * - `closed`: The competition is no longer accepting applications
70
71
  * - `custom`: A custom status
71
72
  */
73
+ @Versioning.added(CommonGrants.Versions.v0_2)
72
74
  enum CompetitionStatusOptions {
73
75
  open,
74
76
  closed,
@@ -81,9 +83,10 @@ enum CompetitionStatusOptions {
81
83
 
82
84
  /** Set of forms that need to be completed to apply to the competition. */
83
85
  @example(Examples.Competition.forms)
86
+ @Versioning.added(CommonGrants.Versions.v0_2)
84
87
  model CompetitionForms {
85
88
  /** The forms for the competition */
86
- forms: Record<Models.Form>;
89
+ forms: Record<Models.FormBase>;
87
90
 
88
91
  /** The validation rules for the competition forms */
89
92
  validation?: Record<unknown>;
@@ -93,7 +96,9 @@ model CompetitionForms {
93
96
  // CompetitionTimeline
94
97
  // #########################################################
95
98
 
99
+ /** Key dates in the competition's timeline. */
96
100
  @example(Examples.Competition.keyDates)
101
+ @Versioning.added(CommonGrants.Versions.v0_2)
97
102
  model CompetitionTimeline {
98
103
  /** The start date of the competition */
99
104
  openDate?: Fields.Event;
@@ -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 = #{
@@ -40,6 +40,7 @@ using Types;
40
40
  * ```
41
41
  */
42
42
  @doc("A funding opportunity")
43
+ @Versioning.added(CommonGrants.Versions.v0_1)
43
44
  model OpportunityBase {
44
45
  /** Globally unique id for the opportunity */
45
46
  @visibility(Lifecycle.Read)
@@ -19,6 +19,7 @@ using Fields;
19
19
  #{ title: "Total funding limit but no award range" }
20
20
  )
21
21
  @example(Examples.Funding.allFields, #{ title: "All fields defined" })
22
+ @Versioning.added(CommonGrants.Versions.v0_1)
22
23
  model OppFunding {
23
24
  /** Details about the funding available for this opportunity that don't fit other fields */
24
25
  details?: string;
@@ -8,6 +8,7 @@ namespace CommonGrants.Models;
8
8
  // ############################################################################
9
9
 
10
10
  /** Filters to apply when searching for opportunities */
11
+ @Versioning.added(CommonGrants.Versions.v0_1)
11
12
  model OppFilters {
12
13
  /** The default filters to apply to the search */
13
14
  ...OppDefaultFilters;
@@ -17,6 +18,7 @@ model OppFilters {
17
18
  }
18
19
 
19
20
  /** The standard set of filters supported for opportunity searches */
21
+ @Versioning.added(CommonGrants.Versions.v0_1)
20
22
  model OppDefaultFilters extends Record<Filters.DefaultFilter> {
21
23
  /** `status.value` matches one of the following values */
22
24
  @example(#{
@@ -82,6 +84,7 @@ model OppDefaultFilters extends Record<Filters.DefaultFilter> {
82
84
  // Sorting models
83
85
  // ############################################################################
84
86
 
87
+ @Versioning.added(CommonGrants.Versions.v0_1)
85
88
  enum OppSortBy {
86
89
  lastModifiedAt,
87
90
  createdAt,
@@ -95,6 +98,7 @@ enum OppSortBy {
95
98
  custom,
96
99
  }
97
100
 
101
+ @Versioning.added(CommonGrants.Versions.v0_1)
98
102
  model OppSorting extends Sorting.SortBodyParams {
99
103
  /** The field to sort by */
100
104
  @example(OppSortBy.lastModifiedAt)
@@ -10,6 +10,7 @@ namespace CommonGrants.Models;
10
10
  * - `closed`: The opportunity is no longer accepting applications
11
11
  * - `custom`: A custom status
12
12
  */
13
+ @Versioning.added(CommonGrants.Versions.v0_1)
13
14
  enum OppStatusOptions {
14
15
  forecasted,
15
16
  open,
@@ -24,6 +25,7 @@ enum OppStatusOptions {
24
25
  /** The status of the opportunity */
25
26
  @example(Examples.OppStatus.custom)
26
27
  @example(Examples.OppStatus.default)
28
+ @Versioning.added(CommonGrants.Versions.v0_1)
27
29
  model OppStatus {
28
30
  /** The status of the opportunity, from a predefined set of options */
29
31
  value: OppStatusOptions;
@@ -12,6 +12,7 @@ using Types;
12
12
 
13
13
  /** Key dates and events in the opportunity's timeline, such as when the opportunity is posted and closes */
14
14
  @example(Examples.Timeline.opportunity)
15
+ @Versioning.added(CommonGrants.Versions.v0_1)
15
16
  model OppTimeline {
16
17
  /** The date (and time) at which the opportunity is posted */
17
18
  postDate?: Event;
@@ -54,6 +54,7 @@ model ProposalOpportunity {
54
54
  // ProjectTimeline
55
55
  // #########################################################
56
56
 
57
+ /** Key dates for the project. */
57
58
  @Versioning.added(CommonGrants.Versions.v0_2)
58
59
  model ProjectTimeline {
59
60
  /** The start date of the period for which the funding is requested. */
@@ -73,6 +74,7 @@ model ProjectTimeline {
73
74
  // ProjectContacts
74
75
  // #########################################################
75
76
 
77
+ /** The points of contact for the proposal. */
76
78
  @Versioning.added(CommonGrants.Versions.v0_2)
77
79
  model ProposalContacts {
78
80
  /** The primary point of contact for the proposal. */
@@ -86,6 +88,7 @@ model ProposalContacts {
86
88
  // ProposalOrgs
87
89
  // #########################################################
88
90
 
91
+ /** The organizations that are requesting funding or supporting the proposal. */
89
92
  @Versioning.added(CommonGrants.Versions.v0_2)
90
93
  model ProposalOrgs {
91
94
  /** The primary organization that is requesting funding. */
@@ -8,6 +8,7 @@ using TypeSpec.JsonSchema;
8
8
  namespace CommonGrants.Pagination;
9
9
 
10
10
  /** Query parameters for paginated routes */
11
+ @Versioning.added(CommonGrants.Versions.v0_1)
11
12
  model PaginatedQueryParams {
12
13
  /** The page to return */
13
14
  @query
@@ -23,6 +24,7 @@ model PaginatedQueryParams {
23
24
  }
24
25
 
25
26
  /** Body parameters for paginated routes */
27
+ @Versioning.added(CommonGrants.Versions.v0_1)
26
28
  model PaginatedBodyParams {
27
29
  /** The page to return */
28
30
  @pageIndex
@@ -36,6 +38,7 @@ model PaginatedBodyParams {
36
38
  }
37
39
 
38
40
  /** Details about the paginated results */
41
+ @Versioning.added(CommonGrants.Versions.v0_1)
39
42
  model PaginatedResultsInfo {
40
43
  /** Current page number (indexing starts at 1) */
41
44
  @example(1)
@@ -14,6 +14,7 @@ namespace CommonGrants.Responses;
14
14
  */
15
15
  @error
16
16
  @doc("A non-2xx response schema")
17
+ @Versioning.added(CommonGrants.Versions.v0_1)
17
18
  model Error {
18
19
  @example(400)
19
20
  status: int32;
@@ -8,6 +8,7 @@ namespace CommonGrants.Responses;
8
8
  // Default success response
9
9
  // ############################################################################
10
10
 
11
+ @Versioning.added(CommonGrants.Versions.v0_1)
11
12
  model Success {
12
13
  @example(200)
13
14
  status: int32;
@@ -37,6 +38,7 @@ model Success {
37
38
  * ```
38
39
  */
39
40
  @doc("A 200 response with data")
41
+ @Versioning.added(CommonGrants.Versions.v0_1)
40
42
  model Ok<T> extends Success {
41
43
  // Inherit the 200 status code
42
44
  ...Http.OkResponse;
@@ -66,6 +68,7 @@ model Ok<T> extends Success {
66
68
  * ```
67
69
  */
68
70
  @doc("A 200 response with a paginated list of items")
71
+ @Versioning.added(CommonGrants.Versions.v0_1)
69
72
  model Paginated<T> extends Success {
70
73
  // Inherit the 200 status code
71
74
  ...Http.OkResponse;
@@ -98,6 +101,8 @@ model Paginated<T> extends Success {
98
101
  * alias CustomModelSortedResponse = Responses.Sorted<CustomModel>;
99
102
  * ```
100
103
  */
104
+ @doc("A paginated list of items with a sort order")
105
+ @Versioning.added(CommonGrants.Versions.v0_1)
101
106
  model Sorted<T> {
102
107
  // Inherit the properties of the Paginated response
103
108
  ...Paginated<T>;
@@ -132,6 +137,8 @@ model Sorted<T> {
132
137
  * alias CustomModelFilteredResponse = Responses.Filtered<CustomModel, CustomFilter>;
133
138
  * ```
134
139
  */
140
+ @doc("A paginated list of items with a filter")
141
+ @Versioning.added(CommonGrants.Versions.v0_1)
135
142
  model Filtered<ItemsT, FilterT> extends Success {
136
143
  // Inherit the properties of the Sorted response
137
144
  ...Sorted<ItemsT>;
@@ -153,6 +160,7 @@ model Filtered<ItemsT, FilterT> extends Success {
153
160
  *
154
161
  * @template T The schema for the value of the `"data"` property in this response
155
162
  */
163
+ @Versioning.added(CommonGrants.Versions.v0_1)
156
164
  model Created<T> extends Success {
157
165
  // Inherit the 201 status code
158
166
  ...Http.CreatedResponse;
@@ -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
+ @post
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
  }
@@ -18,12 +18,14 @@ using TypeSpec.JsonSchema;
18
18
  @jsonSchema
19
19
  namespace CommonGrants.Sorting;
20
20
 
21
+ @Versioning.added(CommonGrants.Versions.v0_1)
21
22
  enum SortOrder {
22
23
  asc,
23
24
  desc,
24
25
  }
25
26
 
26
27
  /** Query parameters for sorting */
28
+ @Versioning.added(CommonGrants.Versions.v0_1)
27
29
  model SortQueryParams {
28
30
  /** The field to sort by */
29
31
  @query
@@ -42,6 +44,7 @@ model SortQueryParams {
42
44
  }
43
45
 
44
46
  /** Sorting parameters included in the request body */
47
+ @Versioning.added(CommonGrants.Versions.v0_1)
45
48
  model SortBodyParams {
46
49
  /** The field to sort by */
47
50
  @example("lastModifiedAt")
@@ -57,6 +60,7 @@ model SortBodyParams {
57
60
  }
58
61
 
59
62
  /** Information about the sort order of the items returned */
63
+ @Versioning.added(CommonGrants.Versions.v0_1)
60
64
  model SortedResultsInfo {
61
65
  /** The field results are sorted by, or "custom" if an implementation-defined sort key is used */
62
66
  @example("lastModifiedAt")
@@ -28,6 +28,7 @@ namespace CommonGrants.Types;
28
28
  /** A universally unique identifier */
29
29
  @example("30a12e5e-5940-4c08-921c-17a8960fcf4b")
30
30
  @format("uuid")
31
+ @Versioning.added(CommonGrants.Versions.v0_1)
31
32
  scalar uuid extends string;
32
33
 
33
34
  /** An email address */
@@ -67,6 +68,7 @@ scalar duns extends string;
67
68
  @example("100", #{ title: "Scale 0" })
68
69
  @example("100.5", #{ title: "Scale 1" })
69
70
  @example("-100.5", #{ title: "Negative, scale 2" })
71
+ @Versioning.added(CommonGrants.Versions.v0_1)
70
72
  scalar decimalString extends string;
71
73
 
72
74
  // ########################################
@@ -75,10 +77,12 @@ scalar decimalString extends string;
75
77
 
76
78
  /** A time on a clock, without a timezone, in ISO 8601 format HH:mm:ss */
77
79
  @example(isoTime.fromISO("17:00:00"))
80
+ @Versioning.added(CommonGrants.Versions.v0_1)
78
81
  scalar isoTime extends plainTime;
79
82
 
80
83
  /** A date on a calendar in ISO 8601 format YYYY-MM-DD */
81
84
  @example(isoDate.fromISO("2025-01-01"))
85
+ @Versioning.added(CommonGrants.Versions.v0_1)
82
86
  scalar isoDate extends plainDate;
83
87
 
84
88
  /** A calendar year */
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.4",
3
+ "version": "0.3.0",
4
4
  "description": "TypeSpec library for defining grant opportunity data models and APIs",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "@eslint/js": "^9.18.0",
52
- "@types/node": "^20.10.6",
52
+ "@types/node": "^20.19.23",
53
53
  "eslint": "^9.18.0",
54
54
  "globals": "^15.14.0",
55
55
  "prettier": "^3.4.2",