patents-mcp-server 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 +21 -0
- package/README.md +191 -0
- package/dist/base.client-zZnUjoIb.js +2 -0
- package/dist/base.client-zZnUjoIb.js.map +1 -0
- package/dist/clients/base.client.d.ts +19 -0
- package/dist/clients/base.client.js +1 -0
- package/dist/clients/bigquery.client.d.ts +14 -0
- package/dist/clients/bigquery.client.js +66 -0
- package/dist/clients/bigquery.client.js.map +1 -0
- package/dist/clients/epo-ops.client.d.ts +13 -0
- package/dist/clients/epo-ops.client.js +2 -0
- package/dist/clients/epo-ops.client.js.map +1 -0
- package/dist/clients/odp.client.d.ts +52 -0
- package/dist/clients/odp.client.js +2 -0
- package/dist/clients/odp.client.js.map +1 -0
- package/dist/clients/patentsview.client.d.ts +38 -0
- package/dist/clients/patentsview.client.js +2 -0
- package/dist/clients/patentsview.client.js.map +1 -0
- package/dist/generated/odp/index.d.ts +2 -0
- package/dist/generated/odp/index.js +1 -0
- package/dist/generated/odp/types.gen.d.ts +4432 -0
- package/dist/generated/odp/types.gen.js +1 -0
- package/dist/generated/odp/zod.gen.d.ts +7504 -0
- package/dist/generated/odp/zod.gen.js +2 -0
- package/dist/generated/odp/zod.gen.js.map +1 -0
- package/dist/generated/patentsview/index.d.ts +2 -0
- package/dist/generated/patentsview/index.js +1 -0
- package/dist/generated/patentsview/types.gen.d.ts +2454 -0
- package/dist/generated/patentsview/types.gen.js +1 -0
- package/dist/generated/patentsview/zod.gen.d.ts +3376 -0
- package/dist/generated/patentsview/zod.gen.js +2 -0
- package/dist/generated/patentsview/zod.gen.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +24 -0
- package/dist/lib/config.js +2 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/errors.d.ts +7 -0
- package/dist/lib/errors.js +2 -0
- package/dist/lib/errors.js.map +1 -0
- package/dist/lib/patent-number.d.ts +5 -0
- package/dist/lib/patent-number.js +2 -0
- package/dist/lib/patent-number.js.map +1 -0
- package/dist/lib/retry.d.ts +10 -0
- package/dist/lib/retry.js +2 -0
- package/dist/lib/retry.js.map +1 -0
- package/dist/lib/types.d.ts +22 -0
- package/dist/lib/types.js +1 -0
- package/dist/prompts/index.d.ts +7 -0
- package/dist/prompts/index.js +255 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/resources/index.d.ts +7 -0
- package/dist/resources/index.js +44 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/bigquery.tools.d.ts +7 -0
- package/dist/tools/bigquery.tools.js +14 -0
- package/dist/tools/bigquery.tools.js.map +1 -0
- package/dist/tools/citations.tools.d.ts +7 -0
- package/dist/tools/citations.tools.js +2 -0
- package/dist/tools/citations.tools.js.map +1 -0
- package/dist/tools/epo.tools.d.ts +7 -0
- package/dist/tools/epo.tools.js +18 -0
- package/dist/tools/epo.tools.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/odp.tools.d.ts +7 -0
- package/dist/tools/odp.tools.js +2 -0
- package/dist/tools/odp.tools.js.map +1 -0
- package/dist/tools/office-actions.tools.d.ts +7 -0
- package/dist/tools/office-actions.tools.js +2 -0
- package/dist/tools/office-actions.tools.js.map +1 -0
- package/dist/tools/patentsview.tools.d.ts +7 -0
- package/dist/tools/patentsview.tools.js +2 -0
- package/dist/tools/patentsview.tools.js.map +1 -0
- package/dist/tools/ptab.tools.d.ts +7 -0
- package/dist/tools/ptab.tools.js +2 -0
- package/dist/tools/ptab.tools.js.map +1 -0
- package/dist/tools/utility.tools.d.ts +7 -0
- package/dist/tools/utility.tools.js +2 -0
- package/dist/tools/utility.tools.js.map +1 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Jordan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# patents-mcp-server
|
|
2
|
+
|
|
3
|
+
FastMCP TypeScript patent intelligence MCP server. 55 tools across USPTO, EPO, and Google Patents for IP landscape analysis, freedom-to-operate research, and patent monitoring.
|
|
4
|
+
|
|
5
|
+
## Data Sources
|
|
6
|
+
|
|
7
|
+
| Source | Tools | Key Capability |
|
|
8
|
+
| ------------------- | ----- | ----------------------------------------------------------------------------- |
|
|
9
|
+
| **PatentsView** | 14 | US patent search, disambiguated entities (assignees, inventors, attorneys) |
|
|
10
|
+
| **USPTO ODP** | 29 | Applications, PTAB proceedings, citations, litigation, office actions |
|
|
11
|
+
| **EPO OPS** | 8 | INPADOC patent families, legal status across ~44 offices, claims/descriptions |
|
|
12
|
+
| **Google BigQuery** | 4 | Full-text search across 90M+ patents, citation networks, CPC analytics |
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm install
|
|
18
|
+
cp .env.example .env # Add your API keys
|
|
19
|
+
pnpm build
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Run via stdio (Claude Desktop / Claude Code)
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node dist/index.js
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Run via HTTP (remote deployment)
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
TRANSPORT=httpStream PORT=8080 node dist/index.js
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Test with MCP Inspector
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx @modelcontextprotocol/inspector node dist/index.js
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Configuration
|
|
41
|
+
|
|
42
|
+
Copy `.env.example` and fill in your API keys:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# USPTO Open Data Portal (required for ODP, PTAB, litigation, office actions)
|
|
46
|
+
USPTO_API_KEY=
|
|
47
|
+
|
|
48
|
+
# PatentsView (optional — works without key, key grants suspended March 2026)
|
|
49
|
+
PATENTSVIEW_API_KEY=
|
|
50
|
+
|
|
51
|
+
# EPO OPS (register at developers.epo.org)
|
|
52
|
+
EPO_CONSUMER_KEY=
|
|
53
|
+
EPO_CONSUMER_SECRET=
|
|
54
|
+
|
|
55
|
+
# Google BigQuery (requires GCP project with service account)
|
|
56
|
+
GOOGLE_APPLICATION_CREDENTIALS= # Path to service account JSON
|
|
57
|
+
GOOGLE_CLOUD_PROJECT= # GCP project ID
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Missing API keys disable related tools gracefully — the server still starts with whatever sources are configured. Use the `check-api-status` tool to verify which sources are available.
|
|
61
|
+
|
|
62
|
+
## Tools
|
|
63
|
+
|
|
64
|
+
### PatentsView (14 tools)
|
|
65
|
+
|
|
66
|
+
Search and retrieve US patent data with disambiguated entities.
|
|
67
|
+
|
|
68
|
+
- `patentsview-search-patents` — Full-text search by text, assignee, or inventor
|
|
69
|
+
- `patentsview-get-patent` — Get patent by ID
|
|
70
|
+
- `patentsview-search-assignees` / `get-assignee` — Disambiguated assignee search
|
|
71
|
+
- `patentsview-search-inventors` / `get-inventor` — Disambiguated inventor search
|
|
72
|
+
- `patentsview-search-attorneys` / `get-attorney` — Attorney search
|
|
73
|
+
- `patentsview-get-claims` — Full claims text
|
|
74
|
+
- `patentsview-get-description` — Patent description
|
|
75
|
+
- `patentsview-search-by-cpc` / `lookup-cpc` — CPC classification search
|
|
76
|
+
- `patentsview-search-by-ipc` / `lookup-ipc` — IPC classification search
|
|
77
|
+
|
|
78
|
+
### USPTO ODP (12 tools)
|
|
79
|
+
|
|
80
|
+
Official USPTO Open Data Portal — applications, prosecution history, assignments.
|
|
81
|
+
|
|
82
|
+
- `odp-search-applications` — Search patent applications (2001+)
|
|
83
|
+
- `odp-get-application` / `metadata` / `continuity` / `assignment` / `adjustment` / `attorney` / `foreign-priority` / `transactions` / `documents`
|
|
84
|
+
- `odp-search-datasets` / `get-dataset` — Bulk data products
|
|
85
|
+
|
|
86
|
+
### PTAB (7 tools)
|
|
87
|
+
|
|
88
|
+
Post-grant proceedings — IPR, PGR, CBM, ex parte appeals.
|
|
89
|
+
|
|
90
|
+
- `ptab-search-proceedings` / `get-proceeding` / `get-documents`
|
|
91
|
+
- `ptab-search-decisions` / `get-decision`
|
|
92
|
+
- `ptab-search-appeals` / `get-appeal`
|
|
93
|
+
|
|
94
|
+
### Citations & Litigation (6 tools)
|
|
95
|
+
|
|
96
|
+
Patent citations and litigation data.
|
|
97
|
+
|
|
98
|
+
- `citations-get-enriched` / `search` / `get-metrics`
|
|
99
|
+
- `litigation-search` / `get-case` / `get-patent`
|
|
100
|
+
|
|
101
|
+
### EPO OPS (8 tools)
|
|
102
|
+
|
|
103
|
+
European Patent Office — international coverage, INPADOC families, legal status.
|
|
104
|
+
|
|
105
|
+
- `epo-search-patents` — CQL search (title, abstract, applicant, inventor, CPC, date)
|
|
106
|
+
- `epo-get-biblio` / `abstract` / `claims` / `description` — Patent document sections
|
|
107
|
+
- `epo-family-lookup` — INPADOC family members across all jurisdictions
|
|
108
|
+
- `epo-legal-status` — Legal status across ~44 patent offices
|
|
109
|
+
- `epo-number-convert` — Convert between number formats
|
|
110
|
+
|
|
111
|
+
### Google BigQuery (4 tools)
|
|
112
|
+
|
|
113
|
+
Full-text search across 90M+ patent documents. Replaces PPUBS for claims search.
|
|
114
|
+
|
|
115
|
+
- `bigquery-patent-search` — Full-text search across titles and abstracts
|
|
116
|
+
- `bigquery-patent-family` — Family members by INPADOC family ID
|
|
117
|
+
- `bigquery-citation-network` — Citation graph (depth 1 or 2)
|
|
118
|
+
- `bigquery-cpc-analytics` — Filing statistics by CPC classification
|
|
119
|
+
|
|
120
|
+
### Office Actions (4 tools)
|
|
121
|
+
|
|
122
|
+
USPTO office action data (migrating to ODP in 2026).
|
|
123
|
+
|
|
124
|
+
- `office-action-get-text` / `search` / `get-citations` / `get-rejections`
|
|
125
|
+
|
|
126
|
+
### Utility (3 tools)
|
|
127
|
+
|
|
128
|
+
- `check-api-status` — Health check all configured APIs
|
|
129
|
+
- `get-cpc-info` — CPC classification lookup
|
|
130
|
+
- `get-status-code` — USPTO status code meanings
|
|
131
|
+
|
|
132
|
+
## Prompts
|
|
133
|
+
|
|
134
|
+
Six workflow prompt templates for common patent analysis tasks:
|
|
135
|
+
|
|
136
|
+
| Prompt | Purpose |
|
|
137
|
+
| ---------------------- | ------------------------------------------ |
|
|
138
|
+
| `prior_art_search` | Multi-source prior art search workflow |
|
|
139
|
+
| `patent_validity` | Structured validity analysis (102/103/112) |
|
|
140
|
+
| `competitor_portfolio` | Competitor patent portfolio analysis |
|
|
141
|
+
| `ptab_research` | PTAB proceedings research (IPR/PGR/CBM) |
|
|
142
|
+
| `freedom_to_operate` | FTO analysis methodology |
|
|
143
|
+
| `patent_landscape` | Technology area landscape mapping |
|
|
144
|
+
|
|
145
|
+
## Resources
|
|
146
|
+
|
|
147
|
+
| URI | Description |
|
|
148
|
+
| ------------------------- | -------------------------------------------------------- |
|
|
149
|
+
| `patents://cpc/{code}` | CPC classification info |
|
|
150
|
+
| `patents://status-codes` | USPTO status code definitions |
|
|
151
|
+
| `patents://sources` | Data source overview |
|
|
152
|
+
| `patents://search-syntax` | Query syntax guide (PatentsView, EPO CQL, ODP, BigQuery) |
|
|
153
|
+
|
|
154
|
+
## Development
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pnpm validate # Format + lint + typecheck + test + build
|
|
158
|
+
pnpm test # Run tests
|
|
159
|
+
pnpm build # Production build
|
|
160
|
+
pnpm typecheck # Type check only
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Architecture
|
|
164
|
+
|
|
165
|
+
Built with [FastMCP](https://github.com/punkpeye/fastmcp) + [Zod](https://zod.dev/) + [ts-builds](https://github.com/jordanburke/ts-builds).
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
src/
|
|
169
|
+
├── index.ts # Entry point
|
|
170
|
+
├── server.ts # FastMCP instance
|
|
171
|
+
├── tools/ # 55 tools across 8 modules
|
|
172
|
+
├── clients/ # API clients (base, PatentsView, ODP, EPO, BigQuery)
|
|
173
|
+
├── resources/ # 4 MCP resources
|
|
174
|
+
├── prompts/ # 6 prompt templates
|
|
175
|
+
└── lib/ # Config, retry, errors, patent number normalization
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT
|
|
181
|
+
|
|
182
|
+
## Acknowledgments
|
|
183
|
+
|
|
184
|
+
- [USPTO](https://www.uspto.gov/) - US Patent and Trademark Office
|
|
185
|
+
- [EPO OPS](https://www.epo.org/en/searching-for-patents/data/web-services/ops) - European Patent Office Open Patent Services
|
|
186
|
+
- [PatentsView](https://patentsview.org/) - USPTO patent data platform
|
|
187
|
+
- [Google Patents Public Data](https://console.cloud.google.com/marketplace/product/google_patents_public_datasets/google-patents-public-data) - BigQuery patent dataset
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
**Sponsored by <a href="https://sapientsai.com/"><img src="https://sapientsai.com/images/logo.svg" alt="SapientsAI" width="20" style="vertical-align: middle;"> SapientsAI</a>** — Building agentic AI for businesses
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{withRetry as e}from"./lib/retry.js";function t(e){"@babel/helpers - typeof";return t=typeof Symbol==`function`&&typeof Symbol.iterator==`symbol`?function(e){return typeof e}:function(e){return e&&typeof Symbol==`function`&&e.constructor===Symbol&&e!==Symbol.prototype?`symbol`:typeof e},t(e)}function n(e,n){if(t(e)!=`object`||!e)return e;var r=e[Symbol.toPrimitive];if(r!==void 0){var i=r.call(e,n||`default`);if(t(i)!=`object`)return i;throw TypeError(`@@toPrimitive must return a primitive value.`)}return(n===`string`?String:Number)(e)}function r(e){var r=n(e,`string`);return t(r)==`symbol`?r:r+``}function i(e,t,n){return(t=r(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}const a=(e,t,n)=>{let r=Error(`API Error ${e} ${t}: ${n}`);return r.status=e,r.statusText=t,r.body=n,r};var o=class{constructor(e){i(this,`baseUrl`,void 0),i(this,`headers`,void 0),i(this,`timeout`,void 0),this.baseUrl=e.baseUrl.endsWith(`/`)?e.baseUrl:`${e.baseUrl}/`,this.headers={"Content-Type":`application/json`,Accept:`application/json`,...e.headers},this.timeout=e.timeout??3e4}async get(t,n){let r=this.buildUrl(t,n);return e(()=>this.request(r,{method:`GET`}))}async post(t,n,r){let i=this.buildUrl(t,r),a={method:`POST`,...n===void 0?{}:{body:JSON.stringify(n)}};return e(()=>this.request(i,a))}buildUrl(e,t){let n=new URL(e,this.baseUrl);if(t)for(let[e,r]of Object.entries(t))r!==void 0&&r!==``&&n.searchParams.set(e,r);return n.toString()}async request(e,t){let n=new AbortController,r=setTimeout(()=>n.abort(),this.timeout);try{let r=await fetch(e,{...t,headers:this.headers,signal:n.signal});if(!r.ok){let e=await r.text();throw a(r.status,r.statusText,e)}return await r.json()}catch(t){throw t instanceof Error&&`status`in t?t:t instanceof DOMException&&t.name===`AbortError`?Error(`Request to ${e} timed out after ${this.timeout}ms`,{cause:t}):t}finally{clearTimeout(r)}}};export{i as n,o as t};
|
|
2
|
+
//# sourceMappingURL=base.client-zZnUjoIb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.client-zZnUjoIb.js","names":[],"sources":["../src/clients/base.client.ts"],"sourcesContent":["import { withRetry } from \"../lib/retry\"\n\nexport type BaseClientOptions = {\n readonly baseUrl: string\n readonly headers?: Record<string, string>\n readonly timeout?: number\n}\n\ntype HttpError = Error & { status: number; statusText: string; body: string }\n\nconst createHttpError = (status: number, statusText: string, body: string): HttpError => {\n const error = new Error(`API Error ${status} ${statusText}: ${body}`) as HttpError\n error.status = status\n error.statusText = statusText\n error.body = body\n return error\n}\n\nexport class BaseClient {\n private readonly baseUrl: string\n private readonly headers: Record<string, string>\n private readonly timeout: number\n\n constructor(options: BaseClientOptions) {\n this.baseUrl = options.baseUrl.endsWith(\"/\") ? options.baseUrl : `${options.baseUrl}/`\n this.headers = {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n ...options.headers,\n }\n this.timeout = options.timeout ?? 30000\n }\n\n async get<T>(path: string, params?: Record<string, string>): Promise<T> {\n const url = this.buildUrl(path, params)\n return withRetry(() => this.request<T>(url, { method: \"GET\" }))\n }\n\n async post<T>(path: string, body?: unknown, params?: Record<string, string>): Promise<T> {\n const url = this.buildUrl(path, params)\n const init: RequestInit = {\n method: \"POST\",\n ...(body !== undefined ? { body: JSON.stringify(body) } : {}),\n }\n return withRetry(() => this.request<T>(url, init))\n }\n\n private buildUrl(path: string, params?: Record<string, string>): string {\n const url = new URL(path, this.baseUrl)\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined && value !== \"\") {\n url.searchParams.set(key, value)\n }\n }\n }\n return url.toString()\n }\n\n private async request<T>(url: string, init: RequestInit): Promise<T> {\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await fetch(url, {\n ...init,\n headers: this.headers,\n signal: controller.signal,\n })\n\n if (!response.ok) {\n const body = await response.text()\n throw createHttpError(response.status, response.statusText, body)\n }\n\n return (await response.json()) as T\n } catch (error) {\n if (error instanceof Error && \"status\" in error) throw error\n\n if (error instanceof DOMException && error.name === \"AbortError\") {\n throw new Error(`Request to ${url} timed out after ${this.timeout}ms`, { cause: error })\n }\n\n throw error\n } finally {\n clearTimeout(timeoutId)\n }\n }\n}\n"],"mappings":"+tBAUA,MAAM,GAAmB,EAAgB,EAAoB,IAA4B,CACvF,IAAM,EAAY,MAAM,aAAa,EAAO,GAAG,EAAW,IAAI,IAAO,CAIrE,MAHA,GAAM,OAAS,EACf,EAAM,WAAa,EACnB,EAAM,KAAO,EACN,GAGT,IAAa,EAAb,KAAwB,CAKtB,YAAY,EAA4B,QAJvB,UAAA,IAAA,GAAe,QACf,UAAA,IAAA,GAA+B,QAC/B,UAAA,IAAA,GAAe,CAG9B,KAAK,QAAU,EAAQ,QAAQ,SAAS,IAAI,CAAG,EAAQ,QAAU,GAAG,EAAQ,QAAQ,GACpF,KAAK,QAAU,CACb,eAAgB,mBAChB,OAAQ,mBACR,GAAG,EAAQ,QACZ,CACD,KAAK,QAAU,EAAQ,SAAW,IAGpC,MAAM,IAAO,EAAc,EAA6C,CACtE,IAAM,EAAM,KAAK,SAAS,EAAM,EAAO,CACvC,OAAO,MAAgB,KAAK,QAAW,EAAK,CAAE,OAAQ,MAAO,CAAC,CAAC,CAGjE,MAAM,KAAQ,EAAc,EAAgB,EAA6C,CACvF,IAAM,EAAM,KAAK,SAAS,EAAM,EAAO,CACjC,EAAoB,CACxB,OAAQ,OACR,GAAI,IAAS,IAAA,GAA6C,EAAE,CAAnC,CAAE,KAAM,KAAK,UAAU,EAAK,CAAE,CACxD,CACD,OAAO,MAAgB,KAAK,QAAW,EAAK,EAAK,CAAC,CAGpD,SAAiB,EAAc,EAAyC,CACtE,IAAM,EAAM,IAAI,IAAI,EAAM,KAAK,QAAQ,CACvC,GAAI,MACG,GAAM,CAAC,EAAK,KAAU,OAAO,QAAQ,EAAO,CAC3C,IAAU,IAAA,IAAa,IAAU,IACnC,EAAI,aAAa,IAAI,EAAK,EAAM,CAItC,OAAO,EAAI,UAAU,CAGvB,MAAc,QAAW,EAAa,EAA+B,CACnE,IAAM,EAAa,IAAI,gBACjB,EAAY,eAAiB,EAAW,OAAO,CAAE,KAAK,QAAQ,CAEpE,GAAI,CACF,IAAM,EAAW,MAAM,MAAM,EAAK,CAChC,GAAG,EACH,QAAS,KAAK,QACd,OAAQ,EAAW,OACpB,CAAC,CAEF,GAAI,CAAC,EAAS,GAAI,CAChB,IAAM,EAAO,MAAM,EAAS,MAAM,CAClC,MAAM,EAAgB,EAAS,OAAQ,EAAS,WAAY,EAAK,CAGnE,OAAQ,MAAM,EAAS,MAAM,OACtB,EAAO,CAOd,MANI,aAAiB,OAAS,WAAY,EAAa,EAEnD,aAAiB,cAAgB,EAAM,OAAS,aACxC,MAAM,cAAc,EAAI,mBAAmB,KAAK,QAAQ,IAAK,CAAE,MAAO,EAAO,CAAC,CAGpF,SACE,CACR,aAAa,EAAU"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/clients/base.client.d.ts
|
|
2
|
+
type BaseClientOptions = {
|
|
3
|
+
readonly baseUrl: string;
|
|
4
|
+
readonly headers?: Record<string, string>;
|
|
5
|
+
readonly timeout?: number;
|
|
6
|
+
};
|
|
7
|
+
declare class BaseClient {
|
|
8
|
+
private readonly baseUrl;
|
|
9
|
+
private readonly headers;
|
|
10
|
+
private readonly timeout;
|
|
11
|
+
constructor(options: BaseClientOptions);
|
|
12
|
+
get<T>(path: string, params?: Record<string, string>): Promise<T>;
|
|
13
|
+
post<T>(path: string, body?: unknown, params?: Record<string, string>): Promise<T>;
|
|
14
|
+
private buildUrl;
|
|
15
|
+
private request;
|
|
16
|
+
}
|
|
17
|
+
//#endregion
|
|
18
|
+
export { BaseClient, BaseClientOptions };
|
|
19
|
+
//# sourceMappingURL=base.client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{t as e}from"../base.client-zZnUjoIb.js";export{e as BaseClient};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region src/clients/bigquery.client.d.ts
|
|
2
|
+
type BigQueryResult = {
|
|
3
|
+
rows: Record<string, unknown>[];
|
|
4
|
+
totalRows: number;
|
|
5
|
+
estimatedBytesProcessed: string;
|
|
6
|
+
estimatedCostUsd: string;
|
|
7
|
+
};
|
|
8
|
+
declare const bigqueryPatentSearch: (query: string, fields?: string[], limit?: number) => Promise<BigQueryResult>;
|
|
9
|
+
declare const bigqueryPatentFamily: (familyId: string) => Promise<BigQueryResult>;
|
|
10
|
+
declare const bigqueryCitationNetwork: (publicationNumber: string, depth?: number) => Promise<BigQueryResult>;
|
|
11
|
+
declare const bigqueryCpcAnalytics: (cpcPrefix: string, dateFrom?: string, dateTo?: string) => Promise<BigQueryResult>;
|
|
12
|
+
//#endregion
|
|
13
|
+
export { bigqueryCitationNetwork, bigqueryCpcAnalytics, bigqueryPatentFamily, bigqueryPatentSearch };
|
|
14
|
+
//# sourceMappingURL=bigquery.client.d.ts.map
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import{config as e}from"../lib/config.js";import{BigQuery as t}from"@google-cloud/bigquery";const n=`patents-public-data.patents.publications`,r=()=>new t({projectId:e.googleCloudProject}),i=e=>{let t=Number(e)/0xe8d4a51000;return t<=1?`Free (within 1 TB/month free tier)`:`~$${(t*5).toFixed(2)} (${t.toFixed(3)} TB at $5/TB)`},a=async(e,t)=>{let n=r(),[a]=await n.createQueryJob({query:e,params:t,dryRun:!0,useLegacySql:!1}),o=a.metadata?.statistics?.totalBytesProcessed??`0`,s=i(o),[c]=await n.createQueryJob({query:e,params:t,useLegacySql:!1}),[l]=await c.getQueryResults();return{rows:l,totalRows:l.length,estimatedBytesProcessed:o,estimatedCostUsd:s}},o=async(e,t=[`publication_number`,`title_localized`,`abstract_localized`,`publication_date`,`assignee_harmonized`],r=25)=>a(`
|
|
2
|
+
SELECT ${t.join(`, `)}
|
|
3
|
+
FROM \`${n}\`
|
|
4
|
+
WHERE SEARCH(abstract_localized.text, @query)
|
|
5
|
+
OR SEARCH(title_localized.text, @query)
|
|
6
|
+
ORDER BY publication_date DESC
|
|
7
|
+
LIMIT @limit
|
|
8
|
+
`,{query:e,limit:r}),s=async e=>a(`
|
|
9
|
+
SELECT
|
|
10
|
+
publication_number,
|
|
11
|
+
country_code,
|
|
12
|
+
title_localized,
|
|
13
|
+
publication_date,
|
|
14
|
+
grant_date,
|
|
15
|
+
application_number,
|
|
16
|
+
priority_date
|
|
17
|
+
FROM \`${n}\`
|
|
18
|
+
WHERE family_id = @familyId
|
|
19
|
+
ORDER BY publication_date
|
|
20
|
+
`,{familyId:e}),c=async(e,t=1)=>a(t===1?`
|
|
21
|
+
SELECT
|
|
22
|
+
p.publication_number AS source,
|
|
23
|
+
c.publication_number AS cited_publication,
|
|
24
|
+
c.category,
|
|
25
|
+
c.type
|
|
26
|
+
FROM \`${n}\` p,
|
|
27
|
+
UNNEST(citation) AS c
|
|
28
|
+
WHERE p.publication_number = @publicationNumber
|
|
29
|
+
`:`
|
|
30
|
+
WITH level1 AS (
|
|
31
|
+
SELECT
|
|
32
|
+
p.publication_number AS source,
|
|
33
|
+
c.publication_number AS cited
|
|
34
|
+
FROM \`${n}\` p,
|
|
35
|
+
UNNEST(citation) AS c
|
|
36
|
+
WHERE p.publication_number = @publicationNumber
|
|
37
|
+
),
|
|
38
|
+
level2 AS (
|
|
39
|
+
SELECT
|
|
40
|
+
l1.cited AS source,
|
|
41
|
+
c.publication_number AS cited
|
|
42
|
+
FROM level1 l1
|
|
43
|
+
JOIN \`${n}\` p ON p.publication_number = l1.cited,
|
|
44
|
+
UNNEST(citation) AS c
|
|
45
|
+
)
|
|
46
|
+
SELECT * FROM level1
|
|
47
|
+
UNION ALL
|
|
48
|
+
SELECT * FROM level2
|
|
49
|
+
LIMIT 500
|
|
50
|
+
`,{publicationNumber:e}),l=async(e,t,r)=>{let i=`
|
|
51
|
+
SELECT
|
|
52
|
+
c.code AS cpc_code,
|
|
53
|
+
COUNT(*) AS patent_count,
|
|
54
|
+
COUNT(DISTINCT assignee.name) AS unique_assignees,
|
|
55
|
+
MIN(publication_date) AS earliest_publication,
|
|
56
|
+
MAX(publication_date) AS latest_publication
|
|
57
|
+
FROM \`${n}\` p,
|
|
58
|
+
UNNEST(cpc) AS c,
|
|
59
|
+
UNNEST(assignee_harmonized) AS assignee
|
|
60
|
+
WHERE c.code LIKE @cpcPrefix
|
|
61
|
+
${[t?`AND publication_date >= @dateFrom`:``,r?`AND publication_date <= @dateTo`:``].join(` `)}
|
|
62
|
+
GROUP BY c.code
|
|
63
|
+
ORDER BY patent_count DESC
|
|
64
|
+
LIMIT 100
|
|
65
|
+
`,o={cpcPrefix:`${e}%`};return t&&(o.dateFrom=Number(t)),r&&(o.dateTo=Number(r)),a(i,o)};export{c as bigqueryCitationNetwork,l as bigqueryCpcAnalytics,s as bigqueryPatentFamily,o as bigqueryPatentSearch};
|
|
66
|
+
//# sourceMappingURL=bigquery.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bigquery.client.js","names":[],"sources":["../../src/clients/bigquery.client.ts"],"sourcesContent":["import { BigQuery } from \"@google-cloud/bigquery\"\n\nimport { config } from \"../lib/config\"\n\nconst DATASET = \"patents-public-data.patents.publications\"\n\ntype BigQueryResult = {\n rows: Record<string, unknown>[]\n totalRows: number\n estimatedBytesProcessed: string\n estimatedCostUsd: string\n}\n\nconst getBigQueryClient = (): BigQuery => {\n return new BigQuery({\n projectId: config.googleCloudProject,\n })\n}\n\nconst estimateCost = (bytes: string): string => {\n const tb = Number(bytes) / 1e12\n if (tb <= 1) return \"Free (within 1 TB/month free tier)\"\n return `~$${(tb * 5).toFixed(2)} (${tb.toFixed(3)} TB at $5/TB)`\n}\n\nconst runQuery = async (sql: string, params?: Record<string, unknown>): Promise<BigQueryResult> => {\n const client = getBigQueryClient()\n\n // Always dry run first to estimate cost\n const [dryRunJob] = await client.createQueryJob({\n query: sql,\n params,\n dryRun: true,\n useLegacySql: false,\n })\n\n const bytesProcessed = dryRunJob.metadata?.statistics?.totalBytesProcessed ?? \"0\"\n const costEstimate = estimateCost(bytesProcessed)\n\n // Execute the actual query\n const [job] = await client.createQueryJob({\n query: sql,\n params,\n useLegacySql: false,\n })\n\n const [rows] = await job.getQueryResults()\n\n return {\n rows: rows as Record<string, unknown>[],\n totalRows: rows.length,\n estimatedBytesProcessed: bytesProcessed,\n estimatedCostUsd: costEstimate,\n }\n}\n\nexport const bigqueryPatentSearch = async (\n query: string,\n fields: string[] = [\n \"publication_number\",\n \"title_localized\",\n \"abstract_localized\",\n \"publication_date\",\n \"assignee_harmonized\",\n ],\n limit = 25,\n): Promise<BigQueryResult> => {\n const selectedFields = fields.join(\", \")\n const sql = `\n SELECT ${selectedFields}\n FROM \\`${DATASET}\\`\n WHERE SEARCH(abstract_localized.text, @query)\n OR SEARCH(title_localized.text, @query)\n ORDER BY publication_date DESC\n LIMIT @limit\n `\n return runQuery(sql, { query, limit })\n}\n\nexport const bigqueryPatentFamily = async (familyId: string): Promise<BigQueryResult> => {\n const sql = `\n SELECT\n publication_number,\n country_code,\n title_localized,\n publication_date,\n grant_date,\n application_number,\n priority_date\n FROM \\`${DATASET}\\`\n WHERE family_id = @familyId\n ORDER BY publication_date\n `\n return runQuery(sql, { familyId })\n}\n\nexport const bigqueryCitationNetwork = async (publicationNumber: string, depth = 1): Promise<BigQueryResult> => {\n if (depth === 1) {\n const sql = `\n SELECT\n p.publication_number AS source,\n c.publication_number AS cited_publication,\n c.category,\n c.type\n FROM \\`${DATASET}\\` p,\n UNNEST(citation) AS c\n WHERE p.publication_number = @publicationNumber\n `\n return runQuery(sql, { publicationNumber })\n }\n\n // Depth 2: citations of citations\n const sql = `\n WITH level1 AS (\n SELECT\n p.publication_number AS source,\n c.publication_number AS cited\n FROM \\`${DATASET}\\` p,\n UNNEST(citation) AS c\n WHERE p.publication_number = @publicationNumber\n ),\n level2 AS (\n SELECT\n l1.cited AS source,\n c.publication_number AS cited\n FROM level1 l1\n JOIN \\`${DATASET}\\` p ON p.publication_number = l1.cited,\n UNNEST(citation) AS c\n )\n SELECT * FROM level1\n UNION ALL\n SELECT * FROM level2\n LIMIT 500\n `\n return runQuery(sql, { publicationNumber })\n}\n\nexport const bigqueryCpcAnalytics = async (\n cpcPrefix: string,\n dateFrom?: string,\n dateTo?: string,\n): Promise<BigQueryResult> => {\n const dateFilter = [\n dateFrom ? \"AND publication_date >= @dateFrom\" : \"\",\n dateTo ? \"AND publication_date <= @dateTo\" : \"\",\n ].join(\" \")\n\n const sql = `\n SELECT\n c.code AS cpc_code,\n COUNT(*) AS patent_count,\n COUNT(DISTINCT assignee.name) AS unique_assignees,\n MIN(publication_date) AS earliest_publication,\n MAX(publication_date) AS latest_publication\n FROM \\`${DATASET}\\` p,\n UNNEST(cpc) AS c,\n UNNEST(assignee_harmonized) AS assignee\n WHERE c.code LIKE @cpcPrefix\n ${dateFilter}\n GROUP BY c.code\n ORDER BY patent_count DESC\n LIMIT 100\n `\n\n const params: Record<string, unknown> = { cpcPrefix: `${cpcPrefix}%` }\n if (dateFrom) params.dateFrom = Number(dateFrom)\n if (dateTo) params.dateTo = Number(dateTo)\n\n return runQuery(sql, params)\n}\n"],"mappings":"4FAIA,MAAM,EAAU,2CASV,MACG,IAAI,EAAS,CAClB,UAAW,EAAO,mBACnB,CAAC,CAGE,EAAgB,GAA0B,CAC9C,IAAM,EAAK,OAAO,EAAM,CAAG,aAE3B,OADI,GAAM,EAAU,qCACb,MAAM,EAAK,GAAG,QAAQ,EAAE,CAAC,IAAI,EAAG,QAAQ,EAAE,CAAC,gBAG9C,EAAW,MAAO,EAAa,IAA8D,CACjG,IAAM,EAAS,GAAmB,CAG5B,CAAC,GAAa,MAAM,EAAO,eAAe,CAC9C,MAAO,EACP,SACA,OAAQ,GACR,aAAc,GACf,CAAC,CAEI,EAAiB,EAAU,UAAU,YAAY,qBAAuB,IACxE,EAAe,EAAa,EAAe,CAG3C,CAAC,GAAO,MAAM,EAAO,eAAe,CACxC,MAAO,EACP,SACA,aAAc,GACf,CAAC,CAEI,CAAC,GAAQ,MAAM,EAAI,iBAAiB,CAE1C,MAAO,CACC,OACN,UAAW,EAAK,OAChB,wBAAyB,EACzB,iBAAkB,EACnB,EAGU,EAAuB,MAClC,EACA,EAAmB,CACjB,qBACA,kBACA,qBACA,mBACA,sBACD,CACD,EAAQ,KAWD,EARK;aADW,EAAO,KAAK,KAAK,CAEd;aACf,EAAQ;;;;;IAME,CAAE,QAAO,QAAO,CAAC,CAG3B,EAAuB,KAAO,IAclC,EAbK;;;;;;;;;aASD,EAAQ;;;IAIE,CAAE,WAAU,CAAC,CAGvB,EAA0B,MAAO,EAA2B,EAAQ,IAYtE,EAXL,IAAU,EACA;;;;;;eAMD,EAAQ;;;MAQT;;;;;eAKC,EAAQ;;;;;;;;;eASR,EAAQ;;;;;;;IAlBE,CAAE,oBAAmB,CAAC,CA6BlC,EAAuB,MAClC,EACA,EACA,IAC4B,CAM5B,IAAM,EAAM;;;;;;;aAOD,EAAQ;;;;QAZA,CACjB,EAAW,oCAAsC,GACjD,EAAS,kCAAoC,GAC9C,CAAC,KAAK,IAAI,CAaM;;;;IAMX,EAAkC,CAAE,UAAW,GAAG,EAAU,GAAI,CAItE,OAHI,IAAU,EAAO,SAAW,OAAO,EAAS,EAC5C,IAAQ,EAAO,OAAS,OAAO,EAAO,EAEnC,EAAS,EAAK,EAAO"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
//#region src/clients/epo-ops.client.d.ts
|
|
2
|
+
type EpoNumberFormat = "docdb" | "epodoc" | "original";
|
|
3
|
+
declare const epoSearchPatents: (query: string, range?: string) => Promise<unknown>;
|
|
4
|
+
declare const epoGetBiblio: (number: string, format?: EpoNumberFormat) => Promise<unknown>;
|
|
5
|
+
declare const epoGetAbstract: (number: string, format?: EpoNumberFormat) => Promise<unknown>;
|
|
6
|
+
declare const epoGetClaims: (number: string, format?: EpoNumberFormat) => Promise<unknown>;
|
|
7
|
+
declare const epoGetDescription: (number: string, format?: EpoNumberFormat) => Promise<unknown>;
|
|
8
|
+
declare const epoFamilyLookup: (number: string, format?: EpoNumberFormat) => Promise<unknown>;
|
|
9
|
+
declare const epoLegalStatus: (number: string, format?: EpoNumberFormat) => Promise<unknown>;
|
|
10
|
+
declare const epoNumberConvert: (number: string, inputFormat: EpoNumberFormat, outputFormat: EpoNumberFormat) => Promise<unknown>;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { epoFamilyLookup, epoGetAbstract, epoGetBiblio, epoGetClaims, epoGetDescription, epoLegalStatus, epoNumberConvert, epoSearchPatents };
|
|
13
|
+
//# sourceMappingURL=epo-ops.client.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{config as e}from"../lib/config.js";import{withRetry as t}from"../lib/retry.js";import{XMLParser as n}from"fast-xml-parser";let r;const i=new n({ignoreAttributes:!1,attributeNamePrefix:`@_`,removeNSPrefix:!0,isArray:e=>[`exchange-document`,`document-id`,`classification-ipcr`,`classification-cpc`,`patent-classification`,`applicant`,`inventor`,`priority-claim`,`family-member`,`legal`].includes(e)}),a=async()=>{if(r&&Date.now()<r.expiresAt)return r.token;let t=e.epoConsumerKey,n=e.epoConsumerSecret;if(!t||!n)throw Error(`EPO OPS credentials not configured. Set EPO_CONSUMER_KEY and EPO_CONSUMER_SECRET.`);let i=Buffer.from(`${t}:${n}`).toString(`base64`),a=await fetch(`https://ops.epo.org/3.2/auth/accesstoken`,{method:`POST`,headers:{Authorization:`Basic ${i}`,"Content-Type":`application/x-www-form-urlencoded`},body:`grant_type=client_credentials`});if(!a.ok)throw Error(`EPO OAuth failed: ${a.status} ${a.statusText}`);return r={token:(await a.json()).access_token,expiresAt:Date.now()+1140*1e3},r.token},o=()=>{r=void 0},s=async(n,r=`application/xml`)=>t(async()=>{let t=await a(),s=new AbortController,c=setTimeout(()=>s.abort(),e.requestTimeout);try{let e=await fetch(`https://ops.epo.org/3.2/rest-services/${n}`,{headers:{Authorization:`Bearer ${t}`,Accept:r},signal:s.signal});if(e.status===400||e.status===401)throw o(),Error(`EPO auth error: ${e.status}`);if(!e.ok){let t=await e.text();throw Error(`EPO API error ${e.status}: ${t.slice(0,500)}`)}if(e.headers.get(`x-throttling-control`)?.includes(`black`))throw Error(`EPO rate limit exceeded (black). Wait before retrying.`);if(r===`application/json`)return await e.json();let a=await e.text();return i.parse(a)}finally{clearTimeout(c)}},{maxRetries:e.maxRetries,minWait:e.retryMinWait,maxWait:e.retryMaxWait}),c=(e,t=`docdb`)=>{let n=e.replace(/\s+/g,``).replace(/[/,]/g,``);switch(t){case`docdb`:return n;case`epodoc`:return n;case`original`:return e;default:return n}},l=async(e,t)=>{let n=t?`&Range=${t}`:``;return s(`published-data/search?q=${encodeURIComponent(e)}${n}`)},u=async(e,t=`docdb`)=>s(`published-data/publication/${t}/${c(e,t)}/biblio`),d=async(e,t=`docdb`)=>s(`published-data/publication/${t}/${c(e,t)}/abstract`),f=async(e,t=`docdb`)=>s(`published-data/publication/${t}/${c(e,t)}/claims`),p=async(e,t=`docdb`)=>s(`published-data/publication/${t}/${c(e,t)}/description`),m=async(e,t=`docdb`)=>s(`family/publication/${t}/${c(e,t)}`),h=async(e,t=`docdb`)=>s(`published-data/publication/${t}/${c(e,t)}/legal`),g=async(e,t,n)=>s(`number-service/${t}/${c(e,t)}/${n}`);export{m as epoFamilyLookup,d as epoGetAbstract,u as epoGetBiblio,f as epoGetClaims,p as epoGetDescription,h as epoLegalStatus,g as epoNumberConvert,l as epoSearchPatents};
|
|
2
|
+
//# sourceMappingURL=epo-ops.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"epo-ops.client.js","names":[],"sources":["../../src/clients/epo-ops.client.ts"],"sourcesContent":["import { XMLParser } from \"fast-xml-parser\"\n\nimport { config } from \"../lib/config\"\nimport { withRetry } from \"../lib/retry\"\nimport { BaseClient } from \"./base.client\"\n\nconst EPO_AUTH_URL = \"https://ops.epo.org/3.2/auth/accesstoken\"\nconst EPO_BASE_URL = \"https://ops.epo.org/3.2/rest-services/\"\n\ntype EpoNumberFormat = \"docdb\" | \"epodoc\" | \"original\"\n\ntype TokenCache = {\n token: string\n expiresAt: number\n}\n\nlet tokenCache: TokenCache | undefined\n\nconst xmlParser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n removeNSPrefix: true,\n isArray: (name) => {\n const arrayElements = [\n \"exchange-document\",\n \"document-id\",\n \"classification-ipcr\",\n \"classification-cpc\",\n \"patent-classification\",\n \"applicant\",\n \"inventor\",\n \"priority-claim\",\n \"family-member\",\n \"legal\",\n ]\n return arrayElements.includes(name)\n },\n})\n\nconst getAccessToken = async (): Promise<string> => {\n if (tokenCache && Date.now() < tokenCache.expiresAt) {\n return tokenCache.token\n }\n\n const key = config.epoConsumerKey\n const secret = config.epoConsumerSecret\n\n if (!key || !secret) {\n throw new Error(\"EPO OPS credentials not configured. Set EPO_CONSUMER_KEY and EPO_CONSUMER_SECRET.\")\n }\n\n const credentials = Buffer.from(`${key}:${secret}`).toString(\"base64\")\n\n const response = await fetch(EPO_AUTH_URL, {\n method: \"POST\",\n headers: {\n Authorization: `Basic ${credentials}`,\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: \"grant_type=client_credentials\",\n })\n\n if (!response.ok) {\n throw new Error(`EPO OAuth failed: ${response.status} ${response.statusText}`)\n }\n\n const data = (await response.json()) as { access_token: string }\n tokenCache = {\n token: data.access_token,\n expiresAt: Date.now() + 19 * 60 * 1000, // 19 min (1 min buffer before 20 min expiry)\n }\n\n return tokenCache.token\n}\n\nconst clearTokenCache = (): void => {\n tokenCache = undefined\n}\n\nconst epoRequest = async <T>(path: string, accept = \"application/xml\"): Promise<T> => {\n const makeRequest = async (): Promise<T> => {\n const token = await getAccessToken()\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), config.requestTimeout)\n\n try {\n const response = await fetch(`${EPO_BASE_URL}${path}`, {\n headers: {\n Authorization: `Bearer ${token}`,\n Accept: accept,\n },\n signal: controller.signal,\n })\n\n if (response.status === 400 || response.status === 401) {\n clearTokenCache()\n throw new Error(`EPO auth error: ${response.status}`)\n }\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(`EPO API error ${response.status}: ${text.slice(0, 500)}`)\n }\n\n const throttling = response.headers.get(\"x-throttling-control\")\n if (throttling?.includes(\"black\")) {\n throw new Error(\"EPO rate limit exceeded (black). Wait before retrying.\")\n }\n\n if (accept === \"application/json\") {\n return (await response.json()) as T\n }\n\n const xml = await response.text()\n return xmlParser.parse(xml) as T\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n return withRetry(makeRequest, {\n maxRetries: config.maxRetries,\n minWait: config.retryMinWait,\n maxWait: config.retryMaxWait,\n })\n}\n\nconst formatNumber = (number: string, format: EpoNumberFormat = \"docdb\"): string => {\n const cleaned = number.replace(/\\s+/g, \"\").replace(/[/,]/g, \"\")\n switch (format) {\n case \"docdb\":\n return cleaned\n case \"epodoc\":\n return cleaned\n case \"original\":\n return number\n default:\n return cleaned\n }\n}\n\nexport const epoSearchPatents = async (query: string, range?: string): Promise<unknown> => {\n const rangePart = range ? `&Range=${range}` : \"\"\n return epoRequest(`published-data/search?q=${encodeURIComponent(query)}${rangePart}`)\n}\n\nexport const epoGetBiblio = async (number: string, format: EpoNumberFormat = \"docdb\"): Promise<unknown> => {\n const num = formatNumber(number, format)\n return epoRequest(`published-data/publication/${format}/${num}/biblio`)\n}\n\nexport const epoGetAbstract = async (number: string, format: EpoNumberFormat = \"docdb\"): Promise<unknown> => {\n const num = formatNumber(number, format)\n return epoRequest(`published-data/publication/${format}/${num}/abstract`)\n}\n\nexport const epoGetClaims = async (number: string, format: EpoNumberFormat = \"docdb\"): Promise<unknown> => {\n const num = formatNumber(number, format)\n return epoRequest(`published-data/publication/${format}/${num}/claims`)\n}\n\nexport const epoGetDescription = async (number: string, format: EpoNumberFormat = \"docdb\"): Promise<unknown> => {\n const num = formatNumber(number, format)\n return epoRequest(`published-data/publication/${format}/${num}/description`)\n}\n\nexport const epoFamilyLookup = async (number: string, format: EpoNumberFormat = \"docdb\"): Promise<unknown> => {\n const num = formatNumber(number, format)\n return epoRequest(`family/publication/${format}/${num}`)\n}\n\nexport const epoLegalStatus = async (number: string, format: EpoNumberFormat = \"docdb\"): Promise<unknown> => {\n const num = formatNumber(number, format)\n return epoRequest(`published-data/publication/${format}/${num}/legal`)\n}\n\nexport const epoNumberConvert = async (\n number: string,\n inputFormat: EpoNumberFormat,\n outputFormat: EpoNumberFormat,\n): Promise<unknown> => {\n const num = formatNumber(number, inputFormat)\n return epoRequest(`number-service/${inputFormat}/${num}/${outputFormat}`)\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
//#region src/clients/odp.client.d.ts
|
|
2
|
+
type OdpConfig = {
|
|
3
|
+
readonly apiKey: string;
|
|
4
|
+
readonly baseUrl?: string;
|
|
5
|
+
readonly timeout?: number;
|
|
6
|
+
};
|
|
7
|
+
declare const getOdpConfig: () => OdpConfig;
|
|
8
|
+
declare class OdpClient {
|
|
9
|
+
private readonly client;
|
|
10
|
+
constructor(config?: OdpConfig);
|
|
11
|
+
searchApplications(query: string, limit?: number, offset?: number, sort?: string): Promise<unknown>;
|
|
12
|
+
getApplication(appNum: string): Promise<unknown>;
|
|
13
|
+
getApplicationMetadata(appNum: string): Promise<unknown>;
|
|
14
|
+
getContinuity(appNum: string): Promise<unknown>;
|
|
15
|
+
getAssignment(appNum: string): Promise<unknown>;
|
|
16
|
+
getAdjustment(appNum: string): Promise<unknown>;
|
|
17
|
+
getAttorney(appNum: string): Promise<unknown>;
|
|
18
|
+
getForeignPriority(appNum: string): Promise<unknown>;
|
|
19
|
+
getTransactions(appNum: string): Promise<unknown>;
|
|
20
|
+
getDocuments(appNum: string): Promise<unknown>;
|
|
21
|
+
searchDatasets(query: string): Promise<unknown>;
|
|
22
|
+
getDataset(productId: string): Promise<unknown>;
|
|
23
|
+
searchProceedings(query: string, type?: string, limit?: number): Promise<unknown>;
|
|
24
|
+
getProceeding(trialNumber: string): Promise<unknown>;
|
|
25
|
+
getProceedingDocuments(trialNumber: string): Promise<unknown>;
|
|
26
|
+
searchDecisions(query: string, limit?: number): Promise<unknown>;
|
|
27
|
+
getDecision(decisionId: string): Promise<unknown>;
|
|
28
|
+
searchAppeals(query: string, limit?: number): Promise<unknown>;
|
|
29
|
+
getAppeal(appealId: string): Promise<unknown>;
|
|
30
|
+
getEnrichedCitations(patentNumber: string): Promise<unknown>;
|
|
31
|
+
searchCitations(query: string, limit?: number): Promise<unknown>;
|
|
32
|
+
getCitationMetrics(patentNumber: string): Promise<unknown>;
|
|
33
|
+
searchLitigation(params: {
|
|
34
|
+
query?: string;
|
|
35
|
+
plaintiff?: string;
|
|
36
|
+
defendant?: string;
|
|
37
|
+
patent_number?: string;
|
|
38
|
+
court?: string;
|
|
39
|
+
date_from?: string;
|
|
40
|
+
date_to?: string;
|
|
41
|
+
limit?: number;
|
|
42
|
+
}): Promise<unknown>;
|
|
43
|
+
getLitigationCase(caseId: string): Promise<unknown>;
|
|
44
|
+
getLitigationByPatent(patentNumber: string): Promise<unknown>;
|
|
45
|
+
getOfficeActionText(applicationNumber: string): Promise<unknown>;
|
|
46
|
+
searchOfficeActions(query: string, limit?: number): Promise<unknown>;
|
|
47
|
+
getOfficeActionCitations(applicationNumber: string): Promise<unknown>;
|
|
48
|
+
getOfficeActionRejections(applicationNumber: string): Promise<unknown>;
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { OdpClient, OdpConfig, getOdpConfig };
|
|
52
|
+
//# sourceMappingURL=odp.client.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{normalizePatentNumber as e}from"../lib/patent-number.js";import{n as t,t as n}from"../base.client-zZnUjoIb.js";const r=()=>{let e=process.env.USPTO_API_KEY;if(!e)throw Error(`USPTO_API_KEY environment variable is required for ODP client`);return{apiKey:e,baseUrl:process.env.USPTO_BASE_URL??`https://api.uspto.gov/api/v1/`,timeout:process.env.USPTO_TIMEOUT?parseInt(process.env.USPTO_TIMEOUT,10):3e4}};var i=class{constructor(e){t(this,`client`,void 0);let i=e??r();this.client=new n({baseUrl:i.baseUrl??`https://api.uspto.gov/api/v1/`,headers:{"X-API-KEY":i.apiKey},timeout:i.timeout})}async searchApplications(e,t,n,r){let i={searchText:e};return t!==void 0&&(i.limit=String(t)),n!==void 0&&(i.offset=String(n)),r!==void 0&&(i.sort=r),this.client.get(`patent/applications`,i)}async getApplication(t){return this.client.get(`patent/applications/${e(t)}`)}async getApplicationMetadata(t){return this.client.get(`patent/applications/${e(t)}/metadata`)}async getContinuity(t){return this.client.get(`patent/applications/${e(t)}/continuity`)}async getAssignment(t){return this.client.get(`patent/applications/${e(t)}/assignment`)}async getAdjustment(t){return this.client.get(`patent/applications/${e(t)}/adjustment`)}async getAttorney(t){return this.client.get(`patent/applications/${e(t)}/attorney`)}async getForeignPriority(t){return this.client.get(`patent/applications/${e(t)}/foreign-priority`)}async getTransactions(t){return this.client.get(`patent/applications/${e(t)}/transactions`)}async getDocuments(t){return this.client.get(`patent/applications/${e(t)}/documents`)}async searchDatasets(e){return this.client.get(`datasets`,{searchText:e})}async getDataset(e){return this.client.get(`datasets/${e}`)}async searchProceedings(e,t,n){let r={searchText:e};return t!==void 0&&(r.type=t),n!==void 0&&(r.limit=String(n)),this.client.get(`patent/trials`,r)}async getProceeding(e){return this.client.get(`patent/trials/${e}`)}async getProceedingDocuments(e){return this.client.get(`patent/trials/${e}/documents`)}async searchDecisions(e,t){let n={searchText:e};return t!==void 0&&(n.limit=String(t)),this.client.get(`patent/trials/decisions`,n)}async getDecision(e){return this.client.get(`patent/trials/decisions/${e}`)}async searchAppeals(e,t){let n={searchText:e};return t!==void 0&&(n.limit=String(t)),this.client.get(`patent/appeals`,n)}async getAppeal(e){return this.client.get(`patent/appeals/${e}`)}async getEnrichedCitations(t){return this.client.get(`patent/citations/${e(t)}`)}async searchCitations(e,t){let n={searchText:e};return t!==void 0&&(n.limit=String(t)),this.client.get(`patent/citations`,n)}async getCitationMetrics(t){return this.client.get(`patent/citations/${e(t)}/metrics`)}async searchLitigation(t){let n={};return t.query!==void 0&&(n.searchText=t.query),t.plaintiff!==void 0&&(n.plaintiff=t.plaintiff),t.defendant!==void 0&&(n.defendant=t.defendant),t.patent_number!==void 0&&(n.patentNumber=e(t.patent_number)),t.court!==void 0&&(n.court=t.court),t.date_from!==void 0&&(n.dateFrom=t.date_from),t.date_to!==void 0&&(n.dateTo=t.date_to),t.limit!==void 0&&(n.limit=String(t.limit)),this.client.get(`patent/litigation`,n)}async getLitigationCase(e){return this.client.get(`patent/litigation/${e}`)}async getLitigationByPatent(t){return this.client.get(`patent/litigation/patent/${e(t)}`)}async getOfficeActionText(t){return this.client.get(`patent/office-actions/${e(t)}/text`)}async searchOfficeActions(e,t){let n={searchText:e};return t!==void 0&&(n.limit=String(t)),this.client.get(`patent/office-actions`,n)}async getOfficeActionCitations(t){return this.client.get(`patent/office-actions/${e(t)}/citations`)}async getOfficeActionRejections(t){return this.client.get(`patent/office-actions/${e(t)}/rejections`)}};export{i as OdpClient,r as getOdpConfig};
|
|
2
|
+
//# sourceMappingURL=odp.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"odp.client.js","names":[],"sources":["../../src/clients/odp.client.ts"],"sourcesContent":["import { normalizePatentNumber } from \"../lib/patent-number\"\nimport { BaseClient } from \"./base.client\"\n\nexport type OdpConfig = {\n readonly apiKey: string\n readonly baseUrl?: string\n readonly timeout?: number\n}\n\nexport const getOdpConfig = (): OdpConfig => {\n const apiKey = process.env.USPTO_API_KEY\n if (!apiKey) {\n throw new Error(\"USPTO_API_KEY environment variable is required for ODP client\")\n }\n return {\n apiKey,\n baseUrl: process.env.USPTO_BASE_URL ?? \"https://api.uspto.gov/api/v1/\",\n timeout: process.env.USPTO_TIMEOUT ? parseInt(process.env.USPTO_TIMEOUT, 10) : 30000,\n }\n}\n\nexport class OdpClient {\n private readonly client: BaseClient\n\n constructor(config?: OdpConfig) {\n const cfg = config ?? getOdpConfig()\n this.client = new BaseClient({\n baseUrl: cfg.baseUrl ?? \"https://api.uspto.gov/api/v1/\",\n headers: {\n \"X-API-KEY\": cfg.apiKey,\n },\n timeout: cfg.timeout,\n })\n }\n\n // ── Application Methods ──────────────────────────────────────────────\n\n async searchApplications(query: string, limit?: number, offset?: number, sort?: string): Promise<unknown> {\n const params: Record<string, string> = { searchText: query }\n if (limit !== undefined) params.limit = String(limit)\n if (offset !== undefined) params.offset = String(offset)\n if (sort !== undefined) params.sort = sort\n return this.client.get(\"patent/applications\", params)\n }\n\n async getApplication(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}`)\n }\n\n async getApplicationMetadata(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/metadata`)\n }\n\n async getContinuity(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/continuity`)\n }\n\n async getAssignment(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/assignment`)\n }\n\n async getAdjustment(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/adjustment`)\n }\n\n async getAttorney(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/attorney`)\n }\n\n async getForeignPriority(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/foreign-priority`)\n }\n\n async getTransactions(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/transactions`)\n }\n\n async getDocuments(appNum: string): Promise<unknown> {\n return this.client.get(`patent/applications/${normalizePatentNumber(appNum)}/documents`)\n }\n\n // ── Dataset Methods ──────────────────────────────────────────────────\n\n async searchDatasets(query: string): Promise<unknown> {\n return this.client.get(\"datasets\", { searchText: query })\n }\n\n async getDataset(productId: string): Promise<unknown> {\n return this.client.get(`datasets/${productId}`)\n }\n\n // ── PTAB Methods ─────────────────────────────────────────────────────\n\n async searchProceedings(query: string, type?: string, limit?: number): Promise<unknown> {\n const params: Record<string, string> = { searchText: query }\n if (type !== undefined) params.type = type\n if (limit !== undefined) params.limit = String(limit)\n return this.client.get(\"patent/trials\", params)\n }\n\n async getProceeding(trialNumber: string): Promise<unknown> {\n return this.client.get(`patent/trials/${trialNumber}`)\n }\n\n async getProceedingDocuments(trialNumber: string): Promise<unknown> {\n return this.client.get(`patent/trials/${trialNumber}/documents`)\n }\n\n async searchDecisions(query: string, limit?: number): Promise<unknown> {\n const params: Record<string, string> = { searchText: query }\n if (limit !== undefined) params.limit = String(limit)\n return this.client.get(\"patent/trials/decisions\", params)\n }\n\n async getDecision(decisionId: string): Promise<unknown> {\n return this.client.get(`patent/trials/decisions/${decisionId}`)\n }\n\n async searchAppeals(query: string, limit?: number): Promise<unknown> {\n const params: Record<string, string> = { searchText: query }\n if (limit !== undefined) params.limit = String(limit)\n return this.client.get(\"patent/appeals\", params)\n }\n\n async getAppeal(appealId: string): Promise<unknown> {\n return this.client.get(`patent/appeals/${appealId}`)\n }\n\n // ── Citation / Litigation Methods ────────────────────────────────────\n\n async getEnrichedCitations(patentNumber: string): Promise<unknown> {\n return this.client.get(`patent/citations/${normalizePatentNumber(patentNumber)}`)\n }\n\n async searchCitations(query: string, limit?: number): Promise<unknown> {\n const params: Record<string, string> = { searchText: query }\n if (limit !== undefined) params.limit = String(limit)\n return this.client.get(\"patent/citations\", params)\n }\n\n async getCitationMetrics(patentNumber: string): Promise<unknown> {\n return this.client.get(`patent/citations/${normalizePatentNumber(patentNumber)}/metrics`)\n }\n\n async searchLitigation(params: {\n query?: string\n plaintiff?: string\n defendant?: string\n patent_number?: string\n court?: string\n date_from?: string\n date_to?: string\n limit?: number\n }): Promise<unknown> {\n const searchParams: Record<string, string> = {}\n if (params.query !== undefined) searchParams.searchText = params.query\n if (params.plaintiff !== undefined) searchParams.plaintiff = params.plaintiff\n if (params.defendant !== undefined) searchParams.defendant = params.defendant\n if (params.patent_number !== undefined) searchParams.patentNumber = normalizePatentNumber(params.patent_number)\n if (params.court !== undefined) searchParams.court = params.court\n if (params.date_from !== undefined) searchParams.dateFrom = params.date_from\n if (params.date_to !== undefined) searchParams.dateTo = params.date_to\n if (params.limit !== undefined) searchParams.limit = String(params.limit)\n return this.client.get(\"patent/litigation\", searchParams)\n }\n\n async getLitigationCase(caseId: string): Promise<unknown> {\n return this.client.get(`patent/litigation/${caseId}`)\n }\n\n async getLitigationByPatent(patentNumber: string): Promise<unknown> {\n return this.client.get(`patent/litigation/patent/${normalizePatentNumber(patentNumber)}`)\n }\n\n // ── Office Action Methods ───────────────────────────────────────────\n\n async getOfficeActionText(applicationNumber: string): Promise<unknown> {\n return this.client.get(`patent/office-actions/${normalizePatentNumber(applicationNumber)}/text`)\n }\n\n async searchOfficeActions(query: string, limit?: number): Promise<unknown> {\n const params: Record<string, string> = { searchText: query }\n if (limit !== undefined) params.limit = String(limit)\n return this.client.get(\"patent/office-actions\", params)\n }\n\n async getOfficeActionCitations(applicationNumber: string): Promise<unknown> {\n return this.client.get(`patent/office-actions/${normalizePatentNumber(applicationNumber)}/citations`)\n }\n\n async getOfficeActionRejections(applicationNumber: string): Promise<unknown> {\n return this.client.get(`patent/office-actions/${normalizePatentNumber(applicationNumber)}/rejections`)\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { zAssigneeSuccessResponse, zAttorneySuccessResponse, zCpcSubclassSuccessResponse, zGClaimSuccessResponse, zInventorSuccessResponse, zIpcClassificationSuccessResponse, zPatentSuccessResponse } from "../generated/patentsview/zod.gen.js";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
//#region src/clients/patentsview.client.d.ts
|
|
5
|
+
type PatentsViewClientOptions = {
|
|
6
|
+
readonly baseUrl?: string;
|
|
7
|
+
readonly apiKey?: string;
|
|
8
|
+
readonly timeout?: number;
|
|
9
|
+
};
|
|
10
|
+
type PatentResponse = z.infer<typeof zPatentSuccessResponse>;
|
|
11
|
+
type AssigneeResponse = z.infer<typeof zAssigneeSuccessResponse>;
|
|
12
|
+
type InventorResponse = z.infer<typeof zInventorSuccessResponse>;
|
|
13
|
+
type AttorneyResponse = z.infer<typeof zAttorneySuccessResponse>;
|
|
14
|
+
type ClaimResponse = z.infer<typeof zGClaimSuccessResponse>;
|
|
15
|
+
type CpcSubclassResponse = z.infer<typeof zCpcSubclassSuccessResponse>;
|
|
16
|
+
type IpcResponse = z.infer<typeof zIpcClassificationSuccessResponse>;
|
|
17
|
+
declare class PatentsViewClient {
|
|
18
|
+
private readonly client;
|
|
19
|
+
constructor(options?: PatentsViewClientOptions);
|
|
20
|
+
searchPatents(query: string, searchType?: "text" | "assignee" | "inventor", limit?: number): Promise<PatentResponse>;
|
|
21
|
+
getPatent(patentId: string): Promise<PatentResponse>;
|
|
22
|
+
searchAssignees(name: string, limit?: number): Promise<AssigneeResponse>;
|
|
23
|
+
getAssignee(id: string): Promise<AssigneeResponse>;
|
|
24
|
+
searchInventors(name: string, limit?: number): Promise<InventorResponse>;
|
|
25
|
+
getInventor(id: string): Promise<InventorResponse>;
|
|
26
|
+
searchAttorneys(name: string, limit?: number): Promise<AttorneyResponse>;
|
|
27
|
+
getAttorney(id: string): Promise<AttorneyResponse>;
|
|
28
|
+
getClaims(patentId: string): Promise<ClaimResponse>;
|
|
29
|
+
getDescription(patentId: string): Promise<PatentResponse>;
|
|
30
|
+
searchByCpc(cpcCode: string, limit?: number): Promise<PatentResponse>;
|
|
31
|
+
lookupCpc(cpcCode: string): Promise<CpcSubclassResponse>;
|
|
32
|
+
searchByIpc(ipcCode: string, limit?: number): Promise<PatentResponse>;
|
|
33
|
+
lookupIpc(ipcCode: string): Promise<IpcResponse>;
|
|
34
|
+
private buildPatentQuery;
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
export { AssigneeResponse, AttorneyResponse, ClaimResponse, CpcSubclassResponse, InventorResponse, IpcResponse, PatentResponse, PatentsViewClient, PatentsViewClientOptions };
|
|
38
|
+
//# sourceMappingURL=patentsview.client.d.ts.map
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{n as e,t}from"../base.client-zZnUjoIb.js";import{zAssigneeSuccessResponse as n,zAttorneySuccessResponse as r,zCpcSubclassSuccessResponse as i,zGClaimSuccessResponse as a,zInventorSuccessResponse as o,zIpcClassificationSuccessResponse as s,zPatentSuccessResponse as c}from"../generated/patentsview/zod.gen.js";const l=(e,t)=>{let n=e.safeParse(t);return n.success?n.data:t},u=[`patent_id`,`patent_title`,`patent_abstract`,`patent_date`,`patent_type`,`assignees`,`inventors`],d=(e,t,n)=>{let r={q:JSON.stringify(e)};return t&&(r.f=JSON.stringify(t)),n&&(r.o=JSON.stringify(n)),r};var f=class{constructor(n){e(this,`client`,void 0);let r=n?.baseUrl??`https://search.patentsview.org/api/v1/`,i={};n?.apiKey&&(i[`X-Api-Key`]=n.apiKey),this.client=new t({baseUrl:r,headers:i,timeout:n?.timeout})}async searchPatents(e,t=`text`,n=25){let r=d(this.buildPatentQuery(e,t),[...u],{size:n});return l(c,await this.client.get(`patent/`,r))}async getPatent(e){return l(c,await this.client.get(`patent/${e}/`))}async searchAssignees(e,t=25){let r=d({_text_any:{assignee_organization:e}},void 0,{size:t});return l(n,await this.client.get(`assignee/`,r))}async getAssignee(e){return l(n,await this.client.get(`assignee/${e}/`))}async searchInventors(e,t=25){let n=d({_or:[{_text_any:{inventor_name_first:e}},{_text_any:{inventor_name_last:e}}]},void 0,{size:t});return l(o,await this.client.get(`inventor/`,n))}async getInventor(e){return l(o,await this.client.get(`inventor/${e}/`))}async searchAttorneys(e,t=25){let n=d({_or:[{_text_any:{attorney_organization:e}},{_text_any:{attorney_name_last:e}}]},void 0,{size:t});return l(r,await this.client.get(`patent/attorney/`,n))}async getAttorney(e){return l(r,await this.client.get(`patent/attorney/${e}/`))}async getClaims(e){let t=d({_eq:{patent_id:e}});return l(a,await this.client.get(`g_claim/`,t))}async getDescription(e){let t={f:JSON.stringify([`patent_id`,`patent_title`,`patent_abstract`])};return l(c,await this.client.get(`patent/${e}/`,t))}async searchByCpc(e,t=25){let n=d({_eq:{cpc_subgroup_id:e}},[...u],{size:t});return l(c,await this.client.get(`patent/`,n))}async lookupCpc(e){let t=d({_eq:{cpc_subclass_id:e}});return l(i,await this.client.get(`cpc_subclass/`,t))}async searchByIpc(e,t=25){let n=d({_eq:{ipc_class:e}},[...u],{size:t});return l(c,await this.client.get(`patent/`,n))}async lookupIpc(e){let t=d({_eq:{ipc_class:e}});return l(s,await this.client.get(`ipc/`,t))}buildPatentQuery(e,t){switch(t){case`text`:return{_text_any:{patent_abstract:e}};case`assignee`:return{_text_any:{assignee_organization:e}};case`inventor`:return{_or:[{_text_any:{inventor_name_first:e}},{_text_any:{inventor_name_last:e}}]}}}};export{f as PatentsViewClient};
|
|
2
|
+
//# sourceMappingURL=patentsview.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"patentsview.client.js","names":[],"sources":["../../src/clients/patentsview.client.ts"],"sourcesContent":["import type { z, ZodType } from \"zod\"\n\nimport {\n zAssigneeSuccessResponse,\n zAttorneySuccessResponse,\n zCpcSubclassSuccessResponse,\n zGClaimSuccessResponse,\n zInventorSuccessResponse,\n zIpcClassificationSuccessResponse,\n zPatentSuccessResponse,\n} from \"../generated/patentsview/zod.gen\"\nimport { BaseClient } from \"./base.client\"\n\nconst looseParse = <T extends ZodType>(schema: T, data: unknown): z.infer<T> => {\n const result = schema.safeParse(data)\n return result.success ? result.data : (data as z.infer<T>)\n}\n\nexport type PatentsViewClientOptions = {\n readonly baseUrl?: string\n readonly apiKey?: string\n readonly timeout?: number\n}\n\nexport type PatentResponse = z.infer<typeof zPatentSuccessResponse>\nexport type AssigneeResponse = z.infer<typeof zAssigneeSuccessResponse>\nexport type InventorResponse = z.infer<typeof zInventorSuccessResponse>\nexport type AttorneyResponse = z.infer<typeof zAttorneySuccessResponse>\nexport type ClaimResponse = z.infer<typeof zGClaimSuccessResponse>\nexport type CpcSubclassResponse = z.infer<typeof zCpcSubclassSuccessResponse>\nexport type IpcResponse = z.infer<typeof zIpcClassificationSuccessResponse>\n\nconst DEFAULT_PATENT_FIELDS = [\n \"patent_id\",\n \"patent_title\",\n \"patent_abstract\",\n \"patent_date\",\n \"patent_type\",\n \"assignees\",\n \"inventors\",\n] as const\n\nconst buildParams = (\n q: Record<string, unknown>,\n f?: ReadonlyArray<string>,\n o?: Record<string, unknown>,\n): Record<string, string> => {\n const params: Record<string, string> = { q: JSON.stringify(q) }\n if (f) params.f = JSON.stringify(f)\n if (o) params.o = JSON.stringify(o)\n return params\n}\n\nexport class PatentsViewClient {\n private readonly client: BaseClient\n\n constructor(options?: PatentsViewClientOptions) {\n const baseUrl = options?.baseUrl ?? \"https://search.patentsview.org/api/v1/\"\n const headers: Record<string, string> = {}\n if (options?.apiKey) {\n headers[\"X-Api-Key\"] = options.apiKey\n }\n\n this.client = new BaseClient({\n baseUrl,\n headers,\n timeout: options?.timeout,\n })\n }\n\n async searchPatents(\n query: string,\n searchType: \"text\" | \"assignee\" | \"inventor\" = \"text\",\n limit = 25,\n ): Promise<PatentResponse> {\n const q = this.buildPatentQuery(query, searchType)\n const params = buildParams(q, [...DEFAULT_PATENT_FIELDS], { size: limit })\n const raw = await this.client.get<unknown>(\"patent/\", params)\n return looseParse(zPatentSuccessResponse, raw)\n }\n\n async getPatent(patentId: string): Promise<PatentResponse> {\n const raw = await this.client.get<unknown>(`patent/${patentId}/`)\n return looseParse(zPatentSuccessResponse, raw)\n }\n\n async searchAssignees(name: string, limit = 25): Promise<AssigneeResponse> {\n const params = buildParams({ _text_any: { assignee_organization: name } }, undefined, { size: limit })\n const raw = await this.client.get<unknown>(\"assignee/\", params)\n return looseParse(zAssigneeSuccessResponse, raw)\n }\n\n async getAssignee(id: string): Promise<AssigneeResponse> {\n const raw = await this.client.get<unknown>(`assignee/${id}/`)\n return looseParse(zAssigneeSuccessResponse, raw)\n }\n\n async searchInventors(name: string, limit = 25): Promise<InventorResponse> {\n const q = {\n _or: [{ _text_any: { inventor_name_first: name } }, { _text_any: { inventor_name_last: name } }],\n }\n const params = buildParams(q, undefined, { size: limit })\n const raw = await this.client.get<unknown>(\"inventor/\", params)\n return looseParse(zInventorSuccessResponse, raw)\n }\n\n async getInventor(id: string): Promise<InventorResponse> {\n const raw = await this.client.get<unknown>(`inventor/${id}/`)\n return looseParse(zInventorSuccessResponse, raw)\n }\n\n async searchAttorneys(name: string, limit = 25): Promise<AttorneyResponse> {\n const q = {\n _or: [{ _text_any: { attorney_organization: name } }, { _text_any: { attorney_name_last: name } }],\n }\n const params = buildParams(q, undefined, { size: limit })\n const raw = await this.client.get<unknown>(\"patent/attorney/\", params)\n return looseParse(zAttorneySuccessResponse, raw)\n }\n\n async getAttorney(id: string): Promise<AttorneyResponse> {\n const raw = await this.client.get<unknown>(`patent/attorney/${id}/`)\n return looseParse(zAttorneySuccessResponse, raw)\n }\n\n async getClaims(patentId: string): Promise<ClaimResponse> {\n const params = buildParams({ _eq: { patent_id: patentId } })\n const raw = await this.client.get<unknown>(\"g_claim/\", params)\n return looseParse(zGClaimSuccessResponse, raw)\n }\n\n async getDescription(patentId: string): Promise<PatentResponse> {\n const params: Record<string, string> = {\n f: JSON.stringify([\"patent_id\", \"patent_title\", \"patent_abstract\"]),\n }\n const raw = await this.client.get<unknown>(`patent/${patentId}/`, params)\n return looseParse(zPatentSuccessResponse, raw)\n }\n\n async searchByCpc(cpcCode: string, limit = 25): Promise<PatentResponse> {\n const params = buildParams({ _eq: { cpc_subgroup_id: cpcCode } }, [...DEFAULT_PATENT_FIELDS], { size: limit })\n const raw = await this.client.get<unknown>(\"patent/\", params)\n return looseParse(zPatentSuccessResponse, raw)\n }\n\n async lookupCpc(cpcCode: string): Promise<CpcSubclassResponse> {\n const params = buildParams({ _eq: { cpc_subclass_id: cpcCode } })\n const raw = await this.client.get<unknown>(\"cpc_subclass/\", params)\n return looseParse(zCpcSubclassSuccessResponse, raw)\n }\n\n async searchByIpc(ipcCode: string, limit = 25): Promise<PatentResponse> {\n const params = buildParams({ _eq: { ipc_class: ipcCode } }, [...DEFAULT_PATENT_FIELDS], { size: limit })\n const raw = await this.client.get<unknown>(\"patent/\", params)\n return looseParse(zPatentSuccessResponse, raw)\n }\n\n async lookupIpc(ipcCode: string): Promise<IpcResponse> {\n const params = buildParams({ _eq: { ipc_class: ipcCode } })\n const raw = await this.client.get<unknown>(\"ipc/\", params)\n return looseParse(zIpcClassificationSuccessResponse, raw)\n }\n\n private buildPatentQuery(query: string, searchType: \"text\" | \"assignee\" | \"inventor\"): Record<string, unknown> {\n switch (searchType) {\n case \"text\":\n return { _text_any: { patent_abstract: query } }\n case \"assignee\":\n return { _text_any: { assignee_organization: query } }\n case \"inventor\":\n return {\n _or: [{ _text_any: { inventor_name_first: query } }, { _text_any: { inventor_name_last: query } }],\n }\n }\n }\n}\n"],"mappings":"4TAaA,MAAM,GAAiC,EAAW,IAA8B,CAC9E,IAAM,EAAS,EAAO,UAAU,EAAK,CACrC,OAAO,EAAO,QAAU,EAAO,KAAQ,GAiBnC,EAAwB,CAC5B,YACA,eACA,kBACA,cACA,cACA,YACA,YACD,CAEK,GACJ,EACA,EACA,IAC2B,CAC3B,IAAM,EAAiC,CAAE,EAAG,KAAK,UAAU,EAAE,CAAE,CAG/D,OAFI,IAAG,EAAO,EAAI,KAAK,UAAU,EAAE,EAC/B,IAAG,EAAO,EAAI,KAAK,UAAU,EAAE,EAC5B,GAGT,IAAa,EAAb,KAA+B,CAG7B,YAAY,EAAoC,QAF/B,SAAA,IAAA,GAAkB,CAGjC,IAAM,EAAU,GAAS,SAAW,yCAC9B,EAAkC,EAAE,CACtC,GAAS,SACX,EAAQ,aAAe,EAAQ,QAGjC,KAAK,OAAS,IAAI,EAAW,CAC3B,UACA,UACA,QAAS,GAAS,QACnB,CAAC,CAGJ,MAAM,cACJ,EACA,EAA+C,OAC/C,EAAQ,GACiB,CAEzB,IAAM,EAAS,EADL,KAAK,iBAAiB,EAAO,EAAW,CACpB,CAAC,GAAG,EAAsB,CAAE,CAAE,KAAM,EAAO,CAAC,CAE1E,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,UAAW,EAAO,CACf,CAGhD,MAAM,UAAU,EAA2C,CAEzD,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,UAAU,EAAS,GAAG,CACnB,CAGhD,MAAM,gBAAgB,EAAc,EAAQ,GAA+B,CACzE,IAAM,EAAS,EAAY,CAAE,UAAW,CAAE,sBAAuB,EAAM,CAAE,CAAE,IAAA,GAAW,CAAE,KAAM,EAAO,CAAC,CAEtG,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,YAAa,EAAO,CACf,CAGlD,MAAM,YAAY,EAAuC,CAEvD,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,YAAY,EAAG,GAAG,CACb,CAGlD,MAAM,gBAAgB,EAAc,EAAQ,GAA+B,CAIzE,IAAM,EAAS,EAHL,CACR,IAAK,CAAC,CAAE,UAAW,CAAE,oBAAqB,EAAM,CAAE,CAAE,CAAE,UAAW,CAAE,mBAAoB,EAAM,CAAE,CAAC,CACjG,CAC6B,IAAA,GAAW,CAAE,KAAM,EAAO,CAAC,CAEzD,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,YAAa,EAAO,CACf,CAGlD,MAAM,YAAY,EAAuC,CAEvD,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,YAAY,EAAG,GAAG,CACb,CAGlD,MAAM,gBAAgB,EAAc,EAAQ,GAA+B,CAIzE,IAAM,EAAS,EAHL,CACR,IAAK,CAAC,CAAE,UAAW,CAAE,sBAAuB,EAAM,CAAE,CAAE,CAAE,UAAW,CAAE,mBAAoB,EAAM,CAAE,CAAC,CACnG,CAC6B,IAAA,GAAW,CAAE,KAAM,EAAO,CAAC,CAEzD,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,mBAAoB,EAAO,CACtB,CAGlD,MAAM,YAAY,EAAuC,CAEvD,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,mBAAmB,EAAG,GAAG,CACpB,CAGlD,MAAM,UAAU,EAA0C,CACxD,IAAM,EAAS,EAAY,CAAE,IAAK,CAAE,UAAW,EAAU,CAAE,CAAC,CAE5D,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,WAAY,EAAO,CAChB,CAGhD,MAAM,eAAe,EAA2C,CAC9D,IAAM,EAAiC,CACrC,EAAG,KAAK,UAAU,CAAC,YAAa,eAAgB,kBAAkB,CAAC,CACpE,CAED,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,UAAU,EAAS,GAAI,EAAO,CAC3B,CAGhD,MAAM,YAAY,EAAiB,EAAQ,GAA6B,CACtE,IAAM,EAAS,EAAY,CAAE,IAAK,CAAE,gBAAiB,EAAS,CAAE,CAAE,CAAC,GAAG,EAAsB,CAAE,CAAE,KAAM,EAAO,CAAC,CAE9G,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,UAAW,EAAO,CACf,CAGhD,MAAM,UAAU,EAA+C,CAC7D,IAAM,EAAS,EAAY,CAAE,IAAK,CAAE,gBAAiB,EAAS,CAAE,CAAC,CAEjE,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,gBAAiB,EAAO,CAChB,CAGrD,MAAM,YAAY,EAAiB,EAAQ,GAA6B,CACtE,IAAM,EAAS,EAAY,CAAE,IAAK,CAAE,UAAW,EAAS,CAAE,CAAE,CAAC,GAAG,EAAsB,CAAE,CAAE,KAAM,EAAO,CAAC,CAExG,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,UAAW,EAAO,CACf,CAGhD,MAAM,UAAU,EAAuC,CACrD,IAAM,EAAS,EAAY,CAAE,IAAK,CAAE,UAAW,EAAS,CAAE,CAAC,CAE3D,OAAO,EAAW,EADN,MAAM,KAAK,OAAO,IAAa,OAAQ,EAAO,CACD,CAG3D,iBAAyB,EAAe,EAAuE,CAC7G,OAAQ,EAAR,CACE,IAAK,OACH,MAAO,CAAE,UAAW,CAAE,gBAAiB,EAAO,CAAE,CAClD,IAAK,WACH,MAAO,CAAE,UAAW,CAAE,sBAAuB,EAAO,CAAE,CACxD,IAAK,WACH,MAAO,CACL,IAAK,CAAC,CAAE,UAAW,CAAE,oBAAqB,EAAO,CAAE,CAAE,CAAE,UAAW,CAAE,mBAAoB,EAAO,CAAE,CAAC,CACnG"}
|