@common-grants/core 0.1.0-alpha.8 → 0.1.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 (40) hide show
  1. package/README.md +21 -62
  2. package/lib/api.tsp +23 -8
  3. package/lib/core/fields/address.tsp +86 -0
  4. package/lib/core/fields/custom-field.tsp +11 -9
  5. package/lib/core/fields/email.tsp +35 -0
  6. package/lib/core/fields/event.tsp +138 -16
  7. package/lib/core/fields/index.tsp +23 -1
  8. package/lib/core/fields/metadata.tsp +4 -3
  9. package/lib/core/fields/money.tsp +8 -7
  10. package/lib/core/fields/name.tsp +30 -0
  11. package/lib/core/fields/pcs.tsp +112 -0
  12. package/lib/core/fields/phone.tsp +65 -0
  13. package/lib/core/filters/base.tsp +83 -0
  14. package/lib/core/filters/date.tsp +38 -0
  15. package/lib/core/filters/index.tsp +40 -0
  16. package/lib/core/filters/money.tsp +38 -0
  17. package/lib/core/filters/numeric.tsp +50 -0
  18. package/lib/core/filters/string.tsp +31 -0
  19. package/lib/core/index.tsp +1 -1
  20. package/lib/core/models/application.tsp +142 -0
  21. package/lib/core/models/index.tsp +10 -24
  22. package/lib/core/models/opportunity/base.tsp +34 -38
  23. package/lib/core/models/opportunity/funding.tsp +16 -10
  24. package/lib/core/models/opportunity/index.tsp +2 -1
  25. package/lib/core/models/opportunity/search.tsp +102 -0
  26. package/lib/core/models/opportunity/status.tsp +22 -2
  27. package/lib/core/models/opportunity/timeline.tsp +23 -13
  28. package/lib/core/models/organization.tsp +105 -0
  29. package/lib/core/models/person.tsp +43 -0
  30. package/lib/core/pagination.tsp +56 -0
  31. package/lib/core/responses/error.tsp +1 -1
  32. package/lib/core/responses/index.tsp +22 -1
  33. package/lib/core/responses/success.tsp +84 -29
  34. package/lib/core/routes/index.tsp +5 -6
  35. package/lib/core/routes/opportunities.tsp +46 -7
  36. package/lib/core/sorting.tsp +75 -0
  37. package/lib/core/types.tsp +66 -7
  38. package/lib/main.tsp +0 -85
  39. package/package.json +16 -10
  40. package/lib/core/routes/utils.tsp +0 -19
@@ -4,36 +4,63 @@ import "./timeline.tsp";
4
4
  import "../../fields/index.tsp";
5
5
  import "../../types.tsp";
6
6
 
7
- /** Namespace for Core that are specific to funding opportunities */
8
- namespace Core.Models.Opportunity;
7
+ namespace CommonGrants.Models;
9
8
 
10
- using Core.Fields;
11
- using Core.Types;
9
+ using CommonGrants.Fields;
10
+ using CommonGrants.Types;
12
11
 
13
12
  // ########################################
14
13
  // Model definition
15
14
  // ########################################
16
15
 
