@metaphase-tech/fedspeak 0.1.0 → 1.0.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/LICENSE +1 -1
- package/README.md +284 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/shared/data/acronyms.json +618 -272
- package/dist/shared/decoder.d.ts +3 -0
- package/dist/shared/decoder.d.ts.map +1 -1
- package/dist/shared/decoder.js +17 -0
- package/dist/shared/decoder.js.map +1 -1
- package/dist/shared/truncate.d.ts +2 -2
- package/dist/shared/truncate.d.ts.map +1 -1
- package/dist/shared/truncate.js +7 -7
- package/dist/shared/truncate.js.map +1 -1
- package/package.json +2 -2
package/LICENSE
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# FedSpeak
|
|
2
|
+
|
|
3
|
+
[](https://app.netlify.com/projects/fedspeak/deploys)
|
|
4
|
+
[](https://www.npmjs.com/package/fedspeak)
|
|
5
|
+
[](https://github.com/MetaPhase-Consulting/fedspeak/actions/workflows/ci.yml)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://metaphase.tech)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
|
|
10
|
+
**Federal Acronym Decoder** — Decode and encode U.S. government acronyms from text or single lookups.
|
|
11
|
+
|
|
12
|
+
FedSpeak is a REST API, interactive website, and npm package that expands **1,119 federal government acronyms** with full names, descriptions, agency context, and category classifications.
|
|
13
|
+
|
|
14
|
+
**Website:** [fedspeak.dev](https://fedspeak.dev)
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Decode** — Send any acronym, get the full expansion with description, agency, and category
|
|
19
|
+
- **Encode** — Send a full name, get the acronym back
|
|
20
|
+
- **Text Scanning** — Paste a block of text, FedSpeak finds and decodes every recognized acronym
|
|
21
|
+
- **1,119 Acronyms** — Departments, agencies, cybersecurity, NIST, CMMC, procurement, contract vehicles, legislation, and more
|
|
22
|
+
- **REST API** — GET and POST support, JSON responses, CORS enabled
|
|
23
|
+
- **npm Package** — Use the decoder directly in your Node.js projects
|
|
24
|
+
- **Interactive Demo** — Try it live at [fedspeak.dev](https://fedspeak.dev)
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### API
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Decode an acronym
|
|
32
|
+
curl -X POST https://fedspeak.netlify.app/api/decode \
|
|
33
|
+
-H "Content-Type: application/json" \
|
|
34
|
+
-d '{"acronym": "DOD"}'
|
|
35
|
+
|
|
36
|
+
# Scan text for acronyms
|
|
37
|
+
curl -X POST https://fedspeak.netlify.app/api/decode \
|
|
38
|
+
-H "Content-Type: application/json" \
|
|
39
|
+
-d '{"text": "The DOD and GSA are working with OMB on the new RFP"}'
|
|
40
|
+
|
|
41
|
+
# Encode a full name to its acronym
|
|
42
|
+
curl -X POST https://fedspeak.netlify.app/api/encode \
|
|
43
|
+
-H "Content-Type: application/json" \
|
|
44
|
+
-d '{"name": "General Services Administration"}'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### npm Package
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npm install fedspeak
|
|
51
|
+
# or
|
|
52
|
+
npm install @metaphase-tech/fedspeak
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
import { lookupAcronym, scanText, decode, encode, getAcronymCount } from 'fedspeak';
|
|
57
|
+
|
|
58
|
+
// Single lookup
|
|
59
|
+
const result = lookupAcronym('DOD');
|
|
60
|
+
console.log(result?.full); // "Department of Defense"
|
|
61
|
+
|
|
62
|
+
// Scan text for all acronyms
|
|
63
|
+
const found = scanText('The DOD and GSA are working with OMB');
|
|
64
|
+
found.forEach(r => console.log(`${r.acronym} = ${r.full}`));
|
|
65
|
+
|
|
66
|
+
// Full decode with response envelope
|
|
67
|
+
const response = decode({ text: 'Submit the RFP to the CO at GSA' });
|
|
68
|
+
console.log(response.results); // [{ acronym: 'RFP', ... }, { acronym: 'CO', ... }, { acronym: 'GSA', ... }]
|
|
69
|
+
|
|
70
|
+
// Reverse lookup: full name to acronym
|
|
71
|
+
const encoded = encode({ name: 'General Services Administration' });
|
|
72
|
+
console.log(encoded.results[0].acronym); // "GSA"
|
|
73
|
+
|
|
74
|
+
// Total count
|
|
75
|
+
console.log(getAcronymCount()); // 1069
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## API Reference
|
|
79
|
+
|
|
80
|
+
### Decode
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
POST /api/decode
|
|
84
|
+
GET /api/decode?acronym=GSA
|
|
85
|
+
GET /api/decode?text=The+DOD+and+GSA+work+with+OMB
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Single lookup request:**
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{ "acronym": "GSA" }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Text scan request:**
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{ "text": "The DOD and GSA are working with OMB on the new RFP" }
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
**Response:**
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"success": true,
|
|
105
|
+
"query": "GSA",
|
|
106
|
+
"mode": "single",
|
|
107
|
+
"results": [{
|
|
108
|
+
"acronym": "GSA",
|
|
109
|
+
"full": "General Services Administration",
|
|
110
|
+
"description": "Federal agency managing government buildings, procurement, and technology solutions.",
|
|
111
|
+
"agency": "GSA",
|
|
112
|
+
"category": "agency",
|
|
113
|
+
"url": "https://www.gsa.gov"
|
|
114
|
+
}],
|
|
115
|
+
"count": 1,
|
|
116
|
+
"truncated": false
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Encode
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
POST /api/encode
|
|
124
|
+
GET /api/encode?name=General+Services+Administration
|
|
125
|
+
GET /api/encode?text=The+Department+of+Defense+is+working+with...
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
**Single lookup request:**
|
|
129
|
+
|
|
130
|
+
```json
|
|
131
|
+
{ "name": "General Services Administration" }
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**Text scan request:**
|
|
135
|
+
|
|
136
|
+
```json
|
|
137
|
+
{ "text": "The Department of Defense and General Services Administration..." }
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## npm Package API
|
|
141
|
+
|
|
142
|
+
### Functions
|
|
143
|
+
|
|
144
|
+
| Function | Description |
|
|
145
|
+
|----------|-------------|
|
|
146
|
+
| `lookupAcronym(query)` | Look up a single acronym. Returns `DecodedResult` or `null` |
|
|
147
|
+
| `scanText(text)` | Scan text for all recognized acronyms. Returns `DecodedResult[]` |
|
|
148
|
+
| `decode(request)` | Full decode with response envelope (`{ acronym }` or `{ text }`) |
|
|
149
|
+
| `lookupName(query)` | Reverse lookup: full name to acronym. Returns `EncodedResult` or `null` |
|
|
150
|
+
| `scanTextForNames(text)` | Scan text for full names, return their acronyms. Returns `EncodedResult[]` |
|
|
151
|
+
| `encode(request)` | Full encode with response envelope (`{ name }` or `{ text }`) |
|
|
152
|
+
| `getAllAcronyms()` | Get sorted array of all acronym keys |
|
|
153
|
+
| `getAcronymCount()` | Get total number of acronyms in the database |
|
|
154
|
+
| `truncateResponse(response)` | Truncate response to fit 2000-char limit |
|
|
155
|
+
|
|
156
|
+
### TypeScript Types
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
import type {
|
|
160
|
+
AcronymCategory, // 'department' | 'agency' | 'office' | 'bureau' | 'program' | 'process' | 'regulation' | 'system' | 'general'
|
|
161
|
+
AcronymEntry, // { full, description, agency, category, url?, aliases? }
|
|
162
|
+
AcronymData, // Record of acronym key to AcronymEntry
|
|
163
|
+
DecodedResult, // Single decode result
|
|
164
|
+
DecodeResponse, // Full decode response envelope
|
|
165
|
+
DecodeRequest, // { acronym?: string; text?: string }
|
|
166
|
+
EncodedResult, // Single encode result
|
|
167
|
+
EncodeResponse, // Full encode response envelope
|
|
168
|
+
EncodeRequest, // { name?: string; text?: string }
|
|
169
|
+
} from 'fedspeak';
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Acronym Coverage
|
|
173
|
+
|
|
174
|
+
1,119 entries across these categories:
|
|
175
|
+
|
|
176
|
+
| Category | Examples |
|
|
177
|
+
|----------|----------|
|
|
178
|
+
| **Federal departments** | DOD, DOJ, DOE, HHS, DHS, VA, DOS, DOT, ... |
|
|
179
|
+
| **Agencies & offices** | NASA, GSA, EPA, SBA, CISA, NIST, OPM, FEMA, ... |
|
|
180
|
+
| **Cybersecurity & NIST** | CMMC, FedRAMP, FISMA, CVE, CVSS, ZTA, ATT&CK, CSF, ... |
|
|
181
|
+
| **Identity & auth** | IAL, AAL, FAL, MFA, FIDO, PIV, CAC, SSO, ... |
|
|
182
|
+
| **Procurement & acquisition** | FAR, DFARS, GWAC, IDIQ, BPA, RFP, CO, COR, ... |
|
|
183
|
+
| **Contract vehicles** | OASIS+, CIO-SP4, SEWP VI, 8(a) STARS III, ALLIANT 2, ... |
|
|
184
|
+
| **Legislation** | FITARA, FOIA, APA, NEPA, HIPAA, FISMA, ACA, ... |
|
|
185
|
+
| **IT & systems** | FedRAMP, ATO, HSPD-12, eMASS, Login.gov, ... |
|
|
186
|
+
| **Budget & finance** | OMB, CBO, GAO, PPBE, CR, ... |
|
|
187
|
+
| **HR & personnel** | OPM, GS, SES, USERRA, ... |
|
|
188
|
+
|
|
189
|
+
## Development
|
|
190
|
+
|
|
191
|
+
### Prerequisites
|
|
192
|
+
|
|
193
|
+
- Node.js 20+
|
|
194
|
+
- npm 10+
|
|
195
|
+
|
|
196
|
+
### Setup
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
git clone https://github.com/MetaPhase-Consulting/fedspeak.git
|
|
200
|
+
cd fedspeak
|
|
201
|
+
npm install
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Commands
|
|
205
|
+
|
|
206
|
+
| Command | Description |
|
|
207
|
+
|---------|-------------|
|
|
208
|
+
| `npm run dev` | Start Vite dev server |
|
|
209
|
+
| `npx netlify dev` | Full local dev with API at localhost:8888 |
|
|
210
|
+
| `npm run build` | Production build |
|
|
211
|
+
| `npm run lint` | ESLint |
|
|
212
|
+
| `npm run typecheck` | TypeScript strict check |
|
|
213
|
+
| `npm run test:run` | Run tests once |
|
|
214
|
+
| `npm run test` | Run tests in watch mode |
|
|
215
|
+
| `npm run test:coverage` | Run tests with coverage |
|
|
216
|
+
|
|
217
|
+
### Project Structure
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
fedspeak/
|
|
221
|
+
├── netlify/functions/ Serverless API endpoints
|
|
222
|
+
│ ├── decode.ts POST /api/decode
|
|
223
|
+
│ └── encode.ts POST /api/encode
|
|
224
|
+
├── src/
|
|
225
|
+
│ ├── shared/ Core logic (shared by API, website, npm package)
|
|
226
|
+
│ │ ├── decoder.ts lookupAcronym(), scanText(), decode()
|
|
227
|
+
│ │ ├── encoder.ts lookupName(), scanTextForNames(), encode()
|
|
228
|
+
│ │ ├── truncate.ts Response truncation
|
|
229
|
+
│ │ ├── types.ts TypeScript interfaces
|
|
230
|
+
│ │ └── data/
|
|
231
|
+
│ │ └── acronyms.json
|
|
232
|
+
│ ├── components/ React UI components
|
|
233
|
+
│ └── pages/ React Router pages
|
|
234
|
+
├── cli-package/ npm package for publishing
|
|
235
|
+
├── tests/ Vitest test suites
|
|
236
|
+
├── public/openapi.json OpenAPI 3.1 specification
|
|
237
|
+
└── .github/workflows/ CI/CD pipelines
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Tech Stack
|
|
241
|
+
|
|
242
|
+
| Layer | Choice |
|
|
243
|
+
|-------|--------|
|
|
244
|
+
| Runtime | Node.js 20, TypeScript 5.5 |
|
|
245
|
+
| API | Netlify Functions v2 (serverless) |
|
|
246
|
+
| Data | Static JSON (no database) |
|
|
247
|
+
| Website | Vite + React 18 + Tailwind CSS + React Router |
|
|
248
|
+
| Testing | Vitest + @vitest/coverage-v8 |
|
|
249
|
+
| CI/CD | GitHub Actions |
|
|
250
|
+
| Deploy | Netlify |
|
|
251
|
+
|
|
252
|
+
### Adding Acronyms
|
|
253
|
+
|
|
254
|
+
Add entries to `src/shared/data/acronyms.json` in alphabetical order:
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
"ACRONYM": {
|
|
258
|
+
"full": "Full Name",
|
|
259
|
+
"description": "Brief description (1-2 sentences).",
|
|
260
|
+
"agency": "Parent agency acronym or General",
|
|
261
|
+
"category": "department|agency|office|bureau|program|process|regulation|system|general",
|
|
262
|
+
"url": "https://optional-official-website.gov",
|
|
263
|
+
"aliases": ["optional", "alternate", "spellings"]
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
## Contributing
|
|
268
|
+
|
|
269
|
+
1. Fork the repository
|
|
270
|
+
2. Create a feature branch from `dev`
|
|
271
|
+
3. Make your changes
|
|
272
|
+
4. Ensure `npm run lint`, `npm run typecheck`, and `npm run test:run` all pass
|
|
273
|
+
5. Open a PR to `dev`
|
|
274
|
+
|
|
275
|
+
### Branching
|
|
276
|
+
|
|
277
|
+
- **`dev`** — Default branch, active development
|
|
278
|
+
- **`main`** — Production, deploys to Netlify
|
|
279
|
+
- Feature branches merge into `dev` via PR
|
|
280
|
+
- `dev` merges into `main` via PR for releases
|
|
281
|
+
|
|
282
|
+
## License
|
|
283
|
+
|
|
284
|
+
[MIT](LICENSE) © [MetaPhase](https://metaphase.tech)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { lookupAcronym, scanText, decode, getAllAcronyms, getAcronymCount } from './shared/decoder';
|
|
2
2
|
export { lookupName, scanTextForNames, encode } from './shared/encoder';
|
|
3
|
-
export {
|
|
3
|
+
export { truncateResponse } from './shared/truncate';
|
|
4
4
|
export type { AcronymCategory, AcronymEntry, AcronymData, DecodedResult, DecodeResponse, DecodeRequest, EncodedResult, EncodeResponse, EncodeRequest, } from './shared/types';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,YAAY,EACV,eAAe,EACf,YAAY,EACZ,WAAW,EACX,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,GACd,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
// Re-exports from shared core (files synced via scripts/sync-cli-package.sh)
|
|
3
3
|
export { lookupAcronym, scanText, decode, getAllAcronyms, getAcronymCount } from './shared/decoder';
|
|
4
4
|
export { lookupName, scanTextForNames, encode } from './shared/encoder';
|
|
5
|
-
export {
|
|
5
|
+
export { truncateResponse } from './shared/truncate';
|
|
6
6
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,6EAA6E;AAE7E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mCAAmC;AACnC,6EAA6E;AAE7E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACpG,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC"}
|