@elmohq/sdk 0.1.0 → 0.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.
Files changed (38) hide show
  1. package/README.md +18 -17
  2. package/dist/calls/index.d.mts +1 -1
  3. package/dist/calls/index.mjs +1 -1
  4. package/dist/index.d.mts +1 -1
  5. package/dist/index.mjs +52 -50
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/{request-options-DWYI_Ldj.d.mts → request-options-B9S9d24M.d.mts} +70 -71
  8. package/dist/request-options-B9S9d24M.d.mts.map +1 -0
  9. package/dist/{tools-SwP0sK8H.mjs → tools-B1lVtYAr.mjs} +10 -9
  10. package/dist/tools-B1lVtYAr.mjs.map +1 -0
  11. package/package.json +2 -1
  12. package/src/calls/brands-list.ts +1 -1
  13. package/src/calls/competitors-list.ts +1 -1
  14. package/src/calls/organizations-list.ts +1 -1
  15. package/src/calls/prompts-list.ts +1 -1
  16. package/src/calls/prompts-runs-list.ts +1 -1
  17. package/src/calls/reports-list.ts +1 -1
  18. package/src/client.ts +7 -20
  19. package/src/internal/core/dispatch.ts +2 -4
  20. package/src/internal/core/errors.ts +5 -5
  21. package/src/internal/{page → core}/page.ts +5 -5
  22. package/src/internal/core/types.ts +6 -8
  23. package/src/internal/feature/logger.ts +2 -2
  24. package/src/internal/feature/retry.ts +53 -50
  25. package/src/internal/feature/timeout.ts +2 -2
  26. package/src/internal/feature/validate.ts +8 -0
  27. package/src/resources/analytics.ts +8 -7
  28. package/src/resources/brands.ts +7 -4
  29. package/src/resources/competitors.ts +4 -3
  30. package/src/resources/identity.ts +2 -1
  31. package/src/resources/opportunities.ts +3 -1
  32. package/src/resources/organizations.ts +6 -5
  33. package/src/resources/prompts.ts +3 -2
  34. package/src/resources/reports.ts +3 -2
  35. package/src/resources/runs.ts +5 -4
  36. package/src/resources/tools.ts +1 -0
  37. package/dist/request-options-DWYI_Ldj.d.mts.map +0 -1
  38. package/dist/tools-SwP0sK8H.mjs.map +0 -1
@@ -3,7 +3,7 @@ import { mergeConfigs } from './config';
3
3
  import { applyAliases, applyCredentials } from './credentials';
