@makegov/tango-node 0.1.4
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/.editorconfig +13 -0
- package/.eslintrc.cjs +20 -0
- package/.prettierrc +8 -0
- package/CHANGELOG.md +15 -0
- package/LICENSE +21 -0
- package/README.md +331 -0
- package/dist/client.d.ts +48 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +321 -0
- package/dist/client.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +21 -0
- package/dist/config.js.map +1 -0
- package/dist/errors.d.ts +39 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +78 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/models/Agency.d.ts +8 -0
- package/dist/models/Agency.d.ts.map +1 -0
- package/dist/models/Agency.js +2 -0
- package/dist/models/Agency.js.map +1 -0
- package/dist/models/Contract.d.ts +17 -0
- package/dist/models/Contract.d.ts.map +1 -0
- package/dist/models/Contract.js +2 -0
- package/dist/models/Contract.js.map +1 -0
- package/dist/models/Department.d.ts +5 -0
- package/dist/models/Department.d.ts.map +1 -0
- package/dist/models/Department.js +2 -0
- package/dist/models/Department.js.map +1 -0
- package/dist/models/Entity.d.ts +11 -0
- package/dist/models/Entity.d.ts.map +1 -0
- package/dist/models/Entity.js +2 -0
- package/dist/models/Entity.js.map +1 -0
- package/dist/models/Forecast.d.ts +12 -0
- package/dist/models/Forecast.d.ts.map +1 -0
- package/dist/models/Forecast.js +2 -0
- package/dist/models/Forecast.js.map +1 -0
- package/dist/models/Grant.d.ts +10 -0
- package/dist/models/Grant.d.ts.map +1 -0
- package/dist/models/Grant.js +2 -0
- package/dist/models/Grant.js.map +1 -0
- package/dist/models/Location.d.ts +17 -0
- package/dist/models/Location.d.ts.map +1 -0
- package/dist/models/Location.js +2 -0
- package/dist/models/Location.js.map +1 -0
- package/dist/models/Notice.d.ts +9 -0
- package/dist/models/Notice.d.ts.map +1 -0
- package/dist/models/Notice.js +2 -0
- package/dist/models/Notice.js.map +1 -0
- package/dist/models/Opportunity.d.ts +11 -0
- package/dist/models/Opportunity.d.ts.map +1 -0
- package/dist/models/Opportunity.js +2 -0
- package/dist/models/Opportunity.js.map +1 -0
- package/dist/models/RecipientProfile.d.ts +12 -0
- package/dist/models/RecipientProfile.d.ts.map +1 -0
- package/dist/models/RecipientProfile.js +2 -0
- package/dist/models/RecipientProfile.js.map +1 -0
- package/dist/models/index.d.ts +11 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +2 -0
- package/dist/models/index.js.map +1 -0
- package/dist/shapes/explicitSchemas.d.ts +24 -0
- package/dist/shapes/explicitSchemas.d.ts.map +1 -0
- package/dist/shapes/explicitSchemas.js +1818 -0
- package/dist/shapes/explicitSchemas.js.map +1 -0
- package/dist/shapes/factory.d.ts +29 -0
- package/dist/shapes/factory.d.ts.map +1 -0
- package/dist/shapes/factory.js +93 -0
- package/dist/shapes/factory.js.map +1 -0
- package/dist/shapes/generator.d.ts +53 -0
- package/dist/shapes/generator.d.ts.map +1 -0
- package/dist/shapes/generator.js +117 -0
- package/dist/shapes/generator.js.map +1 -0
- package/dist/shapes/index.d.ts +8 -0
- package/dist/shapes/index.d.ts.map +1 -0
- package/dist/shapes/index.js +8 -0
- package/dist/shapes/index.js.map +1 -0
- package/dist/shapes/parser.d.ts +36 -0
- package/dist/shapes/parser.d.ts.map +1 -0
- package/dist/shapes/parser.js +169 -0
- package/dist/shapes/parser.js.map +1 -0
- package/dist/shapes/schema.d.ts +30 -0
- package/dist/shapes/schema.d.ts.map +1 -0
- package/dist/shapes/schema.js +63 -0
- package/dist/shapes/schema.js.map +1 -0
- package/dist/shapes/schemaTypes.d.ts +42 -0
- package/dist/shapes/schemaTypes.d.ts.map +1 -0
- package/dist/shapes/schemaTypes.js +2 -0
- package/dist/shapes/schemaTypes.js.map +1 -0
- package/dist/shapes/types.d.ts +46 -0
- package/dist/shapes/types.d.ts.map +1 -0
- package/dist/shapes/types.js +25 -0
- package/dist/shapes/types.js.map +1 -0
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/dates.d.ts +14 -0
- package/dist/utils/dates.d.ts.map +1 -0
- package/dist/utils/dates.js +25 -0
- package/dist/utils/dates.js.map +1 -0
- package/dist/utils/http.d.ts +23 -0
- package/dist/utils/http.d.ts.map +1 -0
- package/dist/utils/http.js +158 -0
- package/dist/utils/http.js.map +1 -0
- package/dist/utils/number.d.ts +14 -0
- package/dist/utils/number.d.ts.map +1 -0
- package/dist/utils/number.js +14 -0
- package/dist/utils/number.js.map +1 -0
- package/dist/utils/unflatten.d.ts +11 -0
- package/dist/utils/unflatten.d.ts.map +1 -0
- package/dist/utils/unflatten.js +49 -0
- package/dist/utils/unflatten.js.map +1 -0
- package/docs/API_REFERENCE.md +201 -0
- package/docs/DYNAMIC_MODELS.md +127 -0
- package/docs/SHAPES.md +94 -0
- package/eslint.config.js +37 -0
- package/package.json +73 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +18 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# Tango Node SDK – API Reference
|
|
2
|
+
|
|
3
|
+
This document provides the full API reference for the **Node.js / TypeScript**
|
|
4
|
+
version of the Tango SDK. It is a translation of the Python SDK documentation,
|
|
5
|
+
rewritten for JavaScript runtime semantics, async/await, and the TypeScript
|
|
6
|
+
type system.
|
|
7
|
+
|
|
8
|
+
## Importing
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { TangoClient, ShapeConfig } from "@makegov/tango-node";
|
|
12
|
+
// Models (optional)
|
|
13
|
+
import type { Contract } from "@makegov/tango-node/models";
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
All methods are async and return Promises.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Agencies
|
|
21
|
+
|
|
22
|
+
### `listAgencies(options?)`
|
|
23
|
+
|
|
24
|
+
List federal departments and subagencies.
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
const resp = await client.listAgencies({ page: 1, limit: 25 });
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
#### Parameters
|
|
31
|
+
|
|
32
|
+
| Name | Type | Description |
|
|
33
|
+
| ------- | -------- | ------------------------------------------- |
|
|
34
|
+
| `page` | `number` | Page number (default 1). |
|
|
35
|
+
| `limit` | `number` | Max results per page (default 25, max 100). |
|
|
36
|
+
|
|
37
|
+
#### Returns
|
|
38
|
+
|
|
39
|
+
`PaginatedResponse<AgencyLike>`
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### `getAgency(code)`
|
|
44
|
+
|
|
45
|
+
Fetch a single agency by its code.
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
const agency = await client.getAgency("2000");
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Returns a shaped Agency object. Responses are materialized via the dynamic model pipeline (dates parsed, nested objects built).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Business Types
|
|
56
|
+
|
|
57
|
+
### `listBusinessTypes(options?)`
|
|
58
|
+
|
|
59
|
+
Lists SBA/USASpending business type entries.
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
const types = await client.listBusinessTypes();
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Contracts
|
|
68
|
+
|
|
69
|
+
### `listContracts(options)`
|
|
70
|
+
|
|
71
|
+
Search and list contract records.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const resp = await client.listContracts({
|
|
75
|
+
keyword: "cloud",
|
|
76
|
+
naics_code: "541511",
|
|
77
|
+
shape: ShapeConfig.CONTRACTS_MINIMAL,
|
|
78
|
+
flat: true,
|
|
79
|
+
});
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Search / Filter Parameters
|
|
83
|
+
|
|
84
|
+
These mirror the Python SDK:
|
|
85
|
+
|
|
86
|
+
| Filter | Maps to API param |
|
|
87
|
+
| ---------------- | ----------------- |
|
|
88
|
+
| `keyword` | `search` |
|
|
89
|
+
| `naics_code` | `naics` |
|
|
90
|
+
| `psc_code` | `psc` |
|
|
91
|
+
| `recipient_name` | `recipient` |
|
|
92
|
+
| `recipient_uei` | `uei` |
|
|
93
|
+
| `set_aside_type` | `set_aside` |
|
|
94
|
+
|
|
95
|
+
Sorting:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
sort: "award_date",
|
|
99
|
+
order: "desc" // -> ordering="-award_date"
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Pagination + shaping options:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
shape: string,
|
|
106
|
+
flat: boolean,
|
|
107
|
+
flatLists: boolean,
|
|
108
|
+
page: number,
|
|
109
|
+
limit: number
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### Returns
|
|
113
|
+
|
|
114
|
+
`PaginatedResponse<Contract>` materialized according to the requested shape. Date/datetime fields are parsed, decimals normalized to strings, nested recipients, agencies, and locations are objects.
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Entities
|
|
119
|
+
|
|
120
|
+
### `listEntities(options)`
|
|
121
|
+
|
|
122
|
+
```ts
|
|
123
|
+
const resp = await client.listEntities({
|
|
124
|
+
search: "Acme",
|
|
125
|
+
shape: ShapeConfig.ENTITIES_MINIMAL,
|
|
126
|
+
});
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Filters:
|
|
130
|
+
|
|
131
|
+
- `search`
|
|
132
|
+
- any field names supported by the API
|
|
133
|
+
|
|
134
|
+
### `getEntity(uei, options?)`
|
|
135
|
+
|
|
136
|
+
Fetch a single entity by UEI or CAGE.
|
|
137
|
+
|
|
138
|
+
Returns a shaped entity object with nested addresses/fields based on the shape.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Forecasts
|
|
143
|
+
|
|
144
|
+
### `listForecasts(options)`
|
|
145
|
+
|
|
146
|
+
Forecast search, with optional shaping.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Opportunities
|
|
151
|
+
|
|
152
|
+
### `listOpportunities(options)`
|
|
153
|
+
|
|
154
|
+
Search SAM.gov opportunities with shaping.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## Notices
|
|
159
|
+
|
|
160
|
+
### `listNotices(options)`
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Grants
|
|
165
|
+
|
|
166
|
+
### `listGrants(options)`
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Error Types
|
|
171
|
+
|
|
172
|
+
All thrown by async methods:
|
|
173
|
+
|
|
174
|
+
- `TangoAPIError`
|
|
175
|
+
- `TangoAuthError`
|
|
176
|
+
- `TangoNotFoundError`
|
|
177
|
+
- `TangoRateLimitError`
|
|
178
|
+
- `TangoValidationError`
|
|
179
|
+
- `ShapeError`
|
|
180
|
+
- `ShapeParseError`
|
|
181
|
+
- `ShapeValidationError`
|
|
182
|
+
- `TypeGenerationError`
|
|
183
|
+
- `ModelInstantiationError`
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Pagination
|
|
188
|
+
|
|
189
|
+
All list endpoints return:
|
|
190
|
+
|
|
191
|
+
```ts
|
|
192
|
+
interface PaginatedResponse<T> {
|
|
193
|
+
count: number;
|
|
194
|
+
next: string | null;
|
|
195
|
+
previous: string | null;
|
|
196
|
+
pageMetadata: Record<string, unknown> | null;
|
|
197
|
+
results: T[];
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
You can follow `next` / `previous` manually or use your own wrapper.
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Tango Node SDK – Dynamic Models Guide
|
|
2
|
+
|
|
3
|
+
This document explains how the **Node.js dynamic shaping system** works.
|
|
4
|
+
It is a full translation of the Python `DEVELOPERS.md` shaping guide.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Tango’s dynamic modeling allows you to:
|
|
11
|
+
|
|
12
|
+
- Request _exactly the fields you want_
|
|
13
|
+
- Validate the shape string against Tango’s schemas
|
|
14
|
+
- Generate a typed model descriptor at runtime
|
|
15
|
+
- Materialize shaped objects using correct:
|
|
16
|
+
- date parsing
|
|
17
|
+
- datetime parsing
|
|
18
|
+
- decimal handling
|
|
19
|
+
- list vs scalar logic
|
|
20
|
+
- nested structure
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Components
|
|
25
|
+
|
|
26
|
+
### ShapeParser
|
|
27
|
+
|
|
28
|
+
Parses shape strings into a `ShapeSpec`.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { ShapeParser } from "@makegov/tango-node/shapes";
|
|
32
|
+
|
|
33
|
+
const parser = new ShapeParser();
|
|
34
|
+
const spec = parser.parse("key,piid,recipient(display_name)");
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### SchemaRegistry
|
|
38
|
+
|
|
39
|
+
Holds the field schemas for all models.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { SchemaRegistry } from "@makegov/tango-node/shapes";
|
|
43
|
+
|
|
44
|
+
const registry = new SchemaRegistry();
|
|
45
|
+
registry.getField("Contract", "award_date");
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### TypeGenerator
|
|
49
|
+
|
|
50
|
+
Builds a `GeneratedModel` descriptor from `(baseModel, shapeSpec)`.
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import { TypeGenerator } from "@makegov/tango-node/shapes";
|
|
54
|
+
|
|
55
|
+
const gen = new TypeGenerator();
|
|
56
|
+
const model = gen.generateModelDescriptor("Contract", spec);
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### ModelFactory
|
|
60
|
+
|
|
61
|
+
Takes a descriptor + raw API JSON and produces typed shaped objects. The TangoClient now uses this pipeline automatically after fetching data.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { TangoClient } from "@makegov/tango-node";
|
|
65
|
+
|
|
66
|
+
const client = new TangoClient({ apiKey: process.env.TANGO_API_KEY });
|
|
67
|
+
const contracts = await client.listContracts({
|
|
68
|
+
shape: "key,award_date,recipient(display_name)",
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// contracts.results are materialized via ModelFactory:
|
|
72
|
+
// - date/datetime parsed to Date
|
|
73
|
+
// - decimals normalized to string
|
|
74
|
+
// - nested structures enforced
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Example: Full Shaping Pipeline (manual)
|
|
80
|
+
|
|
81
|
+
```ts
|
|
82
|
+
const parser = new ShapeParser();
|
|
83
|
+
const spec = parser.parse("key,award_date,recipient(display_name)");
|
|
84
|
+
|
|
85
|
+
const gen = new TypeGenerator();
|
|
86
|
+
const descriptor = gen.generateModelDescriptor("Contract", spec);
|
|
87
|
+
|
|
88
|
+
const factory = new ModelFactory();
|
|
89
|
+
const shaped = factory.createOne("Contract", spec, {
|
|
90
|
+
key: "C-1",
|
|
91
|
+
award_date: "2024-01-15",
|
|
92
|
+
recipient: { display_name: "Acme" },
|
|
93
|
+
});
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`shaped` becomes:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
{
|
|
100
|
+
key: "C-1",
|
|
101
|
+
award_date: Date("2024-01-15"),
|
|
102
|
+
recipient: { display_name: "Acme" }
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Type Safety
|
|
109
|
+
|
|
110
|
+
Node SDK enforces shape correctness at runtime and guarantees nested structures. The client materializes responses through ModelFactory, so the shape schema is applied automatically. TypeScript interfaces are not codegenerated per shape at build time; the SDK exports lightweight model interfaces in `@makegov/tango-node/models` for convenience.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Caching
|
|
115
|
+
|
|
116
|
+
TypeGenerator caches descriptors with FIFO eviction.
|
|
117
|
+
|
|
118
|
+
ShapeParser also caches parse results.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Nested Models
|
|
123
|
+
|
|
124
|
+
If a field is nested in the schema (e.g. `"recipient"` → `RecipientProfile`),
|
|
125
|
+
the generator recursively builds the nested descriptor.
|
|
126
|
+
|
|
127
|
+
---
|
package/docs/SHAPES.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Tango Node SDK – Shaping Guide
|
|
2
|
+
|
|
3
|
+
A complete translation of the Python SHAPES.md document for Node.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Why Shapes?
|
|
8
|
+
|
|
9
|
+
Tango resources can have hundreds of fields. Shapes let you request:
|
|
10
|
+
|
|
11
|
+
- Only what you need
|
|
12
|
+
- In nested form
|
|
13
|
+
- With aliases
|
|
14
|
+
- With wildcards
|
|
15
|
+
- With flattening options
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Shape Grammar
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
shape := field_list
|
|
23
|
+
field_list := field ("," field)*
|
|
24
|
+
field := field_name [alias] [nested]
|
|
25
|
+
field_name := identifier | "*"
|
|
26
|
+
alias := "::" identifier
|
|
27
|
+
nested := "(" field_list ")"
|
|
28
|
+
identifier := [a-zA-Z_][a-zA-Z0-9_]*
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Examples
|
|
34
|
+
|
|
35
|
+
### Simple
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
shape: "key,piid,award_date";
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Nested
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
shape: "recipient(display_name,uei)";
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Aliases
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
shape: "recipient::vendor(display_name)";
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Wildcard
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
shape: "*";
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Wildcard nested
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
shape: "recipient(*)";
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Flat Responses
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
shape: ShapeConfig.CONTRACTS_MINIMAL,
|
|
71
|
+
flat: true
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The Tango API returns dotted keys; the SDK unflattens them:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
recipient.display_name → recipient.display_name
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Validation
|
|
83
|
+
|
|
84
|
+
ShapeParser enforces syntax.
|
|
85
|
+
|
|
86
|
+
TypeGenerator enforces semantic model rules (existence of fields, nested models).
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Performance Tips
|
|
91
|
+
|
|
92
|
+
- Use minimal shapes in production.
|
|
93
|
+
- Avoid full-wildcard unless you need all fields.
|
|
94
|
+
- Prefer shallow nested shapes for large nested structures.
|
package/eslint.config.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
|
3
|
+
import tsParser from "@typescript-eslint/parser";
|
|
4
|
+
import globals from "globals";
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
{
|
|
8
|
+
ignores: ["dist/**", "node_modules/**"],
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
files: ["**/*.ts"],
|
|
12
|
+
languageOptions: {
|
|
13
|
+
parser: tsParser,
|
|
14
|
+
parserOptions: {
|
|
15
|
+
project: "./tsconfig.json",
|
|
16
|
+
tsconfigRootDir: import.meta.dirname,
|
|
17
|
+
sourceType: "module",
|
|
18
|
+
},
|
|
19
|
+
globals: {
|
|
20
|
+
...globals.node,
|
|
21
|
+
...globals.browser,
|
|
22
|
+
fetch: "readonly",
|
|
23
|
+
Request: "readonly",
|
|
24
|
+
Response: "readonly",
|
|
25
|
+
Headers: "readonly",
|
|
26
|
+
AbortController: "readonly",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
plugins: {
|
|
30
|
+
"@typescript-eslint": tsPlugin,
|
|
31
|
+
},
|
|
32
|
+
rules: {
|
|
33
|
+
...js.configs.recommended.rules,
|
|
34
|
+
...tsPlugin.configs["recommended-type-checked"].rules,
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
];
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@makegov/tango-node",
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"description": "Official Node.js SDK for the Tango API – dynamic response shaping, typed models, and full endpoint coverage.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./models": {
|
|
16
|
+
"import": "./dist/models/index.js",
|
|
17
|
+
"types": "./dist/models/index.d.ts",
|
|
18
|
+
"default": "./dist/models/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./shapes": {
|
|
21
|
+
"import": "./dist/shapes/index.js",
|
|
22
|
+
"types": "./dist/shapes/index.d.ts",
|
|
23
|
+
"default": "./dist/shapes/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc -p tsconfig.json",
|
|
29
|
+
"clean": "rm -rf dist",
|
|
30
|
+
"lint": "eslint src --ext .ts",
|
|
31
|
+
"format": "prettier --write .",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"test": "vitest",
|
|
34
|
+
"coverage": "vitest run --coverage",
|
|
35
|
+
"prepare": "npm run build",
|
|
36
|
+
"prepublishOnly": "npm run lint && npm run test && npm run build"
|
|
37
|
+
},
|
|
38
|
+
"keywords": [
|
|
39
|
+
"tango",
|
|
40
|
+
"makegov",
|
|
41
|
+
"federal-contracts",
|
|
42
|
+
"procurement",
|
|
43
|
+
"grants",
|
|
44
|
+
"sdk",
|
|
45
|
+
"api-client",
|
|
46
|
+
"govtech"
|
|
47
|
+
],
|
|
48
|
+
"author": "MakeGov",
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git",
|
|
52
|
+
"url": "git+https://github.com/makegov/tango-node.git"
|
|
53
|
+
},
|
|
54
|
+
"bugs": {
|
|
55
|
+
"url": "https://github.com/makegov/tango-node/issues"
|
|
56
|
+
},
|
|
57
|
+
"homepage": "https://github.com/makegov/tango-node#readme",
|
|
58
|
+
"engines": {
|
|
59
|
+
"node": ">=18.0.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/node": "^22.0.0",
|
|
63
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
64
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
65
|
+
"@vitest/coverage-v8": "^2.0.0",
|
|
66
|
+
"eslint": "^9.0.0",
|
|
67
|
+
"globals": "^15.12.0",
|
|
68
|
+
"prettier": "^3.0.0",
|
|
69
|
+
"typescript": "^5.6.0",
|
|
70
|
+
"vitest": "^2.0.0"
|
|
71
|
+
},
|
|
72
|
+
"dependencies": {}
|
|
73
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"allowSyntheticDefaultImports": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"forceConsistentCasingInFileNames": true,
|
|
9
|
+
"strict": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"declaration": true,
|
|
12
|
+
"declarationMap": true,
|
|
13
|
+
"sourceMap": true,
|
|
14
|
+
"outDir": "./dist",
|
|
15
|
+
"rootDir": "./src",
|
|
16
|
+
"resolveJsonModule": true,
|
|
17
|
+
"types": ["node", "vitest"]
|
|
18
|
+
},
|
|
19
|
+
"include": ["src"],
|
|
20
|
+
"exclude": ["dist", "node_modules", "tests"]
|
|
21
|
+
}
|
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { defineConfig } from "vitest/config";
|
|
2
|
+
|
|
3
|
+
export default defineConfig({
|
|
4
|
+
test: {
|
|
5
|
+
environment: "node",
|
|
6
|
+
globals: true,
|
|
7
|
+
include: ["tests/**/*.test.ts"],
|
|
8
|
+
coverage: {
|
|
9
|
+
provider: "v8",
|
|
10
|
+
reporter: ["text", "html"],
|
|
11
|
+
exclude: [".*", "*.config.*s", "dist/**/**", "src/index.ts", "src/shapes/index.ts", "tests/**/**"],
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
esbuild: {
|
|
15
|
+
loader: "ts",
|
|
16
|
+
target: "es2020",
|
|
17
|
+
},
|
|
18
|
+
});
|