@nxisai/nxis 2.1.1

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/build/api.d.ts ADDED
@@ -0,0 +1,244 @@
1
+ /**
2
+ * A URL object representing an HTTP or HTTPS URI.
3
+ *
4
+ * @remarks
5
+ * Used as the canonical type for page URIs throughout the client-side request path.
6
+ */
7
+ export type HttpUri = URL;
8
+ /**
9
+ * A wrapper around an optional string identifier.
10
+ *
11
+ * @remarks
12
+ * Used to represent entity IDs (organization, site, resource, etc.) that may
13
+ * or may not be present in a given context.
14
+ */
15
+ export type Uid = {
16
+ /** The string identifier value, or `null` if not set. */
17
+ value: string | null;
18
+ };
19
+ /**
20
+ * Makes a type `T` nullable — allowing `null` or `undefined` in addition to `T`.
21
+ */
22
+ export type Nullable<T> = T | null | undefined;
23
+ /**
24
+ * Configuration injected by the Nxis CDN into the browser script.
25
+ *
26
+ * @remarks
27
+ * The CDN extracts these values from the JWT token's claims and writes them
28
+ * into `window.__NXIS_CONFIG__` before the client script executes.
29
+ */
30
+ export type NxisConfig = {
31
+ /** The organization identifier. */
32
+ org_id: string;
33
+ /** The site identifier within the organization. */
34
+ site_id: string;
35
+ /** The subscription identifier used for quota and entitlement checks. */
36
+ sub_id: string;
37
+ };
38
+ /**
39
+ * Parameters for a client-side structured data request sent to the
40
+ * `/v1/nxis:inject` endpoint.
41
+ */
42
+ export type StructuredDataRequest = {
43
+ /** The organization that owns the site. */
44
+ organization_id: Nullable<Uid>;
45
+ /** The site the page belongs to. */
46
+ site_id: Nullable<Uid>;
47
+ /** The full URI of the page being enhanced. */
48
+ uri: HttpUri;
49
+ /** The `document.referrer` value, if available. */
50
+ referrer?: string;
51
+ /** A client-generated session ID for request correlation. */
52
+ session?: string;
53
+ };
54
+ /**
55
+ * The response body returned by both the `/v1/nxis:inject` and `/v1/nxis:ssr`
56
+ * endpoints on success.
57
+ *
58
+ * @remarks
59
+ * The `data` field corresponds to a `google.protobuf.Struct` in the proto
60
+ * definition, which serializes as a flat JSON object over HTTP transcoding.
61
+ */
62
+ export type StructuredDataResponse = {
63
+ /** A JSON-LD structured data object ready for injection into the page. */
64
+ data: Record<string, unknown>;
65
+ };
66
+ /**
67
+ * A non-fatal warning indicating no structured data was found for a page.
68
+ *
69
+ * @remarks
70
+ * Thrown when the proxy returns a 200 response with an empty `data` object.
71
+ * Callers can catch this specifically to distinguish "no data" from actual errors.
72
+ */
73
+ export declare class NxisWarning extends Error {
74
+ constructor(msg: string);
75
+ }
76
+ /**
77
+ * Configuration for initializing a {@link NxisClient} instance.
78
+ *
79
+ * @remarks
80
+ * Used to create a client that automatically manages OAuth tokens and
81
+ * fetches structured data from the Nxis AI Proxy.
82
+ *
83
+ * @example
84
+ * ```typescript
85
+ * const nxis = new NxisClient({
86
+ * clientId: process.env.NXIS_CLIENT_ID!,
87
+ * clientSecret: process.env.NXIS_CLIENT_SECRET!,
88
+ * });
89
+ * ```
90
+ */
91
+ export type NxisClientConfig = {
92
+ /** OAuth client ID (format: `nxis_cid_[a-zA-Z0-9]{16}`). */
93
+ clientId: string;
94
+ /** OAuth client secret (format: `nxis_sec_[a-zA-Z0-9]{32}`). */
95
+ clientSecret: string;
96
+ /**
97
+ * Override for the OAuth token endpoint URL.
98
+ *
99
+ * @defaultValue Falls back to `NXIS_TOKEN_URL` env var, then `"https://authorization.nxis.ai/v1/oauth/token"`.
100
+ */
101
+ tokenUrl?: string;
102
+ /**
103
+ * OAuth scope to request.
104
+ *
105
+ * @defaultValue `"jsonld:read"`
106
+ */
107
+ scope?: string;
108
+ /**
109
+ * Override for the Nxis API host URL.
110
+ *
111
+ * @defaultValue Falls back to the `NXIS_API_HOST` environment variable.
112
+ */
113
+ apiHost?: string;
114
+ };
115
+ /**
116
+ * Request parameters for fetching structured data for a specific page.
117
+ *
118
+ * @remarks
119
+ * Passed to {@link NxisClient.getStructuredData}. Contains only
120
+ * request-specific parameters — credentials and host config are
121
+ * set once at client initialization.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const jsonLd = await nxis.getStructuredData({
126
+ * uri: 'https://example.com/page',
127
+ * userAgent: req.headers['user-agent'],
128
+ * });
129
+ * ```
130
+ */
131
+ export type NxisSSRRequest = {
132
+ /** The full URI of the page being rendered (e.g. `"https://example.com/about"`). */
133
+ uri: string;
134
+ /** The site identifier to scope the request to a specific site. */
135
+ siteId: string;
136
+ /**
137
+ * Optional User-Agent string forwarded to the proxy for bot detection.
138
+ *
139
+ * @remarks
140
+ * When provided, the proxy can distinguish search-engine crawlers and LLM
141
+ * agents from regular visitors and adjust response behavior accordingly.
142
+ */
143
+ userAgent?: string;
144
+ };
145
+ /**
146
+ * gRPC-compatible error codes used by the Nxis AI Proxy.
147
+ *
148
+ * @remarks
149
+ * These codes map directly to gRPC status codes and are included in
150
+ * structured error responses from the proxy. Use {@link errorCodeToHttp}
151
+ * to convert to the corresponding HTTP status code.
152
+ */
153
+ export declare enum ErrorCode {
154
+ /** The request completed successfully. */
155
+ OK = 0,
156
+ /** The request contained an invalid argument (e.g. malformed URI). */
157
+ INVALID_ARGUMENT = 3,
158
+ /** The requested resource was not found. */
159
+ NOT_FOUND = 5,
160
+ /** The caller does not have permission to access the requested resource. */
161
+ PERMISSION_DENIED = 7,
162
+ /** The caller has exceeded their rate limit or quota. */
163
+ RESOURCE_EXHAUSTED = 8,
164
+ /** An internal server error occurred. */
165
+ INTERNAL = 13,
166
+ /** The request lacks valid authentication credentials. */
167
+ UNAUTHENTICATED = 16
168
+ }
169
+ /**
170
+ * Maps each {@link ErrorCode} to its conventional HTTP status code.
171
+ *
172
+ * @example
173
+ * ```typescript
174
+ * const httpStatus = errorCodeToHttp[ErrorCode.NOT_FOUND]; // 404
175
+ * ```
176
+ */
177
+ export declare const errorCodeToHttp: Record<ErrorCode, number>;
178
+ /**
179
+ * The structured JSON body returned by the proxy on error responses.
180
+ */
181
+ export interface NxisErrorResponse {
182
+ /** The gRPC-style error code. */
183
+ code: ErrorCode;
184
+ /** A human-readable error message. */
185
+ message: string;
186
+ /** Optional array of protobuf `Any`-style detail messages. */
187
+ details?: Array<{
188
+ "@type": string;
189
+ value: string;
190
+ }>;
191
+ }
192
+ /**
193
+ * An error thrown when the Nxis AI Proxy returns a non-200 response.
194
+ *
195
+ * @remarks
196
+ * `ProxyError` carries both the gRPC {@link ErrorCode} and the HTTP status
197
+ * code so callers can decide how to surface or retry the failure.
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * try {
202
+ * const data = await getStructuredData({ token, uri });
203
+ * } catch (err) {
204
+ * if (err instanceof ProxyError && err.isRetryable) {
205
+ * // back off and retry
206
+ * }
207
+ * }
208
+ * ```
209
+ */
210
+ export declare class ProxyError extends Error {
211
+ readonly code: ErrorCode;
212
+ readonly httpStatus: number;
213
+ /**
214
+ * @param code - The gRPC-style {@link ErrorCode}.
215
+ * @param httpStatus - The HTTP status code from the proxy response.
216
+ * @param message - A human-readable description of the error.
217
+ */
218
+ constructor(code: ErrorCode, httpStatus: number, message: string);
219
+ /**
220
+ * Whether this error represents a transient failure that may succeed on retry.
221
+ *
222
+ * @remarks
223
+ * Returns `true` for {@link ErrorCode.RESOURCE_EXHAUSTED} (rate limiting)
224
+ * and {@link ErrorCode.INTERNAL} (server errors).
225
+ */
226
+ get isRetryable(): boolean;
227
+ /**
228
+ * Whether this error indicates an authentication or authorization failure.
229
+ *
230
+ * @remarks
231
+ * Returns `true` for {@link ErrorCode.UNAUTHENTICATED} (missing/invalid token)
232
+ * and {@link ErrorCode.PERMISSION_DENIED} (valid token, insufficient access).
233
+ */
234
+ get isAuthError(): boolean;
235
+ /**
236
+ * Creates a `ProxyError` from an HTTP status code and a parsed
237
+ * {@link NxisErrorResponse} body.
238
+ *
239
+ * @param status - The HTTP status code of the response.
240
+ * @param body - The parsed error response body from the proxy.
241
+ * @returns A new `ProxyError` instance.
242
+ */
243
+ static fromResponse(status: number, body: NxisErrorResponse): ProxyError;
244
+ }
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Configuration for the OAuth client credentials flow.
3
+ *
4
+ * @internal
5
+ */
6
+ export interface OAuthConfig {
7
+ /** OAuth client ID (format: `nxis_cid_[a-zA-Z0-9]{16}`). */
8
+ clientId: string;
9
+ /** OAuth client secret (format: `nxis_sec_[a-zA-Z0-9]{32}`). */
10
+ clientSecret: string;
11
+ /**
12
+ * The OAuth token endpoint URL.
13
+ *
14
+ * @defaultValue Falls back to `NXIS_TOKEN_URL` env var, then `"https://authorization.nxis.ai/v1/oauth/token"`.
15
+ */
16
+ tokenUrl?: string;
17
+ /**
18
+ * OAuth scope to request.
19
+ *
20
+ * @defaultValue `"jsonld:read"`
21
+ */
22
+ scope?: string;
23
+ }
24
+ /**
25
+ * Response from the OAuth token endpoint (`POST /v1/oauth/token`).
26
+ *
27
+ * @remarks
28
+ * Matches the `IssueTokenResponse` message in the OAuth service proto.
29
+ */
30
+ export interface IssueTokenResponse {
31
+ /** The issued access token. */
32
+ access_token: string;
33
+ /** Token type — always `"Bearer"`. */
34
+ token_type: string;
35
+ /** Seconds until the token expires. */
36
+ expires_in: number;
37
+ /** The granted scope. */
38
+ scope: string;
39
+ }
40
+ /**
41
+ * Manages OAuth 2.0 access tokens using the client credentials grant.
42
+ *
43
+ * @remarks
44
+ * Tokens are cached in memory and automatically refreshed before expiration.
45
+ * Concurrent calls during a refresh all await the same in-flight request,
46
+ * preventing redundant token fetches.
47
+ *
48
+ * @example
49
+ * ```typescript
50
+ * const manager = new OAuthTokenManager({
51
+ * clientId: process.env.NXIS_CLIENT_ID!,
52
+ * clientSecret: process.env.NXIS_CLIENT_SECRET!,
53
+ * });
54
+ *
55
+ * const token = await manager.getAccessToken();
56
+ * // Use token in Authorization: Bearer <token> header
57
+ * ```
58
+ */
59
+ export declare class OAuthTokenManager {
60
+ private readonly clientId;
61
+ private readonly clientSecret;
62
+ private readonly tokenUrl;
63
+ private readonly scope;
64
+ /** The currently cached access token, or `null` if none. */
65
+ private cachedToken;
66
+ /** Unix timestamp (ms) at which the cached token expires. */
67
+ private expiresAt;
68
+ /** In-flight token request for concurrency deduplication. */
69
+ private pendingRequest;
70
+ constructor(config: OAuthConfig);
71
+ /**
72
+ * Returns a valid access token, fetching or refreshing as needed.
73
+ *
74
+ * @remarks
75
+ * If the cached token has more than {@link REFRESH_BUFFER_SECONDS} seconds
76
+ * remaining, it is returned immediately. Otherwise a new token is requested
77
+ * from the OAuth endpoint.
78
+ *
79
+ * @returns A valid OAuth Bearer access token.
80
+ *
81
+ * @throws {@link ProxyError}
82
+ * Thrown if the token endpoint returns an error response.
83
+ */
84
+ getAccessToken(): Promise<string>;
85
+ /**
86
+ * Fetches a new access token from the OAuth endpoint.
87
+ *
88
+ * @internal
89
+ */
90
+ private fetchToken;
91
+ }
@@ -0,0 +1,56 @@
1
+ import { StructuredDataRequest, StructuredDataResponse } from './api';
2
+ /**
3
+ * Serializes a {@link StructuredDataRequest} into URL query parameters for
4
+ * the client-side `/v1/nxis:inject` endpoint.
5
+ *
6
+ * @param request - The structured data request containing org, site, URI,
7
+ * referrer, and session info.
8
+ * @returns A `URLSearchParams` instance ready to be appended to the request URL.
9
+ *
10
+ * @internal
11
+ */
12
+ export declare function buildParams(request: StructuredDataRequest): URLSearchParams;
13
+ /**
14
+ * Processes an HTTP response from the Nxis API and returns the structured
15
+ * data payload, or throws an appropriate error.
16
+ *
17
+ * @remarks
18
+ * - On a `200` response with data, returns the {@link StructuredDataResponse}.
19
+ * - On a `200` response with an empty `data` object, throws {@link NxisWarning}.
20
+ * - On error responses, attempts to parse a structured {@link NxisErrorResponse}
21
+ * and throws a {@link ProxyError}. Falls back to generic status-based errors
22
+ * if the body cannot be parsed.
23
+ *
24
+ * @param response - The raw `fetch` Response from the proxy.
25
+ * @param pageUrl - The page URL for use in error messages. Defaults to `"unknown"`.
26
+ * @returns The parsed structured data response.
27
+ *
28
+ * @throws {@link NxisWarning}
29
+ * Thrown when the proxy returns 200 but the data object is empty.
30
+ *
31
+ * @throws {@link ProxyError}
32
+ * Thrown when the proxy returns a non-200 status code.
33
+ */
34
+ export declare function responseHandler(response: Response, pageUrl?: string): Promise<StructuredDataResponse>;
35
+ /**
36
+ * Fetches structured data from the Nxis AI Proxy's SSR endpoint (`/v1/nxis:ssr`).
37
+ *
38
+ * @remarks
39
+ * This is the low-level fetch function used by {@link NxisClient}. It sends
40
+ * the request with a `Bearer` access token obtained from the OAuth token manager.
41
+ *
42
+ * @param uri - The full URI of the page being rendered.
43
+ * @param accessToken - A valid OAuth Bearer access token.
44
+ * @param apiHost - The Nxis API host URL.
45
+ * @param userAgent - Optional User-Agent string for bot detection.
46
+ * @returns The full {@link StructuredDataResponse} from the proxy.
47
+ *
48
+ * @throws {@link ProxyError}
49
+ * Thrown if the proxy returns a non-200 response.
50
+ *
51
+ * @throws {@link NxisWarning}
52
+ * Thrown if the proxy returns 200 but no data is available for the page.
53
+ *
54
+ * @internal
55
+ */
56
+ export declare function fetchStructuredData(uri: string, accessToken: string, apiHost: string, userAgent?: string, siteId?: string): Promise<StructuredDataResponse>;