17
- @doc("A funding opportunity") // Overrides internal docstrings when emitting OpenAPI
16
+ /** The base model for a funding opportunity.
17
+ *
18
+ * It supports customization by extending the `customFields` property.
19
+ *
20
+ * @example How to declare a new Opportunity model with custom fields
21
+ *
22
+ * ```typespec
23
+ * using CommonGrants.Fields;
24
+ * using CommonGrants.Models;
25
+ *
26
+ * model Agency extends CustomField {
27
+ * fieldType: CustomFieldType.string;
28
+ *
29
+ * @example("Department of Transportation")
30
+ * value: string;
31
+ * }
32
+ *
33
+ * model NewFields extends CustomFieldMap {
34
+ * agency: Agency;
35
+ * }
36
+ *
37
+ * model CustomOpportunity extends OpportunityBase {
38
+ * customFields: NewFields;
39
+ * }
40
+ * ```
41
+ */
42
+ @doc("A funding opportunity")
18
43
  model OpportunityBase {
19
44
  /** Globally unique id for the opportunity */
20
45
  @visibility(Lifecycle.Read)
21
46
  id: uuid;
22
47
 
23
48
  /** Title or name of the funding opportunity */
49
+ @example("Small business grant program")
24
50
  title: string;
25
51
 
26
52
  /** Status of the opportunity */
27
53
  status: OppStatus;
28
54
 
29
55
  /** Description of the opportunity's purpose and scope */
56
+ @example("This program provides funding to small businesses to help them grow and create jobs")
30
57
  description: string;
31
58
 
32
59
  /** Details about the funding available */
33
- fundingDetails: FundingDetails;
60
+ funding?: OppFunding;
34
61
 
35
62
  /** Key dates for the opportunity, such as when the application opens and closes */
36
- keyDates: OppTimeline;
63
+ keyDates?: OppTimeline;
37
64
 
38
65
  /** URL for the original source of the opportunity */
39
66
  source?: url;
@@ -44,34 +71,3 @@ model OpportunityBase {
44
71
  // Spreads the fields from the Metadata model into the Opportunity model
45
72
  ...SystemMetadata;
46
73
  }
47
-
48
- // ########################################
49
- // Model examples
50
- // ########################################
51
-
52
- namespace OpportunityExamples {
53
- /** A complete opportunity example with all optional fields defined */
54
- const complete = #{
55
- id: "049b4b15-f219-4037-901e-cd95ac32fbc8",
56
- source: "https://grants.gov/opportunity/123",
57
- title: "Healthcare Innovation Research Grant",
58
- description: "Funding for innovative healthcare delivery solutions",
59
- fundingDetails: FundingExamples.allFields,
60
- keyDates: #[EventExamples.openDate, EventExamples.deadline],
61
- customFields: #{
62
- programArea: CustomFieldExamples.programArea,
63
- eligibilityType: CustomFieldExamples.programArea,
64
- },
65
- ...MetadataExample.system,
66
- };
67
-
68
- /** A minimal opportunity example with only required fields */
69
- const minimal = #{
70
- id: "550e8400-e29b-41d4-a716-446655440001",
71
- source: "https://grants.gov/opportunity/456",
72
- title: "Small Business Innovation Grant",
73
- description: "Supporting small business innovation projects",
74
- fundingDetails: FundingExamples.onlyLimit,
75
- ...MetadataExample.system,
76
- };
77
- }
@@ -1,25 +1,28 @@
1
1
  import "../index.tsp";
2
2
  import "../../fields/index.tsp";
3
3
 
4
- namespace Core.Models.Opportunity;
4
+ namespace CommonGrants.Models;
5
5
 
6
- using Core.Fields;
6
+ using CommonGrants.Fields;
7
7
 
8
8
  // ########################################
9
9
  // Model definition
10
10
  // ########################################
11
11
 
12
12
  /** Details about the funding available for this opportunity */
