@radsoft/markbase 2026.10.2 → 2026.11.2
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/README.md +19 -1
- package/dist/client.d.ts +5 -6
- package/dist/client.js +17 -7
- package/dist/types.d.ts +39 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -157,12 +157,23 @@ Keep the key server-side. It's a secret; don't ship it to the browser.
|
|
|
157
157
|
|
|
158
158
|
---
|
|
159
159
|
|
|
160
|
+
## Unreleased: opt-in phonetic clearance
|
|
161
|
+
|
|
162
|
+
The source client accepts an optional `phonetic` boolean in `clearance` and
|
|
163
|
+
`clearanceBatch` options. The API mode is not enabled in production yet; client
|
|
164
|
+
support alone does not make it available. Omit the option for current spelling-only
|
|
165
|
+
behavior. An unavailable opt-in request returns 503, and batches are never retried
|
|
166
|
+
automatically. See the [unreleased contract](../docs/phonetic-clearance.md) for
|
|
167
|
+
response evidence, ranking, and input limits. Existing spelling scores and risk
|
|
168
|
+
thresholds remain unchanged; phonetic evidence is not a legal availability decision.
|
|
169
|
+
|
|
160
170
|
## Reference
|
|
161
171
|
|
|
162
172
|
| Method | Returns |
|
|
163
173
|
|---|---|
|
|
164
174
|
| `search(opts \| string)` | `SearchResult` — typo-tolerant full-text search |
|
|
165
175
|
| `clearance(mark, opts?)` | `ClearanceResult` — ranked conflicts with a risk level |
|
|
176
|
+
| `clearanceBatch(marks, opts?)` | `ClearanceBatchResult` — 1–25 names in input order (**Launch or Scale**) |
|
|
166
177
|
| `suggest(q, limit?)` | `Suggestion[]` — autocomplete, tuned for as-you-type |
|
|
167
178
|
| `getTrademark(serial)` | `Trademark` — one full record |
|
|
168
179
|
| `getTimeline(serial)` | prosecution history |
|
|
@@ -245,7 +256,14 @@ try {
|
|
|
245
256
|
## Rate limits and quota
|
|
246
257
|
|
|
247
258
|
Per-minute limits and 5xx are **retried automatically** with backoff
|
|
248
|
-
(`maxRetries`, default 2)
|
|
259
|
+
(`maxRetries`, default 2), except for `clearanceBatch()`.
|
|
260
|
+
|
|
261
|
+
Bulk clearance accepts 1–25 names, each up to 200 characters, with an optional
|
|
262
|
+
shared `trademarkClass` and `limit` of 1–50 matches per name (default 20). Every
|
|
263
|
+
submitted name counts toward monthly and per-minute limits, including duplicates.
|
|
264
|
+
A batch that exceeds the remaining monthly quota is rejected in full. Accepted
|
|
265
|
+
batches consume their full name count even if a search fails. The SDK never
|
|
266
|
+
automatically retries bulk requests because that could charge the names again.
|
|
249
267
|
|
|
250
268
|
Monthly quota exhaustion is **not retried** — waiting a few seconds can't fix a
|
|
251
269
|
month-long window, so it throws immediately with `resetsAt` rather than burning
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Trademark, SearchOptions, SearchResult, Suggestion, ClearanceResult, OwnerResult, BatchResult, AggregateField, AggregateResult, NiceClass, IndexInfo, RateLimitInfo, MarkStatus } from "./types.js";
|
|
1
|
+
import type { Trademark, SearchOptions, SearchResult, Suggestion, ClearanceOptions, ClearanceResult, ClearanceBatchResult, OwnerResult, BatchResult, AggregateField, AggregateResult, NiceClass, IndexInfo, RateLimitInfo, MarkStatus } from "./types.js";
|
|
2
2
|
export interface MarkbaseOptions {
|
|
3
3
|
/**
|
|
4
4
|
* Get one free at https://markbase.co. Omitted falls back to
|
|
@@ -46,14 +46,13 @@ export declare class Markbase {
|
|
|
46
46
|
limit?: number;
|
|
47
47
|
}): Promise<OwnerResult>;
|
|
48
48
|
/**
|
|
49
|
-
* Screen a proposed name against the register
|
|
49
|
+
* Screen a proposed name against the register. Spelling-only matching is the default.
|
|
50
50
|
* A first-pass signal, not legal advice — pass a class, since trademark
|
|
51
51
|
* rights are scoped to goods and services.
|
|
52
52
|
*/
|
|
53
|
-
clearance(mark: string, opts?:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}): Promise<ClearanceResult>;
|
|
53
|
+
clearance(mark: string, opts?: ClearanceOptions): Promise<ClearanceResult>;
|
|
54
|
+
/** Screen 1–25 names on Launch or Scale. Each name consumes quota; retries are disabled. */
|
|
55
|
+
clearanceBatch(marks: string[], opts?: ClearanceOptions): Promise<ClearanceBatchResult>;
|
|
57
56
|
/** Distribution counts across a facet. */
|
|
58
57
|
aggregate(by: AggregateField): Promise<AggregateResult>;
|
|
59
58
|
/** All 45 Nice classification classes. */
|
package/dist/client.js
CHANGED
|
@@ -68,8 +68,9 @@ export class Markbase {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
async request(path, init) {
|
|
71
|
+
const { query, retry, ...requestInit } = init ?? {};
|
|
71
72
|
const url = new URL(this.baseUrl + path);
|
|
72
|
-
for (const [k, v] of Object.entries(
|
|
73
|
+
for (const [k, v] of Object.entries(query ?? {})) {
|
|
73
74
|
if (v == null)
|
|
74
75
|
continue;
|
|
75
76
|
if (Array.isArray(v))
|
|
@@ -77,13 +78,14 @@ export class Markbase {
|
|
|
77
78
|
else
|
|
78
79
|
url.searchParams.set(k, String(v));
|
|
79
80
|
}
|
|
81
|
+
const maxRetries = retry === false ? 0 : this.maxRetries;
|
|
80
82
|
let lastErr;
|
|
81
|
-
for (let attempt = 0; attempt <=
|
|
83
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
82
84
|
const ctrl = new AbortController();
|
|
83
85
|
const timer = setTimeout(() => ctrl.abort(), this.timeout);
|
|
84
86
|
try {
|
|
85
87
|
const res = await this.fetchImpl(url, {
|
|
86
|
-
...
|
|
88
|
+
...requestInit,
|
|
87
89
|
signal: ctrl.signal,
|
|
88
90
|
headers: {
|
|
89
91
|
accept: "application/json",
|
|
@@ -111,13 +113,13 @@ export class Markbase {
|
|
|
111
113
|
// per-minute limit is worth retrying
|
|
112
114
|
const retryAfterMs = isQuota ? null : 1000 * (attempt + 1) * 2;
|
|
113
115
|
const err = new RateLimitError(message, isQuota ? "quota" : "rate", retryAfterMs, resetsAt, body);
|
|
114
|
-
if (isQuota || attempt >=
|
|
116
|
+
if (isQuota || attempt >= maxRetries)
|
|
115
117
|
throw err;
|
|
116
118
|
lastErr = err;
|
|
117
119
|
await sleep(retryAfterMs);
|
|
118
120
|
continue;
|
|
119
121
|
}
|
|
120
|
-
if (res.status >= 500 && attempt <
|
|
122
|
+
if (res.status >= 500 && attempt < maxRetries) {
|
|
121
123
|
lastErr = new MarkbaseError(message, res.status, body);
|
|
122
124
|
await sleep(1000 * (attempt + 1));
|
|
123
125
|
continue;
|
|
@@ -129,7 +131,7 @@ export class Markbase {
|
|
|
129
131
|
throw err;
|
|
130
132
|
// network error or timeout — worth one more go
|
|
131
133
|
lastErr = err;
|
|
132
|
-
if (attempt >=
|
|
134
|
+
if (attempt >= maxRetries) {
|
|
133
135
|
const msg = err?.name === "AbortError" ? `Request timed out after ${this.timeout}ms` : String(err);
|
|
134
136
|
throw new MarkbaseError(msg, 0);
|
|
135
137
|
}
|
|
@@ -186,7 +188,7 @@ export class Markbase {
|
|
|
186
188
|
return this.request("/owner", { query: { name, ...opts } });
|
|
187
189
|
}
|
|
188
190
|
/**
|
|
189
|
-
* Screen a proposed name against the register
|
|
191
|
+
* Screen a proposed name against the register. Spelling-only matching is the default.
|
|
190
192
|
* A first-pass signal, not legal advice — pass a class, since trademark
|
|
191
193
|
* rights are scoped to goods and services.
|
|
192
194
|
*/
|
|
@@ -196,9 +198,17 @@ export class Markbase {
|
|
|
196
198
|
mark,
|
|
197
199
|
class: opts.trademarkClass == null ? undefined : padClass(opts.trademarkClass),
|
|
198
200
|
limit: opts.limit,
|
|
201
|
+
phonetic: opts.phonetic,
|
|
199
202
|
},
|
|
200
203
|
});
|
|
201
204
|
}
|
|
205
|
+
/** Screen 1–25 names on Launch or Scale. Each name consumes quota; retries are disabled. */
|
|
206
|
+
clearanceBatch(marks, opts = {}) {
|
|
207
|
+
return this.request("/clearance/batch", {
|
|
208
|
+
method: "POST", retry: false,
|
|
209
|
+
body: JSON.stringify({ marks, class: opts.trademarkClass == null ? undefined : padClass(opts.trademarkClass), limit: opts.limit, phonetic: opts.phonetic }),
|
|
210
|
+
});
|
|
211
|
+
}
|
|
202
212
|
/** Distribution counts across a facet. */
|
|
203
213
|
aggregate(by) {
|
|
204
214
|
return this.request("/aggregate", { query: { by } });
|
package/dist/types.d.ts
CHANGED
|
@@ -52,16 +52,54 @@ export interface Suggestion {
|
|
|
52
52
|
owner_name: string | null;
|
|
53
53
|
status_code: string | null;
|
|
54
54
|
}
|
|
55
|
+
export interface ClearanceOptions {
|
|
56
|
+
trademarkClass?: string | number;
|
|
57
|
+
limit?: number;
|
|
58
|
+
/** Unreleased opt-in; unavailable mode returns 503. Omit for spelling-only matching. */
|
|
59
|
+
phonetic?: boolean;
|
|
60
|
+
}
|
|
61
|
+
export interface ClearanceMatching {
|
|
62
|
+
mode: "spelling_and_phonetic";
|
|
63
|
+
algorithm: "double_metaphone_v1";
|
|
64
|
+
ranking: "phonetic_v1";
|
|
65
|
+
phonetic_status: "evaluated" | "not_evaluated";
|
|
66
|
+
truncated: boolean;
|
|
67
|
+
}
|
|
68
|
+
export interface ClearanceSignals {
|
|
69
|
+
exact: boolean;
|
|
70
|
+
spelling: {
|
|
71
|
+
score: number;
|
|
72
|
+
};
|
|
73
|
+
phonetic: {
|
|
74
|
+
algorithm: "double_metaphone_v1";
|
|
75
|
+
status: "matched" | "not_matched" | "not_evaluated";
|
|
76
|
+
scope?: "whole_name";
|
|
77
|
+
tokens?: Array<{
|
|
78
|
+
query: string;
|
|
79
|
+
candidate: string;
|
|
80
|
+
variant: "primary" | "alternate";
|
|
81
|
+
}>;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
55
84
|
export interface ClearanceMatch extends Pick<Trademark, "serial_number" | "word_mark" | "owner_name" | "status_code" | "international_codes"> {
|
|
56
|
-
/** 0-1
|
|
85
|
+
/** 0-1 spelling score; phonetic evidence does not change this value. */
|
|
57
86
|
similarity: number;
|
|
58
87
|
risk: RiskLevel;
|
|
88
|
+
signals?: ClearanceSignals;
|
|
59
89
|
}
|
|
60
90
|
export interface ClearanceResult {
|
|
61
91
|
mark: string;
|
|
62
92
|
class: string | null;
|
|
93
|
+
/** Maximum spelling-based risk among retrieved candidates before the result limit. */
|
|
63
94
|
highest_risk: RiskLevel;
|
|
64
95
|
matches: ClearanceMatch[];
|
|
96
|
+
matching?: ClearanceMatching;
|
|
97
|
+
}
|
|
98
|
+
export interface ClearanceBatchResult {
|
|
99
|
+
results: ClearanceResult[];
|
|
100
|
+
usage: {
|
|
101
|
+
names: number;
|
|
102
|
+
};
|
|
65
103
|
}
|
|
66
104
|
export interface OwnerResult {
|
|
67
105
|
owner: string;
|
package/package.json
CHANGED