4
4
  import {
5
5
  ElmoError,
6
- requestIdOf,
6
+ sniffRequestId,
7
7
  unansweredError,
8
8
  unsendableHeader,
9
9
  UnsupportedInteractionError,
@@ -70,8 +70,6 @@ async function readReply(
70
70
 
71
71
  result = await runner.result(result, request, ctx);
72
72
 
73
- if (request.options.unread) return result.response;
74
-
75
73
  const failure = binding.readError?.(result, request) ?? result.error;
76
74
 
77
75
  if (request.options.raw) {
@@ -221,7 +219,7 @@ export async function exchange(
221
219
  let read: Promise<unknown> | undefined;
222
220
  return {
223
221
  read: (from) => (read ??= readReply(setup, sent, request, from)),
224
- requestId: () => sent.result.response && requestIdOf(sent.result.response),
222
+ requestId: () => sent.result.response && sniffRequestId(sent.result.response),
225
223
  response: sent.result.response,
226
224
  };
227
225
  }
@@ -41,7 +41,7 @@ export class AbortError extends ElmoError {
41
41
  }
42
42
  }
43
43
 
44
- /** Which way a {@link TransportError} failed. `connect` and `other` have no class of their own. */
44
+ /** Which way a {@link TransportError} failed. */
45
45
  export type TransportErrorKind = 'connect' | 'other' | 'timeout';
46
46
 
47
47
  const TRANSPORT_MESSAGES: Readonly<Record<TransportErrorKind, string>> = {
@@ -224,7 +224,7 @@ function shorten(text: string): string {
224
224
  const cut = line.slice(0, MAX_MESSAGE_BODY);
225
225
  const space = cut.lastIndexOf(' ');
226
226
  const kept = space > MAX_MESSAGE_BODY / 2 ? cut.slice(0, space) : cut;
227
- return `${kept.trimEnd()}…`;
227
+ return `${kept.trimEnd()}...`;
228
228
  }
229
229
 
230
230
  const MESSAGE_KEYS: ReadonlyArray<string> = [
@@ -272,7 +272,7 @@ const REQUEST_ID_FALLBACKS: ReadonlyArray<string> = ['x-correlation-id', 'cf-ray
272
272
 
273
273
  const REQUEST_ID_NAME = /(?:^|-)request-?id$/;
274
274
 
275
- export function requestIdOf(response: Response): string | undefined {
275
+ export function sniffRequestId(response: Response): string | undefined {
276
276
  let named: string | undefined;
277
277
  response.headers.forEach((value, name) => {
278
278
  if (!named && value && REQUEST_ID_NAME.test(name)) named = value;
@@ -313,7 +313,7 @@ export class APIError<TBody = FailureBody> extends ElmoError {
313
313
 
314
314
  constructor(status: number, body: unknown, response: Response, note?: string) {
315
315
  const reason = response.statusText ? `${status} ${response.statusText}` : `${status}`;
316
- const requestId = requestIdOf(response);
316
+ const requestId = sniffRequestId(response);
317
317
  const url = response.url ? ` for "${safeAddress(response.url)}"` : '';
318
318
  const where = requestId ? `${url} (request id "${requestId}")` : url;
319
319
  const said = describeStatedFailure(body);
@@ -385,7 +385,7 @@ export class DecodeError extends ElmoError {
385
385
  value?: unknown;
386
386
  } = {},
387
387
  ) {
388
- const requestId = options.response && requestIdOf(options.response);
388
+ const requestId = options.response && sniffRequestId(options.response);
389
389
  super(requestId ? `${message} The request id is "${requestId}".` : message, {
390
390
  cause: options.cause,
391
391
  });
@@ -1,7 +1,7 @@
1
- import { awaitedResult } from '../core/call-promise';
2
- import type { Client } from '../core/client';
3
- import { APIError, ElmoError } from '../core/errors';
4
- import { LazyPromise, unattended } from '../core/lazy-promise';
1
+ import { awaitedResult } from './call-promise';
2
+ import type { Client } from './client';
3
+ import { APIError, ElmoError } from './errors';
4
+ import { LazyPromise, unattended } from './lazy-promise';
5
5
  import type {
6
6
  CallableDescriptor,
7
7
  ErrorMode,
@@ -11,7 +11,7 @@ import type {
11
11
  PaginationStyle,
12
12
  ResolvedOptions,
13
13
  Result,
14
- } from '../core/types';
14
+ } from './types';
15
15
 
16
16
  /**
17
17
  * One page of a paginated call. Iterating a page walks from it to the end of
@@ -110,7 +110,7 @@ export interface RetryRules extends BackoffOptions {
110
110
  */
111
111
  maxRetryAfter?: number;
112
112
  /**
113
- * Methods that may be sent again. A failure that never reached the server,
113
+ * Methods that may be sent again. A request that never reached the API,
114
114
  * a call carrying its API's idempotency key, and 408, 425 and 429 are sent
115
115
  * again whatever this says.
116
116
  *
@@ -132,8 +132,9 @@ export interface RetryRules extends BackoffOptions {
132
132
  */
133
133
  retryOnTimeout?: boolean;
134
134
  /**
135
- * Statuses worth another attempt. A reply with `x-should-retry: false` is
136
- * never retried.
135
+ * Statuses worth another attempt. The API overrules them with
136
+ * `x-should-retry`: a reply answering `false` is never retried, and a
137
+ * failure answering `true` is, whatever its status and method.
137
138
  */
138
139
  statuses?: ReadonlyArray<number>;
139
140
  }
@@ -162,8 +163,7 @@ export interface CallableDescriptor {
162
163
  readonly method?: string;
163
164
  readonly pagination?: PaginationDescriptor;
164
165
  readonly retry?: RetryRules | false;
165
- /** `'json'` where every success is declared as a JSON object or list. */
166
- readonly returns?: 'json';
166
+ readonly returns?: 'json' | 'response';
167
167
  readonly rules?: ReadonlyArray<InputRule>;
168
168
  readonly serialization?: SerializationDescriptor;
169
169
  readonly timeout?: CallTimeout;
@@ -317,13 +317,12 @@ export interface PreparedRequest<TAddress = unknown> {
317
317
  /** Each credential put on the request, with the scheme it answers. */
318
318
  placed?: ReadonlyArray<PlacedCredential>;
319
319
  /**
320
- * Set to `manual` by a feature that follows redirects itself. A transport
320
+ * Set to `manual` where the client follows redirects itself. A transport
321
321
  * that honors it hands back the redirect rather than following it.
322
322
  */
323
323
  redirect?: 'manual';
324
324
  /** Calls the request off when it aborts. */
325
325
  signal?: AbortSignal | undefined;
326
- /** What to tell the caller where the API refuses a call sent with no credential. */
327
326
  unauthenticated?: () => string;
328
327
  }
329
328
 
@@ -362,7 +361,6 @@ export type AnyTransport<TAddress = unknown> = {
362
361
  } & Partial<TransportMethods<TAddress>>;
363
362
 
364
363
  export interface Binding<TAddress = unknown> {
365
- /** What a request asks for where neither its call nor its client says. */
366
364
  readonly accept?: string;
367
365
  applyAuth(credential: Credential, request: PreparedRequest<TAddress>): void;
368
366
  readonly name: string;
@@ -127,7 +127,7 @@ function callLog(id: string, request: PreparedRequest, at: number, sink: Logger)
127
127
  if (response?.redirected && at >= LEVELS.warn) {
128
128
  sink.warn(line(`was redirected to ${safeAddress(response.url)}`));
129
129
  }
130
- if (at >= LEVELS.info) sink.info(line(`→ ${response?.status ?? '?'} in ${ms} ms`));
130
+ if (at >= LEVELS.info) sink.info(line(`-> ${response?.status ?? '?'} in ${ms} ms`));
131
131
  if (at >= LEVELS.debug) {
132
132
  sink.debug(`[${id}] received`, {
133
133
  headers: safeHeaders(Object.fromEntries(response?.headers ?? []), request.callable),
@@ -140,7 +140,7 @@ function callLog(id: string, request: PreparedRequest, at: number, sink: Logger)
140
140
  if (at < LEVELS.warn) return;
141
141
  const again = `retrying in ${Math.round(wait)} ms (${retry} of ${retries})`;
142
142
  if (after?.status !== undefined) {
143
- sink.warn(line(`→ ${after.status}, ${again}`));
143
+ sink.warn(line(`-> ${after.status}, ${again}`));
144
144
  } else if (after?.error !== undefined) {
145
145
  sink.warn(line(`failed: ${failureText(after.error)}, ${again}`));
146
146
  } else {
@@ -1,7 +1,7 @@
1
1
  import { backoffDelay, exceedsMaxRetryAfter, retryAfterDelay, sleep } from '../core/backoff';
2
2
  import { discardBody, isStreamed } from '../core/body';
3
3
  import { calledOffWith, classifyError, ElmoError, failureOf, TransportError } from '../core/errors';
4
- import type { Feature, PreparedRequest, Result, RetryRules } from '../core/types';
4
+ import type { Feature, PreparedRequest, Result, RetryRules, Send } from '../core/types';
5
5
 
6
6
  /** Which failed calls are sent again, how many times, and how long each waits first. */
7
7
  export interface RetryOptions extends RetryRules {
@@ -9,7 +9,7 @@ export interface RetryOptions extends RetryRules {
9
9
  * How long to wait before the next attempt, in milliseconds, in place of the
10
10
  * API's retry headers and the backoff. `undefined` keeps the usual wait.
11
11
  * After a failure that got no reply, `result` holds only the `error`.
12
- * **{@link maxRetryAfter} does not limit what this returns.**
12
+ * {@link maxRetryAfter} does not limit what this returns.
13
13
  */
14
14
  retryDelay?(result: Result, request: PreparedRequest, attempt: number): number | undefined;
15
15
  /**
@@ -17,8 +17,9 @@ export interface RetryOptions extends RetryRules {
17
17
  * `retryOnTimeout`. After a reply, the body is unread: read it from
18
18
  * `response.clone()`. After a failure that got no reply, `result` holds only
19
19
  * the `error`. A call the API may have acted on is never asked about: a
20
- * method outside `methods` is sent again only after 408, 425 or 429, or when
21
- * the request never reached the API.
20
+ * method outside `methods` is sent again only after 408, 425 or 429, after
21
+ * a failure that answers `x-should-retry: true`, or when the request never
22
+ * reached the API.
22
23
  */
23
24
  retryOn?(result: Result, request: PreparedRequest): boolean;
24
25
  }
@@ -93,9 +94,12 @@ function shouldRetry(
93
94
  ): boolean {
94
95
  const { response } = result;
95
96
  if (!response) return false;
96
- if (!repeatable && !REFUSED_STATUSES.includes(response.status)) return false;
97
+ const asked = response.headers.get(RETRY_HEADER);
98
+ const invited = asked === 'true' && response.status >= 400;
99
+ if (!repeatable && !invited && !REFUSED_STATUSES.includes(response.status)) return false;
97
100
  if (config.retryOn) return config.retryOn(result, request);
98
- if (response.headers.get(RETRY_HEADER) === 'false') return false;
101
+ if (asked === 'false') return false;
102
+ if (invited) return true;
99
103
  const { statuses } = config;
100
104
  return statuses ? statuses.includes(response.status) : worthAnotherAttempt(response.status);
101
105
  }
@@ -115,51 +119,50 @@ function shouldRetryError(
115
119
  }
116
120
 
117
121
  export function retryFeature(options: RetryOptions = {}): Feature {
118
- return {
119
- name: 'retry',
120
- async onSend(request, next) {
121
- const config = isStreamed(request.body) ? undefined : resolveRetry(options, request);
122
- if (!config) return next(request);
123
-
124
- const attempts = (config.maxRetries ?? DEFAULT_MAX_RETRIES) + 1;
125
- const repeatable = isRepeatable(config, request);
126
- const started = Date.now();
127
-
128
- for (let attempt = 0; ; attempt++) {
129
- const last = attempt >= attempts - 1;
130
- let result: Result | undefined;
131
- let threw = false;
132
- let wait: number | undefined;
133
-
134
- if (attempt) request.attempt = attempt;
135
- try {
136
- result = await next(request);
137
- if (last || !shouldRetry(config, result, request, repeatable)) return result;
138
-
139
- wait = config.retryDelay?.(result, request, attempt);
140
- if (wait === undefined) {
141
- wait = askedFor(config, result);
142
- if (exceedsMaxRetryAfter(wait, config.maxRetryAfter)) return result;
143
- }
144
- } catch (error) {
145
- if (last || !shouldRetryError(config, error, request, repeatable)) throw error;
146
- threw = true;
147
- result = { error };
148
- wait = config.retryDelay?.(result, request, attempt);
149
- }
150
-
151
- wait ??= backoffDelay(attempt, config);
152
- if (config.budget !== undefined && Date.now() - started + wait >= config.budget) {
153
- if (threw) throw result.error;
154
- return result;
122
+ async function repeated(request: PreparedRequest, next: Send): Promise<Result> {
123
+ const config = isStreamed(request.body) ? undefined : resolveRetry(options, request);
124
+ if (!config) return next(request);
125
+
126
+ const attempts = (config.maxRetries ?? DEFAULT_MAX_RETRIES) + 1;
127
+ const repeatable = isRepeatable(config, request);
128
+ const started = Date.now();
129
+
130
+ for (let attempt = 0; ; attempt++) {
131
+ const last = attempt >= attempts - 1;
132
+ let result: Result | undefined;
133
+ let threw = false;
134
+ let wait: number | undefined;
135
+
136
+ if (attempt) request.attempt = attempt;
137
+ try {
138
+ result = await next(request);
139
+ if (last || !shouldRetry(config, result, request, repeatable)) return result;
140
+
141
+ wait = config.retryDelay?.(result, request, attempt);
142
+ if (wait === undefined) {
143
+ wait = askedFor(config, result);
144
+ if (exceedsMaxRetryAfter(wait, config.maxRetryAfter)) return result;
155
145
  }
146
+ } catch (error) {
147
+ if (last || !shouldRetryError(config, error, request, repeatable)) throw error;
148
+ threw = true;
149
+ result = { error };
150
+ wait = config.retryDelay?.(result, request, attempt);
151
+ }
156
152
 
157
- discardBody(result);
158
- request.log?.retrying(wait, attempt + 1, attempts - 1, result);
159
- await sleep(wait, request.signal).catch((reason: unknown) => {
160
- throw calledOffWith(reason);
161
- });
153
+ wait ??= backoffDelay(attempt, config);
154
+ if (config.budget !== undefined && Date.now() - started + wait >= config.budget) {
155
+ if (threw) throw result.error;
156
+ return result;
162
157
  }
163
- },
164
- };
158
+
159
+ discardBody(result);
160
+ request.log?.retrying(wait, attempt + 1, attempts - 1, result);
161
+ await sleep(wait, request.signal).catch((reason: unknown) => {
162
+ throw calledOffWith(reason);
163
+ });
164
+ }
165
+ }
166
+
167
+ return { name: 'retry', onOpen: repeated, onSend: repeated };
165
168
  }
@@ -131,7 +131,7 @@ export function timeoutFeature(options: TimeoutOptions = {}): Feature {
131
131
  request.signal = caller;
132
132
  });
133
133
  const { response } = result;
134
- if (response?.body && (stream || request.options.unread)) {
134
+ if (response?.body && stream) {
135
135
  return { ...result, response: watchedReply(response, wait, done) };
136
136
  }
137
137
  done();
@@ -141,6 +141,6 @@ export function timeoutFeature(options: TimeoutOptions = {}): Feature {
141
141
  return {
142
142
  name: 'timeout',
143
143
  onOpen: (request, next) => bounded(request, next, true),
144
- onSend: (request, next) => bounded(request, next, false),
144
+ onSend: (request, next) => bounded(request, next, !!request.options.unread),
145
145
  };
146
146
  }
@@ -66,6 +66,14 @@ export function decoded<TIn, TOut>(at: string, value: TIn, read: (value: TIn) =>
66
66
  return result;
67
67
  }
68
68
 
69
+ export type Mutable<T> = T extends (...args: Array<never>) => unknown
70
+ ? T
71
+ : T extends object
72
+ ? {
73
+ -readonly [K in keyof T]: Mutable<T[K]>;
74
+ }
75
+ : T;
76
+
69
77
  export function reviving<T>(revive: (value: T) => void): Validate {
70
78
  return (data) => {
71
79
  if (data != null) revive(data as T);
@@ -4,6 +4,7 @@ import { ElmoResource } from './shared/resource';
4
4
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
5
5
  import { callable } from '../internal/core/callable';
6
6
  import { mergeParams, placeParams } from '../internal/core/params';
7
+ import type { Mutable } from '../internal/feature/validate';
7
8
  import { decoded, reviving } from '../internal/feature/validate';
8
9
  import type {
9
10
  BrandAnalytics,
@@ -40,7 +41,7 @@ import type { BrandIdPath } from '../types/shared/brand-id-path';
40
41
 
41
42
  export const getBrandAnalyticsFields = { path: ['brandId'] };
42
43
 
43
- function reviveDateRange(value: DateRange): void {
44
+ function reviveDateRange(value: Mutable<DateRange>): void {
44
45
  if (value.start != null) {
45
46
  value.start = decoded('DateRange.start', value.start, (raw) => new Date(raw));
46
47
  }
@@ -49,7 +50,7 @@ function reviveDateRange(value: DateRange): void {
49
50
  }
50
51
  }
51
52
 
52
- function reviveBrandAnalytics(value: BrandAnalytics): void {
53
+ function reviveBrandAnalytics(value: Mutable<BrandAnalytics>): void {
53
54
  if (value.range != null) {
54
55
  reviveDateRange(value.range);
55
56
  }
@@ -65,7 +66,7 @@ export const getBrandAnalyticsDescriptor = /* @__PURE__ */ callable({
65
66
 
66
67
  export const listBrandCitationDomainsFields = { path: ['brandId'] };
67
68
 
68
- function reviveCitationDomainList(value: CitationDomainList): void {
69
+ function reviveCitationDomainList(value: Mutable<CitationDomainList>): void {
69
70
  if (value.range != null) {
70
71
  reviveDateRange(value.range);
71
72
  }
@@ -81,7 +82,7 @@ export const listBrandCitationDomainsDescriptor = /* @__PURE__ */ callable({
81
82
 
82
83
  export const listBrandCitationUrlsFields = { path: ['brandId'] };
83
84
 
84
- function reviveCitationUrlList(value: CitationURLList): void {
85
+ function reviveCitationUrlList(value: Mutable<CitationURLList>): void {
85
86
  if (value.range != null) {
86
87
  reviveDateRange(value.range);
87
88
  }
@@ -97,7 +98,7 @@ export const listBrandCitationURLsDescriptor = /* @__PURE__ */ callable({
97
98
 
98
99
  export const listBrandPromptPerformanceFields = { path: ['brandId'] };
99
100
 
100
- function revivePromptPerformance(value: PromptPerformanceSchema): void {
101
+ function revivePromptPerformance(value: Mutable<PromptPerformanceSchema>): void {
101
102
  if (value.lastRunAt != null) {
102
103
  value.lastRunAt = decoded(
103
104
  'PromptPerformance.lastRunAt',
@@ -114,7 +115,7 @@ function revivePromptPerformance(value: PromptPerformanceSchema): void {
114
115
  }
115
116
  }
116
117
 
117
- function revivePromptPerformanceList(value: PromptPerformanceList): void {
118
+ function revivePromptPerformanceList(value: Mutable<PromptPerformanceList>): void {
118
119
  if (value.range != null) {
119
120
  reviveDateRange(value.range);
120
121
  }
@@ -135,7 +136,7 @@ export const listBrandPromptPerformanceDescriptor = /* @__PURE__ */ callable({
135
136
 
136
137
  export const getBrandQueryFanoutFields = { path: ['brandId'] };
137
138
 
138
- function reviveBrandQueryFanout(value: BrandQueryFanout): void {
139
+ function reviveBrandQueryFanout(value: Mutable<BrandQueryFanout>): void {
139
140
  if (value.range != null) {
140
141
  reviveDateRange(value.range);
141
142
  }
@@ -7,9 +7,10 @@ import { brandNameRule, domainsRule, nameRule } from './shared/rule';
7
7
  import { Tags } from './tags';
8
8
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
9
9
  import { callable } from '../internal/core/callable';
10
+ import { PagePromise, pages } from '../internal/core/page';
10
11
  import { groupParams, mergeParams, placeParams } from '../internal/core/params';
12
+ import type { Mutable } from '../internal/feature/validate';
11
13
  import { decoded, reviving } from '../internal/feature/validate';
12
- import { PagePromise, pages } from '../internal/page/page';
13
14
  import type {
14
15
  BrandAnalytics,
15
16
  BrandQueryFanout,
@@ -26,6 +27,7 @@ import type {
26
27
  ListBrandPromptPerformanceResponses,
27
28
  ModelVisibility,
28
29
  PromptPerformanceList,
30
+ PromptPerformance as PromptPerformanceSchema,
29
31
  ShareOfVoiceEntry,
30
32
  ShareOfVoicePoint,
31
33
  TagsFilter,
@@ -57,7 +59,7 @@ import type {
57
59
  import type { BrandIdPath } from '../types/shared/brand-id-path';
58
60
  import type { ListBrandTagsErrors, ListBrandTagsResponses, Tag, TagList } from '../types/tags';
59
61
 
60
- function reviveBrand(value: Brand): void {
62
+ function reviveBrand(value: Mutable<Brand>): void {
61
63
  if (value.createdAt != null) {
62
64
  value.createdAt = decoded('Brand.createdAt', value.createdAt, (raw) => new Date(raw));
63
65
  }
@@ -66,7 +68,7 @@ function reviveBrand(value: Brand): void {
66
68
  }
67
69
  }
68
70
 
69
- function reviveBrandsList(value: BrandsList): void {
71
+ function reviveBrandsList(value: Mutable<BrandsList>): void {
70
72
  if (value.data != null) {
71
73
  value.data.forEach((item) => {
72
74
  reviveBrand(item);
@@ -268,8 +270,9 @@ export declare namespace Brands {
268
270
  Opportunities,
269
271
  Opportunity,
270
272
  OpportunityPrompt,
271
- PromptPerformance,
273
+ PromptPerformanceSchema as PromptPerformance,
272
274
  PromptPerformanceList,
275
+ PromptPerformance as PromptPerformanceResource,
273
276
  QueryFanout,
274
277
  ShareOfVoiceEntry,
275
278
  ShareOfVoicePoint,
@@ -4,9 +4,10 @@ import { ElmoResource } from './shared/resource';
4
4
  import { nameRule } from './shared/rule';
5
5
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
6
6
  import { callable } from '../internal/core/callable';
7
+ import { PagePromise, pages } from '../internal/core/page';
7
8
  import { groupParams, mergeParams, placeParams } from '../internal/core/params';
9
+ import type { Mutable } from '../internal/feature/validate';
8
10
  import { decoded, reviving } from '../internal/feature/validate';
9
- import { PagePromise, pages } from '../internal/page/page';
10
11
  import type {
11
12
  Competitor,
12
13
  CompetitorsList,
@@ -25,7 +26,7 @@ import type {
25
26
  UpdateCompetitorResponses,
26
27
  } from '../types/competitors';
27
28
 
28
- function reviveCompetitor(value: Competitor): void {
29
+ function reviveCompetitor(value: Mutable<Competitor>): void {
29
30
  if (value.createdAt != null) {
30
31
  value.createdAt = decoded('Competitor.createdAt', value.createdAt, (raw) => new Date(raw));
31
32
  }
@@ -34,7 +35,7 @@ function reviveCompetitor(value: Competitor): void {
34
35
  }
35
36
  }
36
37
 
37
- function reviveCompetitorsList(value: CompetitorsList): void {
38
+ function reviveCompetitorsList(value: Mutable<CompetitorsList>): void {
38
39
  if (value.data != null) {
39
40
  value.data.forEach((item) => {
40
41
  reviveCompetitor(item);
@@ -3,10 +3,11 @@ import type { RequestOptions } from './shared/request-options';
3
3
  import { ElmoResource } from './shared/resource';
4
4
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
5
5
  import { callable } from '../internal/core/callable';
6
+ import type { Mutable } from '../internal/feature/validate';
6
7
  import { decoded, reviving } from '../internal/feature/validate';
7
8
  import type { APIKeyIdentity, GetMeErrors, GetMeResponses } from '../types/identity';
8
9
 
9
- function reviveApiKeyIdentity(value: APIKeyIdentity): void {
10
+ function reviveApiKeyIdentity(value: Mutable<APIKeyIdentity>): void {
10
11
  if (value.createdAt != null) {
11
12
  value.createdAt = decoded('ApiKeyIdentity.createdAt', value.createdAt, (raw) => new Date(raw));
12
13
  }
@@ -4,6 +4,7 @@ import { ElmoResource } from './shared/resource';
4
4
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
5
5
  import { callable } from '../internal/core/callable';
6
6
  import { mergeParams, placeParams } from '../internal/core/params';
7
+ import type { Mutable } from '../internal/feature/validate';
7
8
  import { decoded, reviving } from '../internal/feature/validate';
8
9
  import type {
9
10
  BrandOpportunities,
@@ -17,7 +18,7 @@ import type { BrandIdPath } from '../types/shared/brand-id-path';
17
18
 
18
19
  export const getBrandOpportunitiesFields = { path: ['brandId'] };
19
20
 
20
- function reviveBrandOpportunities(value: BrandOpportunities): void {
21
+ function reviveBrandOpportunities(value: Mutable<BrandOpportunities>): void {
21
22
  if (value.generatedAt != null) {
22
23
  value.generatedAt = decoded(
23
24
  'BrandOpportunities.generatedAt',
@@ -32,6 +33,7 @@ export const getBrandOpportunitiesDescriptor = /* @__PURE__ */ callable({
32
33
  auth: apiKeyRequirements,
33
34
  method: 'get',
34
35
  returns: 'json',
36
+ timeout: 600000,
35
37
  validators: { response: /* @__PURE__ */ reviving(reviveBrandOpportunities) },
36
38
  } as const);
37
39
 
@@ -3,9 +3,10 @@ import type { RequestOptions } from './shared/request-options';
3
3
  import { ElmoResource } from './shared/resource';
4
4
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
5
5
  import { callable } from '../internal/core/callable';
6
+ import { PagePromise, pages } from '../internal/core/page';
6
7
  import { groupParams, mergeParams, placeParams } from '../internal/core/params';
8
+ import type { Mutable } from '../internal/feature/validate';
7
9
  import { decoded, reviving } from '../internal/feature/validate';
8
- import { PagePromise, pages } from '../internal/page/page';
9
10
  import type {
10
11
  BillingPlan,
11
12
  GetOrganizationBillingErrors,
@@ -23,13 +24,13 @@ import type {
23
24
 
24
25
  export const getOrganizationBillingFields = { path: ['organizationId'] };
25
26
 
26
- function reviveBillingPlan(value: BillingPlan): void {
27
+ function reviveBillingPlan(value: Mutable<BillingPlan>): void {
27
28
  if (value.periodEnd != null) {
28
29
  value.periodEnd = decoded('BillingPlan.periodEnd', value.periodEnd, (raw) => new Date(raw));
29
30
  }
30
31
  }
31
32
 
32
- function reviveOrganizationBilling(value: OrganizationBilling): void {
33
+ function reviveOrganizationBilling(value: Mutable<OrganizationBilling>): void {
33
34
  if (value.plan != null) {
34
35
  reviveBillingPlan(value.plan);
35
36
  }
@@ -43,13 +44,13 @@ export const getOrganizationBillingDescriptor = /* @__PURE__ */ callable({
43
44
  validators: { response: /* @__PURE__ */ reviving(reviveOrganizationBilling) },
44
45
  } as const);
45
46
 
46
- function reviveOrganization(value: Organization): void {
47
+ function reviveOrganization(value: Mutable<Organization>): void {
47
48
  if (value.createdAt != null) {
48
49
  value.createdAt = decoded('Organization.createdAt', value.createdAt, (raw) => new Date(raw));
49
50
  }
50
51
  }
51
52
 
52
- function reviveOrganizationList(value: OrganizationList): void {
53
+ function reviveOrganizationList(value: Mutable<OrganizationList>): void {
53
54
  if (value.data != null) {
54
55
  value.data.forEach((item) => {
55
56
  reviveOrganization(item);
@@ -6,9 +6,10 @@ import { valueRule } from './shared/rule';
6
6
  import { Snapshot } from './snapshots';
7
7
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
8
8
  import { callable } from '../internal/core/callable';
9
+ import { PagePromise, pages } from '../internal/core/page';
9
10
  import { groupParams, mergeParams, placeParams } from '../internal/core/params';
11
+ import type { Mutable } from '../internal/feature/validate';
10
12
  import { decoded, reviving } from '../internal/feature/validate';
11
- import { PagePromise, pages } from '../internal/page/page';
12
13
  import type {
13
14
  CreatePromptErrors,
14
15
  CreatePromptParams,
@@ -46,7 +47,7 @@ import type {
46
47
  PromptSnapshot,
47
48
  } from '../types/snapshots';
48
49
 
49
- function revivePrompt(value: Prompt): void {
50
+ function revivePrompt(value: Mutable<Prompt>): void {
50
51
  if (value.createdAt != null) {
51
52
  value.createdAt = decoded('Prompt.createdAt', value.createdAt, (raw) => new Date(raw));
52
53
  }
@@ -4,9 +4,10 @@ import { ElmoResource } from './shared/resource';
4
4
  import { brandNameRule } from './shared/rule';
5
5
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
6
6
  import { callable } from '../internal/core/callable';
7
+ import { PagePromise, pages } from '../internal/core/page';
7
8
  import { groupParams, mergeParams, placeParams } from '../internal/core/params';
9
+ import type { Mutable } from '../internal/feature/validate';
8
10
  import { decoded } from '../internal/feature/validate';
9
- import { PagePromise, pages } from '../internal/page/page';
10
11
  import type {
11
12
  CreateReportErrors,
12
13
  CreateReportParams,
@@ -24,7 +25,7 @@ import type {
24
25
  ReportSummary,
25
26
  } from '../types/reports';
26
27
 
27
- function reviveReportSummary(value: ReportSummary): void {
28
+ function reviveReportSummary(value: Mutable<ReportSummary>): void {
28
29
  if (value.createdAt != null) {
29
30
  value.createdAt = decoded('ReportSummary.createdAt', value.createdAt, (raw) => new Date(raw));
30
31
  }
@@ -3,9 +3,10 @@ import type { RequestOptions } from './shared/request-options';
3
3
  import { ElmoResource } from './shared/resource';
4
4
  import { callPromise, RestCallPromise } from '../internal/core/call-promise';
5
5
  import { callable } from '../internal/core/callable';
6
+ import { PagePromise, pages } from '../internal/core/page';
6
7
  import { mergeParams, placeParams } from '../internal/core/params';
8
+ import type { Mutable } from '../internal/feature/validate';
7
9
  import { decoded, reviving } from '../internal/feature/validate';
8
- import { PagePromise, pages } from '../internal/page/page';
9
10
  import type {
10
11
  GetRunErrors,
11
12
  GetRunResponses,
@@ -20,13 +21,13 @@ import type {
20
21
 
21
22
  export const listPromptRunsFields = { path: ['promptId'] };
22
23
 
23
- function reviveRunSummary(value: RunSummary): void {
24
+ function reviveRunSummary(value: Mutable<RunSummary>): void {
24
25
  if (value.createdAt != null) {
25
26
  value.createdAt = decoded('RunSummary.createdAt', value.createdAt, (raw) => new Date(raw));
26
27
  }
27
28
  }
28
29
 
29
- function reviveRunList(value: RunList): void {
30
+ function reviveRunList(value: Mutable<RunList>): void {
30
31
  if (value.data != null) {
31
32
  value.data.forEach((item) => {
32
33
  reviveRunSummary(item);
@@ -53,7 +54,7 @@ export const listPromptRunsDescriptor = /* @__PURE__ */ callable({
53
54
 
54
55
  export const getRunFields = { path: ['promptId', 'runId'] };
55
56
 
56
- function reviveRun(value: Run): void {
57
+ function reviveRun(value: Mutable<Run>): void {
57
58
  if (value.createdAt != null) {
58
59
  value.createdAt = decoded('Run.createdAt', value.createdAt, (raw) => new Date(raw));
59
60
  }