13
- @example(FundingExamples.allFields, #{ title: "All fields defined" })
14
13
  @example(
15
- FundingExamples.awardRange,
14
+ Examples.Funding.awardRange,
16
15
  #{ title: "Award range but no total limit" }
17
16
  )
18
17
  @example(
19
- FundingExamples.onlyLimit,
18
+ Examples.Funding.onlyLimit,
20
19
  #{ title: "Total funding limit but no award range" }
21
20
  )
22
- model FundingDetails {
21
+ @example(Examples.Funding.allFields, #{ title: "All fields defined" })
22
+ model OppFunding {
23
+ /** Details about the funding available for this opportunity that don't fit other fields */
24
+ details?: string;
25
+
23
26
  /** Total amount of funding available for this opportunity */
24
27
  totalAmountAvailable?: Money;
25
28
 
@@ -43,8 +46,9 @@ model FundingDetails {
43
46
  // Model examples
44
47
  // ########################################
45
48
 
46
- namespace FundingExamples {
47
- /** A FundingDetails example in which all of the fields are defined */
49
+ /** Examples of the OppFunding model */
50
+ namespace Examples.Funding {
51
+ /** An OppFunding example in which all of the fields are defined */
48
52
  const allFields = #{
49
53
  totalAmountAvailable: #{ amount: "1000000.00", currency: "USD" },
50
54
  minAwardAmount: #{ amount: "10000.00", currency: "USD" },
@@ -54,16 +58,18 @@ namespace FundingExamples {
54
58
  estimatedAwardCount: 10,
55
59
  };
56
60
 
57
- /** A FundingDetails example that has an award range but no total limit */
61
+ /** An OppFunding example that has an award range but no total limit */
58
62
  const awardRange = #{
63
+ details: "We'll be awarding between $10,000 and $50,000 per recipient",
59
64
  minAwardAmount: #{ amount: "10000.00", currency: "USD" },
60
65
  maxAwardAmount: #{ amount: "50000.00", currency: "USD" },
61
66
  minAwardCount: 5,
62
67
  maxAwardCount: 20,
63
68
  };
64
69
 
65
- /** A FundingDetails example that has a total limit but no award range */
70
+ /** An OppFunding example that has a total limit but no award range */
66
71
  const onlyLimit = #{
72
+ details: "This opportunity has a total funding limit of $1,000,000 but no specific award range",
67
73
  totalAmountAvailable: #{ amount: "1000000.00", currency: "USD" },
68
74
  estimatedAwardCount: 10,
69
75
  };
@@ -2,5 +2,6 @@ import "./status.tsp";
2
2
  import "./funding.tsp";
3
3
  import "./timeline.tsp";
4
4
  import "./base.tsp";
5
+ import "./search.tsp";
5
6
 
6
- namespace Core.Models.Opportunity;
7
+ namespace CommonGrants.Models;
@@ -0,0 +1,102 @@
1
+ import "../../filters/index.tsp";
2
+ import "../../sorting.tsp";
3
+
4
+ namespace CommonGrants.Models;
5
+
6
+ // ############################################################################
7
+ // Filter models
8
+ // ############################################################################
9
+
10
+ /** Filters to apply when searching for opportunities */
11
+ model OppFilters {
12
+ /** The default filters to apply to the search */
13
+ ...OppDefaultFilters;
14
+
15
+ /** Additional implementation-defined filters to apply to the search */
16
+ customFilters?: Record<Filters.DefaultFilter>;
17
+ }
18
+
19
+ /** The standard set of filters supported for opportunity searches */
20
+ model OppDefaultFilters extends Record<Filters.DefaultFilter> {
21
+ /** `status.value` matches one of the following values */
22
+ @example(#{
23
+ operator: Filters.ArrayOperators.in,
24
+ value: #["forecasted", "open"],
25
+ })
26
+ status?: Filters.StringArrayFilter;
27
+
28
+ /** `keyDates.closeDate` is between the given range */
29
+ @example(#{
30
+ operator: Filters.RangeOperators.between,
31
+ value: #{
32
+ min: Types.isoDate.fromISO("2021-01-01"),
33
+ max: Types.isoDate.fromISO("2021-01-02"),
34
+ },
35
+ })
36
+ closeDateRange?: Filters.DateRangeFilter;
37
+
38
+ /** `funding.totalAmountAvailable` is between the given range
39
+ *
40
+ * Funding amounts that are denominated in a different currency will
41
+ * be excluded from the search.
42
+ */
43
+ @example(#{
44
+ operator: Filters.RangeOperators.between,
45
+ value: #{
46
+ min: #{ amount: "1000000", currency: "USD" },
47
+ max: #{ amount: "2000000", currency: "USD" },
48
+ },
49
+ })
50
+ totalFundingAvailableRange?: Filters.MoneyRangeFilter;
51
+
52
+ /** `funding.minAwardAmount` is between the given range
53
+ *
54
+ * Funding amounts that are denominated in a different currency will
55
+ * be excluded from the search.
56
+ */
57
+ @example(#{
58
+ operator: Filters.RangeOperators.between,
59
+ value: #{
60
+ min: #{ amount: "1000000", currency: "USD" },
61
+ max: #{ amount: "2000000", currency: "USD" },
62
+ },
63
+ })
64
+ minAwardAmountRange?: Filters.MoneyRangeFilter;
65
+
66
+ /** `funding.maxAwardAmount` is between the given range.
67
+ *
68
+ * Funding amounts that are denominated in a different currency will
69
+ * be excluded from the search.
70
+ */
71
+ @example(#{
72
+ operator: Filters.RangeOperators.between,
73
+ value: #{
74
+ min: #{ amount: "1000000", currency: "USD" },
75
+ max: #{ amount: "2000000", currency: "USD" },
76
+ },
77
+ })
78
+ maxAwardAmountRange?: Filters.MoneyRangeFilter;
79
+ }
80
+
81
+ // ############################################################################
82
+ // Sorting models
83
+ // ############################################################################
84
+
85
+ enum OppSortBy {
86
+ lastModifiedAt,
87
+ createdAt,
88
+ title,
89
+ status: "status.value",
90
+ closeDate: "keyDates.closeDate",
91
+ maxAwardAmount: "funding.maxAwardAmount",
92
+ minAwardAmount: "funding.minAwardAmount",
93
+ totalFundingAvailable: "funding.totalAmountAvailable",
94
+ estimatedAwardCount: "funding.estimatedAwardCount",
95
+ custom,
96
+ }
97
+
98
+ model OppSorting extends Sorting.SortBodyParams {
99
+ /** The field to sort by */
100
+ @example(OppSortBy.lastModifiedAt)
101
+ sortBy: OppSortBy;
102
+ }
@@ -1,7 +1,7 @@
1
1
  import "@typespec/json-schema";
