@common-grants/core 0.1.0-alpha.7 → 0.1.0-alpha.8
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 +29 -0
- package/lib/{models → core/fields}/custom-field.tsp +2 -2
- package/lib/{models → core/fields}/event.tsp +5 -1
- package/lib/core/fields/index.tsp +6 -0
- package/lib/{models → core/fields}/metadata.tsp +1 -1
- package/lib/{models → core/fields}/money.tsp +5 -1
- package/lib/core/index.tsp +8 -0
- package/lib/{models → core/models}/index.tsp +7 -10
- package/lib/{models/opportunity/index.tsp → core/models/opportunity/base.tsp} +7 -5
- package/lib/{models → core/models}/opportunity/funding.tsp +4 -1
- package/lib/core/models/opportunity/index.tsp +6 -0
- package/lib/core/models/opportunity/status.tsp +32 -0
- package/lib/{models → core/models}/opportunity/timeline.tsp +6 -3
- package/lib/{responses/errors.tsp → core/responses/error.tsp} +3 -1
- package/lib/{responses → core/responses}/index.tsp +2 -2
- package/lib/{responses → core/responses}/success.tsp +3 -1
- package/lib/core/routes/index.tsp +23 -0
- package/lib/{routes → core/routes}/opportunities.tsp +14 -26
- package/lib/core/routes/utils.tsp +19 -0
- package/lib/{models/base.tsp → core/types.tsp} +1 -1
- package/lib/main.tsp +83 -18
- package/package.json +1 -1
- package/lib/models/custom-enum.tsp +0 -27
- package/lib/models/opportunity/status.tsp +0 -33
- package/lib/routes/index.tsp +0 -8
package/lib/api.tsp
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Import Schemas.and Routes to make them available outside the package
|
|
2
|
+
import "./core/index.tsp";
|
|
3
|
+
import "@typespec/http";
|
|
4
|
+
|
|
5
|
+
using Core;
|
|
6
|
+
|
|
7
|
+
using TypeSpec.Http;
|
|
8
|
+
|
|
9
|
+
/** The base OpenAPI specification for a CommonGrants API
|
|
10
|
+
*
|
|
11
|
+
* In order for an API to be "compliant" with the CommonGrants protocol,
|
|
12
|
+
* it must implement all of the routes with the "required" tag in this specification.
|
|
13
|
+
*/
|
|
14
|
+
@service({
|
|
15
|
+
title: "CommonGrants Base API",
|
|
16
|
+
})
|
|
17
|
+
namespace CommonGrants.API;
|
|
18
|
+
|
|
19
|
+
@tag("Opportunities")
|
|
20
|
+
@route("/opportunities")
|
|
21
|
+
namespace Opportunities {
|
|
22
|
+
alias Router = Routes.Opportunities;
|
|
23
|
+
|
|
24
|
+
@tag("required")
|
|
25
|
+
op List is Router.list;
|
|
26
|
+
|
|
27
|
+
@tag("required")
|
|
28
|
+
op Read is Router.read;
|
|
29
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
namespace
|
|
1
|
+
namespace Core.Fields;
|
|
2
2
|
|
|
3
3
|
// ########################################
|
|
4
4
|
// Field types definition
|
|
@@ -14,7 +14,7 @@ enum CustomFieldType {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
// ########################################
|
|
17
|
-
//
|
|
17
|
+
// Model definition
|
|
18
18
|
// ########################################
|
|
19
19
|
|
|
20
20
|
/** Model for defining custom fields that are specific to a given implementation.
|
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import "@typespec/json-schema";
|
|
2
2
|
|
|
3
|
-
// Import individual
|
|
3
|
+
// Import individual schemas to provide a consistent interface
|
|
4
4
|
// and make them available throughout the namespace
|
|
5
|
-
import "./base.tsp";
|
|
6
|
-
import "./custom-field.tsp";
|
|
7
|
-
import "./money.tsp";
|
|
8
|
-
import "./event.tsp";
|
|
9
|
-
import "./metadata.tsp";
|
|
10
|
-
import "./custom-enum.tsp";
|
|
11
5
|
import "./opportunity/index.tsp";
|
|
12
6
|
|
|
13
7
|
using TypeSpec.JsonSchema;
|
|
14
8
|
|
|
15
|
-
/** Namespace for
|
|
16
|
-
@jsonSchema // and emit these
|
|
17
|
-
namespace
|
|
9
|
+
/** Namespace for Core that can be used in API routes */
|
|
10
|
+
@jsonSchema // and emit these Schemas.as JSON schemas
|
|
11
|
+
namespace Core.Models;
|
|
18
12
|
|
|
19
13
|
/** The base model for a funding opportunity.
|
|
20
14
|
*
|
|
@@ -23,6 +17,9 @@ namespace CommonGrants.Models;
|
|
|
23
17
|
* @example How to declare a new Opportunity model with custom fields
|
|
24
18
|
*
|
|
25
19
|
* ```typespec
|
|
20
|
+
* using Core.Fields;
|
|
21
|
+
* using Core.Models;
|
|
22
|
+
*
|
|
26
23
|
* model Agency extends CustomField {
|
|
27
24
|
* type: CustomFieldType.string;
|
|
28
25
|
*
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import "@typespec/json-schema";
|
|
2
|
-
|
|
3
1
|
import "./status.tsp";
|
|
4
2
|
import "./funding.tsp";
|
|
5
3
|
import "./timeline.tsp";
|
|
4
|
+
import "../../fields/index.tsp";
|
|
5
|
+
import "../../types.tsp";
|
|
6
|
+
|
|
7
|
+
/** Namespace for Core that are specific to funding opportunities */
|
|
8
|
+
namespace Core.Models.Opportunity;
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
namespace CommonGrants.Models.Opportunity;
|
|
10
|
+
using Core.Fields;
|
|
11
|
+
using Core.Types;
|
|
10
12
|
|
|
11
13
|
// ########################################
|
|
12
14
|
// Model definition
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import "@typespec/json-schema";
|
|
2
|
+
import "@typespec/openapi3";
|
|
3
|
+
|
|
4
|
+
namespace Core.Models.Opportunity;
|
|
5
|
+
|
|
6
|
+
// ########################################
|
|
7
|
+
// Opportunity status options
|
|
8
|
+
// ########################################
|
|
9
|
+
|
|
10
|
+
/** The set of values accepted for opportunity status */
|
|
11
|
+
enum OppStatusOptions {
|
|
12
|
+
forecasted,
|
|
13
|
+
open,
|
|
14
|
+
closed,
|
|
15
|
+
custom,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// ########################################
|
|
19
|
+
// Opportunity status model
|
|
20
|
+
// ########################################
|
|
21
|
+
|
|
22
|
+
/** The status of the opportunity */
|
|
23
|
+
model OppStatus {
|
|
24
|
+
/** The status value */
|
|
25
|
+
value: OppStatusOptions;
|
|
26
|
+
|
|
27
|
+
/** A custom status value */
|
|
28
|
+
customValue?: string;
|
|
29
|
+
|
|
30
|
+
/** A human-readable description of the status */
|
|
31
|
+
description?: string;
|
|
32
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import "
|
|
2
|
-
import "
|
|
1
|
+
import "../../fields/index.tsp";
|
|
2
|
+
import "../../types.tsp";
|
|
3
3
|
|
|
4
|
-
namespace
|
|
4
|
+
namespace Core.Models.Opportunity;
|
|
5
|
+
|
|
6
|
+
using Core.Fields;
|
|
7
|
+
using Core.Types;
|
|
5
8
|
|
|
6
9
|
// ########################################
|
|
7
10
|
// Model definition
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import "@typespec/http";
|
|
2
|
+
import "@typespec/rest";
|
|
3
|
+
|
|
4
|
+
// Import individual route files to provide a consistent interface
|
|
5
|
+
import "./opportunities.tsp";
|
|
6
|
+
|
|
7
|
+
/** A series of interfaces for CommonGrants API routes
|
|
8
|
+
*
|
|
9
|
+
* @example How to use the `Routes` namespace
|
|
10
|
+
*
|
|
11
|
+
* ```tsp
|
|
12
|
+
* import "@common-grants/core";
|
|
13
|
+
*
|
|
14
|
+
* using CommonGrants;
|
|
15
|
+
*
|
|
16
|
+
* namespace MyRoutes {
|
|
17
|
+
* alias OpportunityRouter = Routes.Opportunities;
|
|
18
|
+
*
|
|
19
|
+
* op List is OpportunityRouter.list;
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
namespace Core.Routes;
|
|
@@ -1,26 +1,14 @@
|
|
|
1
1
|
import "../models/index.tsp";
|
|
2
2
|
import "../responses/index.tsp";
|
|
3
|
+
import "./utils.tsp";
|
|
3
4
|
|
|
4
5
|
// Define the top-level namespace for CommonGrants routes
|
|
5
|
-
namespace
|
|
6
|
+
namespace Core.Routes;
|
|
6
7
|
|
|
7
8
|
// Expose the contents of the Http and Rest namespaces
|
|
8
9
|
// these include the decorators @route, @get, etc.
|
|
9
10
|
using TypeSpec.Http;
|
|
10
|
-
using
|
|
11
|
-
using Responses;
|
|
12
|
-
|
|
13
|
-
model PaginatedQuery {
|
|
14
|
-
/** The page to return */
|
|
15
|
-
@query
|
|
16
|
-
@pageIndex
|
|
17
|
-
page?: int32 = 1;
|
|
18
|
-
|
|
19
|
-
/** The number of items to return per page */
|
|
20
|
-
@query
|
|
21
|
-
@pageSize
|
|
22
|
-
perPage?: int32 = 100;
|
|
23
|
-
}
|
|
11
|
+
using Core;
|
|
24
12
|
|
|
25
13
|
/** A re-usable interface for an Opportunities router
|
|
26
14
|
*
|
|
@@ -37,14 +25,13 @@ model PaginatedQuery {
|
|
|
37
25
|
* ```typespec
|
|
38
26
|
* using TypeSpec.Http;
|
|
39
27
|
*
|
|
40
|
-
* @tag("
|
|
28
|
+
* @tag("Opportunities")
|
|
41
29
|
* @route("/opportunities/")
|
|
42
30
|
* namespace Opportunities {
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* op list is Router.list;
|
|
46
|
-
* op read is Router.read<CustomOpportunity>;
|
|
31
|
+
* alias Router = Routes.Opportunities
|
|
47
32
|
*
|
|
33
|
+
* op list is Router.list;
|
|
34
|
+
* op read is Router.read<CustomOpportunity>;
|
|
48
35
|
* }
|
|
49
36
|
* ```
|
|
50
37
|
*/
|
|
@@ -52,24 +39,25 @@ interface Opportunities {
|
|
|
52
39
|
/** `GET /opportunities/` Get a paginated list of opportunities
|
|
53
40
|
*
|
|
54
41
|
* @template T Type of the paginated response model.
|
|
55
|
-
* Must be an extension of
|
|
42
|
+
* Must be an extension of Schemas.OpportunityBase. Default is Schemas.OpportunityBase.
|
|
56
43
|
*/
|
|
57
44
|
@summary("List opportunities")
|
|
58
45
|
@doc("Get a paginated list of opportunities, sorted by `lastModifiedAt` with most recent first.")
|
|
59
46
|
@list
|
|
60
47
|
list<T extends Models.OpportunityBase = Models.OpportunityBase>(
|
|
61
|
-
...PaginatedQuery,
|
|
62
|
-
):
|
|
48
|
+
...Utils.PaginatedQuery,
|
|
49
|
+
): Responses.Paginated<T> | Responses.Unauthorized;
|
|
63
50
|
|
|
64
51
|
/** `GET /opportunities/<id>` View opportunity details
|
|
65
52
|
*
|
|
66
53
|
* @template T Type of the response model.
|
|
67
|
-
* Must be an extension of
|
|
54
|
+
* Must be an extension of Schemas.OpportunityBase. Default is Schemas.OpportunityBase.
|
|
68
55
|
*/
|
|
69
56
|
@summary("View opportunity")
|
|
70
57
|
@doc("View additional details about an opportunity")
|
|
71
58
|
@get
|
|
72
59
|
read<T extends Models.OpportunityBase = Models.OpportunityBase>(
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
/** The ID of the opportunity to view */
|
|
61
|
+
@path id: Types.uuid,
|
|
62
|
+
): Responses.Ok<T> | Responses.NotFound | Responses.Unauthorized;
|
|
75
63
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import "@typespec/http";
|
|
2
|
+
|
|
3
|
+
using TypeSpec.Http;
|
|
4
|
+
|
|
5
|
+
/** Utility models and functions for API routes */
|
|
6
|
+
namespace Core.Routes.Utils;
|
|
7
|
+
|
|
8
|
+
/** A set of query parameters for paginated routes */
|
|
9
|
+
model PaginatedQuery {
|
|
10
|
+
/** The page to return */
|
|
11
|
+
@query
|
|
12
|
+
@pageIndex
|
|
13
|
+
page?: int32 = 1;
|
|
14
|
+
|
|
15
|
+
/** The number of items to return per page */
|
|
16
|
+
@query
|
|
17
|
+
@pageSize
|
|
18
|
+
pageSize?: int32 = 100;
|
|
19
|
+
}
|
package/lib/main.tsp
CHANGED
|
@@ -3,27 +3,92 @@
|
|
|
3
3
|
// https://typespec.io/docs/extending-typespec/basics/#h-add-your-main-typespec-file
|
|
4
4
|
import "../dist/src/index.js";
|
|
5
5
|
|
|
6
|
-
// Import
|
|
7
|
-
import "./
|
|
8
|
-
import "./
|
|
6
|
+
// Import items from the Core namespace to make them available outside the package
|
|
7
|
+
import "./core/index.tsp";
|
|
8
|
+
import "./api.tsp";
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
namespace CommonGrants;
|
|
11
11
|
|
|
12
|
-
/**
|
|
12
|
+
/** Base data types, e.g. `uuid` and `isoDate`, used to build more complex fields and models
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* @example How to use the `Types` namespace
|
|
15
|
+
*
|
|
16
|
+
* ```tsp
|
|
17
|
+
* import "@common-grants/core";
|
|
18
|
+
*
|
|
19
|
+
* using CommonGrants; // exposes the Types namespace
|
|
20
|
+
*
|
|
21
|
+
* model MyModel {
|
|
22
|
+
* id: Types.uuid;
|
|
23
|
+
* createdAt: Types.isoDate;
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
alias Types = Core.Types;
|
|
28
|
+
|
|
29
|
+
/** A standard set of fields, e.g. `money` that can be reused across models
|
|
30
|
+
*
|
|
31
|
+
* @example How to use the `Fields` namespace
|
|
32
|
+
*
|
|
33
|
+
* ```tsp
|
|
34
|
+
* import "@common-grants/core";
|
|
35
|
+
*
|
|
36
|
+
* using CommonGrants; // exposes the Fields namespace
|
|
37
|
+
*
|
|
38
|
+
* model MyModel {
|
|
39
|
+
* amount: Fields.money;
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
alias Fields = Core.Fields;
|
|
44
|
+
|
|
45
|
+
/** A standardized set of response schemas for CommonGrants API routes
|
|
46
|
+
*
|
|
47
|
+
* @example How to use the `Responses` namespace
|
|
48
|
+
*
|
|
49
|
+
* ```tsp
|
|
50
|
+
* import "@typespec/http";
|
|
51
|
+
* import "@common-grants/core";
|
|
52
|
+
*
|
|
53
|
+
* using CommonGrants; // exposes the Responses namespace
|
|
54
|
+
* using TypeSpec.Http;
|
|
55
|
+
*
|
|
56
|
+
* @route("/pets")
|
|
57
|
+
* namespace Pets {
|
|
58
|
+
* @get
|
|
59
|
+
* getPets(): Responses.Ok<Pet> | Responses.Unauthorized;
|
|
60
|
+
* }
|
|
61
|
+
* ```
|
|
16
62
|
*/
|
|
17
|
-
|
|
18
|
-
title: "Base API",
|
|
19
|
-
})
|
|
20
|
-
namespace CommonGrants.API;
|
|
63
|
+
alias Responses = Core.Responses;
|
|
21
64
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
65
|
+
/** A collection of models for the CommonGrants API
|
|
66
|
+
*
|
|
67
|
+
* @example How to use the `Models` namespace
|
|
68
|
+
*
|
|
69
|
+
* ```tsp
|
|
70
|
+
* import "@common-grants/core";
|
|
71
|
+
*
|
|
72
|
+
* using CommonGrants; // exposes the Models namespace
|
|
73
|
+
*
|
|
74
|
+
* model MyModel extends Models.OpportunityBase {}
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
alias Models = Core.Models;
|
|
26
78
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
79
|
+
/** A series of routing interfaces for CommonGrants API endpoints
|
|
80
|
+
*
|
|
81
|
+
* @example How to use the `Routes` namespace
|
|
82
|
+
*
|
|
83
|
+
* ```tsp
|
|
84
|
+
* import "@common-grants/core";
|
|
85
|
+
*
|
|
86
|
+
* using CommonGrants; // exposes the Routes namespace
|
|
87
|
+
*
|
|
88
|
+
* namespace MyRoutes {
|
|
89
|
+
* alias OpportunityRouter = Routes.Opportunities;
|
|
90
|
+
*
|
|
91
|
+
* op List is OpportunityRouter.list;
|
|
92
|
+
* }
|
|
93
|
+
*/
|
|
94
|
+
alias Routes = Core.Routes;
|
package/package.json
CHANGED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
namespace CommonGrants.Models;
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A custom enum value, designed to be used as part of a union with known options
|
|
5
|
-
*
|
|
6
|
-
* @example How to use this CustomEnumValue in a union
|
|
7
|
-
*
|
|
8
|
-
* ```typespec
|
|
9
|
-
* union OpportunityStatus {
|
|
10
|
-
* open: {
|
|
11
|
-
* value: "open",
|
|
12
|
-
* description?: "Opportunity is actively accepting applications",
|
|
13
|
-
* },
|
|
14
|
-
* closed: {
|
|
15
|
-
* value: "closed",
|
|
16
|
-
* description?: "Opportunity is no longer accepting applications",
|
|
17
|
-
* },
|
|
18
|
-
* custom: CustomEnumValue,
|
|
19
|
-
* }
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
@doc("Custom value not included in the standard list of options.")
|
|
23
|
-
model CustomEnumValue {
|
|
24
|
-
value: "custom";
|
|
25
|
-
customValue: string;
|
|
26
|
-
description: string;
|
|
27
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import "@typespec/json-schema";
|
|
2
|
-
import "@typespec/openapi3";
|
|
3
|
-
|
|
4
|
-
import "../custom-enum.tsp";
|
|
5
|
-
|
|
6
|
-
namespace CommonGrants.Models.Opportunity;
|
|
7
|
-
|
|
8
|
-
/** Union of values accepted for opportunity status */
|
|
9
|
-
@JsonSchema.oneOf
|
|
10
|
-
@OpenAPI.oneOf
|
|
11
|
-
@discriminator("value")
|
|
12
|
-
union OppStatus {
|
|
13
|
-
/** Opportunity is anticipated, but not yet accepting applications */
|
|
14
|
-
forecasted: {
|
|
15
|
-
value: "forecasted",
|
|
16
|
-
description?: "Opportunity is anticipated, but not yet accepting applications",
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
/** Opportunity is actively accepting applications */
|
|
20
|
-
open: {
|
|
21
|
-
value: "open",
|
|
22
|
-
description?: "Opportunity is actively accepting applications",
|
|
23
|
-
},
|
|
24
|
-
|
|
25
|
-
/** Opportunity is no longer accepting applications */
|
|
26
|
-
closed: {
|
|
27
|
-
value: "closed",
|
|
28
|
-
description?: "Opportunity is no longer accepting applications",
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
/** Custom opportunity status */
|
|
32
|
-
custom: CustomEnumValue,
|
|
33
|
-
}
|