2
2
  import "@typespec/openapi3";
3
3
 
4
- namespace Core.Models.Opportunity;
4
+ namespace CommonGrants.Models;
5
5
 
6
6
  // ########################################
7
7
  // Opportunity status options
@@ -20,8 +20,10 @@ enum OppStatusOptions {
20
20
  // ########################################
21
21
 
22
22
  /** The status of the opportunity */
23
+ @example(Examples.OppStatus.custom)
24
+ @example(Examples.OppStatus.default)
23
25
  model OppStatus {
24
- /** The status value */
26
+ /** The status value, from a predefined set of options */
25
27
  value: OppStatusOptions;
26
28
 
27
29
  /** A custom status value */
@@ -30,3 +32,21 @@ model OppStatus {
30
32
  /** A human-readable description of the status */
31
33
  description?: string;
32
34
  }
35
+
36
+ // ########################################
37
+ // Opportunity status model examples
38
+ // ########################################
39
+
40
+ /** Examples of the OppStatus model */
41
+ namespace Examples.OppStatus {
42
+ const default = #{
43
+ value: OppStatusOptions.open,
44
+ description: "The opportunity is currently accepting applications",
45
+ };
46
+
47
+ const custom = #{
48
+ value: OppStatusOptions.custom,
49
+ customValue: "archived",
50
+ description: "The opportunity is archived and shouldn't appear in search results",
51
+ };
52
+ }
@@ -1,25 +1,25 @@
1
1
  import "../../fields/index.tsp";
2
2
  import "../../types.tsp";
3
3
 
4
- namespace Core.Models.Opportunity;
4
+ namespace CommonGrants.Models;
5
5
 
6
- using Core.Fields;
7
- using Core.Types;
6
+ using CommonGrants.Fields;
7
+ using CommonGrants.Types;
8
8
 
9
9
  // ########################################
10
10
  // Model definition
11
11
  // ########################################
12
12
 
13
- /** Key dates in the opportunity's timeline, such as when the application opens and closes */
14
- @example(TimelineExamples.opportunity)
13
+ /** Key dates and events in the opportunity's timeline, such as when the opportunity is posted and closes */
14
+ @example(Examples.Timeline.opportunity)
15
15
  model OppTimeline {
16
- /** The date (and time) at which the opportunity begins accepting applications */
17
- appOpens?: Event;
16
+ /** The date (and time) at which the opportunity is posted */
17
+ postDate?: Event;
18
18
 
19
- /** The final deadline for submitting applications */
20
- appDeadline?: Event;
19
+ /** The date (and time) at which the opportunity closes */
20
+ closeDate?: Event;
21
21
 
22
- /** An optional map of other key dates in the opportunity timeline
22
+ /** An optional map of other key dates or events in the opportunity timeline
23
23
  *
24
24
  * Examples might include a deadline for questions, anticipated award date, etc.
25
25
  */
@@ -30,16 +30,26 @@ model OppTimeline {
30
30
  // Model examples
31
31
  // ########################################
32
32
 
33
- namespace TimelineExamples {
33
+ /** Examples of the OppTimeline model */
34
+ namespace Examples.Timeline {
34
35
  const opportunity = #{
35
- appOpens: EventExamples.openDate,
36
- appDeadline: EventExamples.deadline,
36
+ postDate: Fields.Examples.Event.postedDate,
37
+ closeDate: Fields.Examples.Event.closeDate,
37
38
  otherDates: #{
38
39
  anticipatedAward: #{
39
40
  name: "Anticipated award date",
41
+ eventType: EventType.singleDate,
40
42
  date: isoDate.fromISO("2025-03-15"),
41
43
  description: "When we expect to announce awards for this opportunity.",
42
44
  },
45
+ applicationPeriod: Fields.Examples.Event.applicationPeriod,
46
+ performancePeriod: Fields.Examples.Event.performancePeriod,
47
+ infoSessions: #{
48
+ name: "Info sessions",
49
+ eventType: EventType.other,
50
+ details: "Every other Tuesday",
51
+ description: "Info sessions for the opportunity",
52
+ },
43
53
  },
44
54
  };
45
55
  }
@@ -0,0 +1,105 @@
1
+ import "../fields/index.tsp";
2
+
3
+ namespace CommonGrants.Models;
4
+
5
+ /** An organization that can apply for grants. */
6
+ @example(Examples.Organization.exampleOrg)
7
+ model OrganizationBase {
8
+ /** The organization's unique identifier. */
9
+ id: Types.uuid;
10
+
11
+ /** The organization's legal name as registered with relevant authorities. */
12
+ name: string;
13
+
14
+ /** The organization's type within the Philanthropy Classification System (PCS). */
15
+ orgType?: Fields.PCSOrgType;
16
+
17
+ /** The organization's Employer Identification Number (EIN), a unique identifier assigned by the IRS. */
18
+ ein?: Types.employerTaxId;
19
+
20
+ /** The organization's Unique Entity Identifier (UEI) from SAM.gov, used for federal contracting. */
21
+ uei?: Types.samUEI;
22
+
23
+ /** The organization's Data Universal Numbering System (DUNS) number, a unique identifier for businesses. */
24
+ duns?: Types.duns;
25
+
26
+ /** Collection of physical addresses associated with the organization. */
27
+ addresses?: Fields.AddressCollection;
28
+
29
+ /** Collection of phone numbers associated with the organization. */
30
+ phones?: Fields.PhoneCollection;
31
+
32
+ /** Collection of email addresses associated with the organization. */
33
+ emails?: Fields.EmailCollection;
34
+
35
+ /** The organization's mission statement. */
36
+ mission?: string;
37
+
38
+ /** The calendar year the organization was founded. */
39
+ yearFounded?: Types.calendarYear;
40
+
41
+ /** Collection of the organization's social media and web presence links. */
42
+ socials?: OrgSocialLinks;
43
+
44
+ /** Custom fields for the organization. */
45
+ customFields?: Record<Fields.CustomField>;
46
+ }
47
+
48
+ // #########################################################
49
+ // OrgSocialLinks
50
+ // #########################################################
51
+
52
+ /** A collection of social media and web presence links for an organization. */
53
+ @example(Examples.Organization.exampleSocials)
54
+ model OrgSocialLinks {
55
+ /** The organization's primary website URL. */
56
+ website?: url;
57
+
58
+ /** The organization's Facebook profile URL. */
59
+ facebook?: url;
60
+
61
+ /** The organization's Twitter/X profile URL. */
62
+ twitterOrX?: url;
63
+
64
+ /** The organization's BlueSky profile URL. */
65
+ bluesky?: url;
66
+
67
+ /** The organization's Instagram profile URL. */
68
+ instagram?: url;
69
+
70
+ /** The organization's LinkedIn profile URL. */
71
+ linkedin?: url;
72
+
73
+ /** Additional social media profiles not covered by the standard fields. */
74
+ otherSocials?: Record<url>;
75
+ }
76
+
77
+ // #########################################################
78
+ // Examples
79
+ // #########################################################
80
+
81
+ namespace Examples.Organization {
82
+ const exampleOrg = #{
83
+ id: "083b4567-e89d-42c8-a439-6c1234567890",
84
+ name: "Example Organization",
85
+ orgType: Fields.Examples.PCS.orgTypeTerm,
86
+ ein: "12-3456789",
87
+ uei: "ABC1234567890",
88
+ duns: "123456789012",
89
+ addresses: Fields.Examples.Address.orgCollection,
90
+ phones: Fields.Examples.Phone.orgCollection,
91
+ emails: Fields.Examples.Email.orgCollection,
92
+ mission: "To provide support and resources to the community.",
93
+ yearFounded: "2024",
94
+ socials: exampleSocials,
95
+ };
96
+
97
+ const exampleSocials = #{
98
+ website: "https://www.example.com",
99
+ facebook: "https://www.facebook.com/example",
100
+ twitterOrX: "https://x.com/example",
101
+ instagram: "https://www.instagram.com/example",
102
+ linkedin: "https://www.linkedin.com/company/example",
103
+ otherSocials: #{ youtube: "https://www.youtube.com/example" },
104
+ };
105
+ }
@@ -0,0 +1,43 @@
1
+ import "../fields/index.tsp";
2
+ import "../types.tsp";
3
+
4
+ namespace CommonGrants.Models;
5
+
6
+ /** A person affiliated with an organization or grant application. */
7
+ @example(Examples.Person.examplePerson)
8
+ model PersonBase {
9
+ /** The person's full name, including all relevant components (first, middle, last, etc.). */
10
+ name: Fields.Name;
11
+
12
+ /** The person's title, if applicable. */
13
+ title?: string;
14
+
15
+ /** Collection of physical addresses associated with the person. */
16
+ addresses?: Fields.AddressCollection;
17
+
18
+ /** Collection of phone numbers associated with the person. */
19
+ phones?: Fields.PhoneCollection;
20
+
21
+ /** Collection of email addresses associated with the person. */
22
+ emails?: Fields.EmailCollection;
23
+
24
+ /** The person's date of birth. */
25
+ dateOfBirth?: Types.isoDate;
26
+
27
+ /** Custom fields for the person. */
28
+ customFields?: Record<Fields.CustomField>;
29
+ }
30
+
31
+ // #########################################################
32
+ // Examples
33
+ // #########################################################
34
+
35
+ namespace Examples.Person {
36
+ const examplePerson = #{
37
+ name: Fields.Examples.Name.janeDoe,
38
+ title: "Chief Executive Officer",
39
+ addresses: Fields.Examples.Address.personalCollection,
40
+ phones: Fields.Examples.Phone.personalCollection,
41
+ emails: Fields.Examples.Email.personalCollection,
42
+ };
43
+ }
@@ -0,0 +1,56 @@
1
+ import "@typespec/http";
2
+
3
+ using TypeSpec.Http;
4
+ using TypeSpec.JsonSchema;
5
+ /** Models and utilities for pagination */
6
+ @jsonSchema
7
+ namespace CommonGrants.Pagination;
8
+
9
+ /** Query parameters for paginated routes */
10
+ model PaginatedQueryParams {
11
+ /** The page to return */
12
+ @query
13
+ @pageIndex
14
+ @minValue(1)
15
+ page?: int32 = 1;
16
+
17
+ /** The number of items to return per page */
18
+ @query
19
+ @pageSize
20
+ @minValue(1)
21
+ pageSize?: int32 = 100;
22
+ }
23
+
24
+ /** Body parameters for paginated routes */
25
+ model PaginatedBodyParams {
26
+ /** The page to return */
27
+ @pageIndex
28
+ @minValue(1)
29
+ page?: int32 = 1;
30
+
31
+ /** The number of items to return per page */
32
+ @pageSize
33
+ @minValue(1)
34
+ pageSize?: int32 = 100;
35
+ }
36
+
37
+ /** Details about the paginated results */
38
+ model PaginatedResultsInfo {
39
+ /** Current page number (indexing starts at 1) */
40
+ @example(1)
41
+ @minValue(1)
42
+ page: int32;
43
+
44
+ /** Number of items per page */
45
+ @example(20)
46
+ @minValue(1)
47
+ pageSize: integer;
48
+
49
+ /** Total number of items across all pages */
50
+ @example(100)
51
+ totalItems?: integer;
52
+
53
+ /** Total number of pages */
54
+ @example(5)
55
+ totalPages?: integer;
56
+ }
@@ -1,6 +1,6 @@
1
1
  import "@typespec/http";
2
2
 
3
- namespace Core.Responses;
3
+ namespace CommonGrants.Responses;
4
4
 
5
5
  /** A standard error response schema, used to create custom error responses
6
6
  *
@@ -3,4 +3,25 @@ import "@typespec/http";
3
3
  import "./error.tsp";
4
4
  import "./success.tsp";
5
5
 
6
- namespace Core.Responses;
6
+ using TypeSpec.JsonSchema;
7
+
8
+ /** A standardized set of response schemas for CommonGrants API routes
9
+ *
10
+ * @example How to use the `Responses` namespace
11
+ *
12
+ * ```typespec
13
+ * import "@typespec/http";
14
+ * import "@common-grants/core";
15
+ *
16
+ * using CommonGrants; // exposes the Responses namespace
17
+ * using TypeSpec.Http;
18
+ *
19
+ * @route("/pets")
20
+ * namespace Pets {
21
+ * @get
22
+ * op getPets(): Responses.Ok<Pet> | Responses.Unauthorized;
23
+ * }
24
+ * ```
25
+ */
26
+ @jsonSchema
27
+ namespace CommonGrants.Responses;