@signaliz/sdk 1.0.46 → 1.0.47

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 CHANGED
@@ -20,6 +20,15 @@ const signaliz = new Signaliz({
20
20
  apiKey: process.env.SIGNALIZ_API_KEY,
21
21
  });
22
22
 
23
+ // Every product supports a strict no-spend preflight. Batch methods accept the
24
+ // same option and return one plan for the full input.
25
+ const plan = await signaliz.findEmail({
26
+ companyDomain: 'example.com',
27
+ fullName: 'Jane Doe',
28
+ dryRun: true,
29
+ });
30
+ console.log(plan.estimatedCredits.max, plan.creditsCharged); // 2, 0
31
+
23
32
  const found = await signaliz.findEmail({
24
33
  companyDomain: 'example.com',
25
34
  fullName: 'Jane Doe',
@@ -104,8 +113,9 @@ Failed rows preserve `errorCode`, `retryEligible`, and `retryAfterSeconds`
104
113
  when the REST API supplies them, including after automatic row retries are
105
114
  exhausted.
106
115
 
107
- For an ambiguous submission failure, retry with the same
108
- `idempotencyKey` to recover the original job without duplicate work.
116
+ For an ambiguous single request or batch submission failure, retry with the
117
+ same `idempotencyKey` to recover the original request or job without duplicate
118
+ work.
109
119
 
110
120
  Each batch accepts up to 5,000 items. Company Signal Enrichment transparently
111
121
  resumes long-running research through the same `/company-signals` endpoint;
@@ -378,10 +378,17 @@ var Signaliz = class {
378
378
  }
379
379
  async findEmail(params) {
380
380
  const data = await this.client.post("api/v1/find-email", findEmailRequestBody(params));
381
- return normalizeFindEmailResult(data);
381
+ return isCoreProductDryRun(data) ? normalizeCoreProductDryRunResult(data) : normalizeFindEmailResult(data);
382
382
  }
383
383
  async findEmails(params, options) {
384
384
  validateBatchSize(params);
385
+ if (options?.dryRun === true) {
386
+ return this.runCoreProductDryRun(
387
+ "api/v1/find-email",
388
+ params.map(findEmailRequestBody),
389
+ options.idempotencyKey
390
+ );
391
+ }
385
392
  const startedAt = Date.now();
386
393
  const round = await this.runCoreBatchRound(
387
394
  "api/v1/find-email",
@@ -400,9 +407,12 @@ var Signaliz = class {
400
407
  const request = compact({
401
408
  email: email || void 0,
402
409
  verification_run_id: options?.verificationRunId,
403
- skip_cache: options?.skipCache
410
+ skip_cache: options?.skipCache,
411
+ dry_run: options?.dryRun,
412
+ idempotency_key: options?.idempotencyKey
404
413
  });
405
414
  let data = await this.client.post("api/v1/verify-email", request);
415
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
406
416
  if (options?.waitForResult !== false && isPendingSignalResponse(data) && data.verification_run_id) {
407
417
  const maxWaitMs = Math.max(1e3, options?.maxWaitMs ?? 10 * 6e4);
408
418
  const startedAt = Date.now();
@@ -422,6 +432,13 @@ var Signaliz = class {
422
432
  }
423
433
  async verifyEmails(emails, options) {
424
434
  validateBatchSize(emails);
435
+ if (options?.dryRun === true) {
436
+ return this.runCoreProductDryRun(
437
+ "api/v1/verify-email",
438
+ emails.map((email) => ({ email, skip_cache: options.skipCache })),
439
+ options.idempotencyKey
440
+ );
441
+ }
425
442
  const startedAt = Date.now();
426
443
  const round = await this.runCoreBatchRound(
427
444
  "api/v1/verify-email",
@@ -442,6 +459,7 @@ var Signaliz = class {
442
459
  async enrichCompanySignals(params) {
443
460
  const request = companySignalRequestBody(params);
444
461
  let data = await this.client.post("api/v1/company-signals", request);
462
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
445
463
  if (params.waitForResult !== false && data.run_id && isPendingSignalResponse(data)) {
446
464
  const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
447
465
  const startedAt = Date.now();
@@ -472,6 +490,13 @@ var Signaliz = class {
472
490
  }
473
491
  async enrichCompanies(companies, options) {
474
492
  validateBatchSize(companies);
493
+ if (options?.dryRun === true) {
494
+ return this.runCoreProductDryRun(
495
+ "api/v1/company-signals",
496
+ companies.map(companySignalRequestBody),
497
+ options.idempotencyKey
498
+ );
499
+ }
475
500
  const startedAt = Date.now();
476
501
  const results = new Array(companies.length);
477
502
  const initialTasks = companies.map((params, index) => ({
@@ -549,6 +574,7 @@ var Signaliz = class {
549
574
  validateSignalToCopyParams(params);
550
575
  const request = signalToCopyRequestBody(params);
551
576
  let data = await this.client.post("api/v1/signal-to-copy", request);
577
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
552
578
  if (params.waitForResult !== false && (data.signal_run_id || data.run_id) && isPendingSignalResponse(data)) {
553
579
  const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
554
580
  const startedAt = Date.now();
@@ -567,6 +593,13 @@ var Signaliz = class {
567
593
  async createSignalCopyBatch(requests, options) {
568
594
  validateBatchSize(requests);
569
595
  requests.forEach(validateSignalToCopyParams);
596
+ if (options?.dryRun === true) {
597
+ return this.runCoreProductDryRun(
598
+ "api/v1/signal-to-copy",
599
+ requests.map(signalToCopyRequestBody),
600
+ options.idempotencyKey
601
+ );
602
+ }
570
603
  const startedAt = Date.now();
571
604
  const deduplicated = dedupeExactBatchItems(requests, (params) => JSON.stringify({
572
605
  request: signalToCopyRequestBody(params),
@@ -593,6 +626,17 @@ var Signaliz = class {
593
626
  results: compactedResults
594
627
  };
595
628
  }
629
+ async runCoreProductDryRun(path, requests, idempotencyKey) {
630
+ const data = await this.client.post(path, compact({
631
+ requests,
632
+ dry_run: true,
633
+ idempotency_key: idempotencyKey
634
+ }));
635
+ if (!isCoreProductDryRun(data)) {
636
+ throw new Error(`${path} dry run returned a live-result contract`);
637
+ }
638
+ return normalizeCoreProductDryRunResult(data);
639
+ }
596
640
  async runSignalCopyBatchChunks(uniqueRequests, options) {
597
641
  const chunks = [];
598
642
  for (let offset = 0; offset < uniqueRequests.length; offset += 25) {
@@ -951,9 +995,34 @@ function findEmailRequestBody(params) {
951
995
  last_name: params.lastName,
952
996
  linkedin_url: params.linkedinUrl,
953
997
  company_name: params.companyName,
954
- skip_cache: params.skipCache
998
+ skip_cache: params.skipCache,
999
+ dry_run: params.dryRun,
1000
+ idempotency_key: params.idempotencyKey
955
1001
  });
956
1002
  }
1003
+ function isCoreProductDryRun(data) {
1004
+ return data.dry_run === true && data.status === "planned";
1005
+ }
1006
+ function normalizeCoreProductDryRunResult(data) {
1007
+ const estimatedCredits = data.estimated_credits && typeof data.estimated_credits === "object" ? data.estimated_credits : { min: 0, max: 0 };
1008
+ return {
1009
+ success: true,
1010
+ dryRun: true,
1011
+ status: "planned",
1012
+ capability: String(data.capability || ""),
1013
+ inputCount: Number(data.input_count || 0),
1014
+ recoveryReadCount: Number(data.recovery_read_count || 0),
1015
+ plan: data.plan && typeof data.plan === "object" ? data.plan : {},
1016
+ estimate: data.estimate && typeof data.estimate === "object" ? data.estimate : {},
1017
+ estimatedCredits: {
1018
+ min: Number(estimatedCredits.min || 0),
1019
+ max: Number(estimatedCredits.max || 0)
1020
+ },
1021
+ creditsCharged: 0,
1022
+ sideEffects: Array.isArray(data.side_effects) ? data.side_effects : [],
1023
+ raw: data
1024
+ };
1025
+ }
957
1026
  function normalizeFindEmailResult(data) {
958
1027
  const email = typeof data.email === "string" && data.email.trim() ? data.email.trim() : null;
959
1028
  const found = Boolean(email) && data.found !== false;
@@ -1022,7 +1091,9 @@ function companySignalRequestBody(params) {
1022
1091
  // REST always returns a resumable run instead of holding the connection;
1023
1092
  // waitForResult controls the SDK polling loop.
1024
1093
  wait_for_result: false,
1025
- max_wait_ms: params.maxWaitMs
1094
+ max_wait_ms: params.maxWaitMs,
1095
+ dry_run: params.dryRun,
1096
+ idempotency_key: params.idempotencyKey
1026
1097
  });
1027
1098
  }
1028
1099
  function companySignalRecoverableBatchOptions(companies, tasks) {
@@ -1194,7 +1265,9 @@ function signalToCopyRequestBody(params) {
1194
1265
  research_prompt: params.researchPrompt,
1195
1266
  signal_run_id: params.signalRunId,
1196
1267
  skip_cache: params.skipCache,
1197
- enable_deep_search: params.enableDeepSearch
1268
+ enable_deep_search: params.enableDeepSearch,
1269
+ dry_run: params.dryRun,
1270
+ idempotency_key: params.idempotencyKey
1198
1271
  });
1199
1272
  }
1200
1273
  function validateSignalToCopyParams(params) {
package/dist/index.d.mts CHANGED
@@ -13,6 +13,8 @@ interface BatchOptions {
13
13
  idempotencyKey?: string;
14
14
  /** Return exact repeated successes as duplicateOf references. Defaults to false. */
15
15
  compactDuplicates?: boolean;
16
+ /** Return one no-spend plan for the full batch without provider calls or jobs. */
17
+ dryRun?: boolean;
16
18
  }
17
19
  interface BatchItemResult<T> {
18
20
  index: number;
@@ -43,6 +45,23 @@ interface SignalizErrorData {
43
45
  retryAfter?: number;
44
46
  details?: Record<string, unknown>;
45
47
  }
48
+ interface CoreProductDryRunResult {
49
+ success: true;
50
+ dryRun: true;
51
+ status: 'planned';
52
+ capability: string;
53
+ inputCount: number;
54
+ recoveryReadCount: number;
55
+ plan: Record<string, unknown>;
56
+ estimate: Record<string, unknown>;
57
+ estimatedCredits: {
58
+ min: number;
59
+ max: number;
60
+ };
61
+ creditsCharged: 0;
62
+ sideEffects: unknown[];
63
+ raw: Record<string, unknown>;
64
+ }
46
65
  interface FindEmailParams {
47
66
  companyDomain: string;
48
67
  fullName?: string;
@@ -52,6 +71,10 @@ interface FindEmailParams {
52
71
  companyName?: string;
53
72
  /** Bypass cached email and verification data for a fresh-provider run. */
54
73
  skipCache?: boolean;
74
+ /** Return a no-spend plan without provider calls or jobs. */
75
+ dryRun?: boolean;
76
+ /** Stable retry key for recovering the same request after an ambiguous response. */
77
+ idempotencyKey?: string;
55
78
  }
56
79
  interface FindEmailResult {
57
80
  success: boolean;
@@ -100,6 +123,10 @@ interface VerifyEmailOptions {
100
123
  maxWaitMs?: number;
101
124
  /** Override the server-provided polling delay. */
102
125
  pollIntervalMs?: number;
126
+ /** Return a no-spend plan without provider calls or jobs. */
127
+ dryRun?: boolean;
128
+ /** Stable retry key for recovering the same request after an ambiguous response. */
129
+ idempotencyKey?: string;
103
130
  }
104
131
  interface VerifyEmailBatchOptions extends BatchOptions, VerifyEmailOptions {
105
132
  }
@@ -124,6 +151,10 @@ interface CompanySignalEnrichmentParams {
124
151
  maxWaitMs?: number;
125
152
  /** Delay between queued-enrichment status checks. Defaults to 2 seconds. */
126
153
  pollIntervalMs?: number;
154
+ /** Return a no-spend plan without provider calls or jobs. */
155
+ dryRun?: boolean;
156
+ /** Stable retry key for recovering the same request after an ambiguous response. */
157
+ idempotencyKey?: string;
127
158
  }
128
159
  interface CompanySignal {
129
160
  id?: string;
@@ -186,6 +217,10 @@ interface SignalToCopyParams {
186
217
  waitForResult?: boolean;
187
218
  maxWaitMs?: number;
188
219
  pollIntervalMs?: number;
220
+ /** Return a no-spend plan without provider calls or jobs. */
221
+ dryRun?: boolean;
222
+ /** Stable retry key for recovering the same request after an ambiguous response. */
223
+ idempotencyKey?: string;
189
224
  }
190
225
  interface SignalToCopyVariation {
191
226
  style: 'signal_led' | 'business_case' | 'predictive';
@@ -237,14 +272,39 @@ declare class SignalizError extends Error {
237
272
  declare class Signaliz {
238
273
  private readonly client;
239
274
  constructor(config: SignalizConfig);
275
+ findEmail(params: FindEmailParams & {
276
+ dryRun: true;
277
+ }): Promise<CoreProductDryRunResult>;
240
278
  findEmail(params: FindEmailParams): Promise<FindEmailResult>;
279
+ findEmails(params: FindEmailParams[], options: BatchOptions & {
280
+ dryRun: true;
281
+ }): Promise<CoreProductDryRunResult>;
241
282
  findEmails(params: FindEmailParams[], options?: BatchOptions): Promise<BatchResult<FindEmailResult>>;
283
+ verifyEmail(email: string | undefined, options: VerifyEmailOptions & {
284
+ dryRun: true;
285
+ }): Promise<CoreProductDryRunResult>;
242
286
  verifyEmail(email: string | undefined, options?: VerifyEmailOptions): Promise<VerifyEmailResult>;
287
+ verifyEmails(emails: string[], options: VerifyEmailBatchOptions & {
288
+ dryRun: true;
289
+ }): Promise<CoreProductDryRunResult>;
243
290
  verifyEmails(emails: string[], options?: VerifyEmailBatchOptions): Promise<BatchResult<VerifyEmailResult>>;
291
+ enrichCompanySignals(params: CompanySignalEnrichmentParams & {
292
+ dryRun: true;
293
+ }): Promise<CoreProductDryRunResult>;
244
294
  enrichCompanySignals(params: CompanySignalEnrichmentParams): Promise<CompanySignalEnrichmentResult>;
295
+ enrichCompanies(companies: CompanySignalEnrichmentParams[], options: BatchOptions & {
296
+ dryRun: true;
297
+ }): Promise<CoreProductDryRunResult>;
245
298
  enrichCompanies(companies: CompanySignalEnrichmentParams[], options?: BatchOptions): Promise<BatchResult<CompanySignalEnrichmentResult>>;
299
+ signalToCopy(params: SignalToCopyParams & {
300
+ dryRun: true;
301
+ }): Promise<CoreProductDryRunResult>;
246
302
  signalToCopy(params: SignalToCopyParams): Promise<SignalToCopyResult>;
303
+ createSignalCopyBatch(requests: SignalToCopyParams[], options: BatchOptions & {
304
+ dryRun: true;
305
+ }): Promise<CoreProductDryRunResult>;
247
306
  createSignalCopyBatch(requests: SignalToCopyParams[], options?: BatchOptions): Promise<BatchResult<SignalToCopyResult>>;
307
+ private runCoreProductDryRun;
248
308
  private runSignalCopyBatchChunks;
249
309
  private runAvailableSignalCopyBatchJob;
250
310
  private runRecoverableCoreBatchJob;
package/dist/index.d.ts CHANGED
@@ -13,6 +13,8 @@ interface BatchOptions {
13
13
  idempotencyKey?: string;
14
14
  /** Return exact repeated successes as duplicateOf references. Defaults to false. */
15
15
  compactDuplicates?: boolean;
16
+ /** Return one no-spend plan for the full batch without provider calls or jobs. */
17
+ dryRun?: boolean;
16
18
  }
17
19
  interface BatchItemResult<T> {
18
20
  index: number;
@@ -43,6 +45,23 @@ interface SignalizErrorData {
43
45
  retryAfter?: number;
44
46
  details?: Record<string, unknown>;
45
47
  }
48
+ interface CoreProductDryRunResult {
49
+ success: true;
50
+ dryRun: true;
51
+ status: 'planned';
52
+ capability: string;
53
+ inputCount: number;
54
+ recoveryReadCount: number;
55
+ plan: Record<string, unknown>;
56
+ estimate: Record<string, unknown>;
57
+ estimatedCredits: {
58
+ min: number;
59
+ max: number;
60
+ };
61
+ creditsCharged: 0;
62
+ sideEffects: unknown[];
63
+ raw: Record<string, unknown>;
64
+ }
46
65
  interface FindEmailParams {
47
66
  companyDomain: string;
48
67
  fullName?: string;
@@ -52,6 +71,10 @@ interface FindEmailParams {
52
71
  companyName?: string;
53
72
  /** Bypass cached email and verification data for a fresh-provider run. */
54
73
  skipCache?: boolean;
74
+ /** Return a no-spend plan without provider calls or jobs. */
75
+ dryRun?: boolean;
76
+ /** Stable retry key for recovering the same request after an ambiguous response. */
77
+ idempotencyKey?: string;
55
78
  }
56
79
  interface FindEmailResult {
57
80
  success: boolean;
@@ -100,6 +123,10 @@ interface VerifyEmailOptions {
100
123
  maxWaitMs?: number;
101
124
  /** Override the server-provided polling delay. */
102
125
  pollIntervalMs?: number;
126
+ /** Return a no-spend plan without provider calls or jobs. */
127
+ dryRun?: boolean;
128
+ /** Stable retry key for recovering the same request after an ambiguous response. */
129
+ idempotencyKey?: string;
103
130
  }
104
131
  interface VerifyEmailBatchOptions extends BatchOptions, VerifyEmailOptions {
105
132
  }
@@ -124,6 +151,10 @@ interface CompanySignalEnrichmentParams {
124
151
  maxWaitMs?: number;
125
152
  /** Delay between queued-enrichment status checks. Defaults to 2 seconds. */
126
153
  pollIntervalMs?: number;
154
+ /** Return a no-spend plan without provider calls or jobs. */
155
+ dryRun?: boolean;
156
+ /** Stable retry key for recovering the same request after an ambiguous response. */
157
+ idempotencyKey?: string;
127
158
  }
128
159
  interface CompanySignal {
129
160
  id?: string;
@@ -186,6 +217,10 @@ interface SignalToCopyParams {
186
217
  waitForResult?: boolean;
187
218
  maxWaitMs?: number;
188
219
  pollIntervalMs?: number;
220
+ /** Return a no-spend plan without provider calls or jobs. */
221
+ dryRun?: boolean;
222
+ /** Stable retry key for recovering the same request after an ambiguous response. */
223
+ idempotencyKey?: string;
189
224
  }
190
225
  interface SignalToCopyVariation {
191
226
  style: 'signal_led' | 'business_case' | 'predictive';
@@ -237,14 +272,39 @@ declare class SignalizError extends Error {
237
272
  declare class Signaliz {
238
273
  private readonly client;
239
274
  constructor(config: SignalizConfig);
275
+ findEmail(params: FindEmailParams & {
276
+ dryRun: true;
277
+ }): Promise<CoreProductDryRunResult>;
240
278
  findEmail(params: FindEmailParams): Promise<FindEmailResult>;
279
+ findEmails(params: FindEmailParams[], options: BatchOptions & {
280
+ dryRun: true;
281
+ }): Promise<CoreProductDryRunResult>;
241
282
  findEmails(params: FindEmailParams[], options?: BatchOptions): Promise<BatchResult<FindEmailResult>>;
283
+ verifyEmail(email: string | undefined, options: VerifyEmailOptions & {
284
+ dryRun: true;
285
+ }): Promise<CoreProductDryRunResult>;
242
286
  verifyEmail(email: string | undefined, options?: VerifyEmailOptions): Promise<VerifyEmailResult>;
287
+ verifyEmails(emails: string[], options: VerifyEmailBatchOptions & {
288
+ dryRun: true;
289
+ }): Promise<CoreProductDryRunResult>;
243
290
  verifyEmails(emails: string[], options?: VerifyEmailBatchOptions): Promise<BatchResult<VerifyEmailResult>>;
291
+ enrichCompanySignals(params: CompanySignalEnrichmentParams & {
292
+ dryRun: true;
293
+ }): Promise<CoreProductDryRunResult>;
244
294
  enrichCompanySignals(params: CompanySignalEnrichmentParams): Promise<CompanySignalEnrichmentResult>;
295
+ enrichCompanies(companies: CompanySignalEnrichmentParams[], options: BatchOptions & {
296
+ dryRun: true;
297
+ }): Promise<CoreProductDryRunResult>;
245
298
  enrichCompanies(companies: CompanySignalEnrichmentParams[], options?: BatchOptions): Promise<BatchResult<CompanySignalEnrichmentResult>>;
299
+ signalToCopy(params: SignalToCopyParams & {
300
+ dryRun: true;
301
+ }): Promise<CoreProductDryRunResult>;
246
302
  signalToCopy(params: SignalToCopyParams): Promise<SignalToCopyResult>;
303
+ createSignalCopyBatch(requests: SignalToCopyParams[], options: BatchOptions & {
304
+ dryRun: true;
305
+ }): Promise<CoreProductDryRunResult>;
247
306
  createSignalCopyBatch(requests: SignalToCopyParams[], options?: BatchOptions): Promise<BatchResult<SignalToCopyResult>>;
307
+ private runCoreProductDryRun;
248
308
  private runSignalCopyBatchChunks;
249
309
  private runAvailableSignalCopyBatchJob;
250
310
  private runRecoverableCoreBatchJob;
package/dist/index.js CHANGED
@@ -405,10 +405,17 @@ var Signaliz = class {
405
405
  }
406
406
  async findEmail(params) {
407
407
  const data = await this.client.post("api/v1/find-email", findEmailRequestBody(params));
408
- return normalizeFindEmailResult(data);
408
+ return isCoreProductDryRun(data) ? normalizeCoreProductDryRunResult(data) : normalizeFindEmailResult(data);
409
409
  }
410
410
  async findEmails(params, options) {
411
411
  validateBatchSize(params);
412
+ if (options?.dryRun === true) {
413
+ return this.runCoreProductDryRun(
414
+ "api/v1/find-email",
415
+ params.map(findEmailRequestBody),
416
+ options.idempotencyKey
417
+ );
418
+ }
412
419
  const startedAt = Date.now();
413
420
  const round = await this.runCoreBatchRound(
414
421
  "api/v1/find-email",
@@ -427,9 +434,12 @@ var Signaliz = class {
427
434
  const request = compact({
428
435
  email: email || void 0,
429
436
  verification_run_id: options?.verificationRunId,
430
- skip_cache: options?.skipCache
437
+ skip_cache: options?.skipCache,
438
+ dry_run: options?.dryRun,
439
+ idempotency_key: options?.idempotencyKey
431
440
  });
432
441
  let data = await this.client.post("api/v1/verify-email", request);
442
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
433
443
  if (options?.waitForResult !== false && isPendingSignalResponse(data) && data.verification_run_id) {
434
444
  const maxWaitMs = Math.max(1e3, options?.maxWaitMs ?? 10 * 6e4);
435
445
  const startedAt = Date.now();
@@ -449,6 +459,13 @@ var Signaliz = class {
449
459
  }
450
460
  async verifyEmails(emails, options) {
451
461
  validateBatchSize(emails);
462
+ if (options?.dryRun === true) {
463
+ return this.runCoreProductDryRun(
464
+ "api/v1/verify-email",
465
+ emails.map((email) => ({ email, skip_cache: options.skipCache })),
466
+ options.idempotencyKey
467
+ );
468
+ }
452
469
  const startedAt = Date.now();
453
470
  const round = await this.runCoreBatchRound(
454
471
  "api/v1/verify-email",
@@ -469,6 +486,7 @@ var Signaliz = class {
469
486
  async enrichCompanySignals(params) {
470
487
  const request = companySignalRequestBody(params);
471
488
  let data = await this.client.post("api/v1/company-signals", request);
489
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
472
490
  if (params.waitForResult !== false && data.run_id && isPendingSignalResponse(data)) {
473
491
  const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
474
492
  const startedAt = Date.now();
@@ -499,6 +517,13 @@ var Signaliz = class {
499
517
  }
500
518
  async enrichCompanies(companies, options) {
501
519
  validateBatchSize(companies);
520
+ if (options?.dryRun === true) {
521
+ return this.runCoreProductDryRun(
522
+ "api/v1/company-signals",
523
+ companies.map(companySignalRequestBody),
524
+ options.idempotencyKey
525
+ );
526
+ }
502
527
  const startedAt = Date.now();
503
528
  const results = new Array(companies.length);
504
529
  const initialTasks = companies.map((params, index) => ({
@@ -576,6 +601,7 @@ var Signaliz = class {
576
601
  validateSignalToCopyParams(params);
577
602
  const request = signalToCopyRequestBody(params);
578
603
  let data = await this.client.post("api/v1/signal-to-copy", request);
604
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
579
605
  if (params.waitForResult !== false && (data.signal_run_id || data.run_id) && isPendingSignalResponse(data)) {
580
606
  const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
581
607
  const startedAt = Date.now();
@@ -594,6 +620,13 @@ var Signaliz = class {
594
620
  async createSignalCopyBatch(requests, options) {
595
621
  validateBatchSize(requests);
596
622
  requests.forEach(validateSignalToCopyParams);
623
+ if (options?.dryRun === true) {
624
+ return this.runCoreProductDryRun(
625
+ "api/v1/signal-to-copy",
626
+ requests.map(signalToCopyRequestBody),
627
+ options.idempotencyKey
628
+ );
629
+ }
597
630
  const startedAt = Date.now();
598
631
  const deduplicated = dedupeExactBatchItems(requests, (params) => JSON.stringify({
599
632
  request: signalToCopyRequestBody(params),
@@ -620,6 +653,17 @@ var Signaliz = class {
620
653
  results: compactedResults
621
654
  };
622
655
  }
656
+ async runCoreProductDryRun(path, requests, idempotencyKey) {
657
+ const data = await this.client.post(path, compact({
658
+ requests,
659
+ dry_run: true,
660
+ idempotency_key: idempotencyKey
661
+ }));
662
+ if (!isCoreProductDryRun(data)) {
663
+ throw new Error(`${path} dry run returned a live-result contract`);
664
+ }
665
+ return normalizeCoreProductDryRunResult(data);
666
+ }
623
667
  async runSignalCopyBatchChunks(uniqueRequests, options) {
624
668
  const chunks = [];
625
669
  for (let offset = 0; offset < uniqueRequests.length; offset += 25) {
@@ -978,9 +1022,34 @@ function findEmailRequestBody(params) {
978
1022
  last_name: params.lastName,
979
1023
  linkedin_url: params.linkedinUrl,
980
1024
  company_name: params.companyName,
981
- skip_cache: params.skipCache
1025
+ skip_cache: params.skipCache,
1026
+ dry_run: params.dryRun,
1027
+ idempotency_key: params.idempotencyKey
982
1028
  });
983
1029
  }
1030
+ function isCoreProductDryRun(data) {
1031
+ return data.dry_run === true && data.status === "planned";
1032
+ }
1033
+ function normalizeCoreProductDryRunResult(data) {
1034
+ const estimatedCredits = data.estimated_credits && typeof data.estimated_credits === "object" ? data.estimated_credits : { min: 0, max: 0 };
1035
+ return {
1036
+ success: true,
1037
+ dryRun: true,
1038
+ status: "planned",
1039
+ capability: String(data.capability || ""),
1040
+ inputCount: Number(data.input_count || 0),
1041
+ recoveryReadCount: Number(data.recovery_read_count || 0),
1042
+ plan: data.plan && typeof data.plan === "object" ? data.plan : {},
1043
+ estimate: data.estimate && typeof data.estimate === "object" ? data.estimate : {},
1044
+ estimatedCredits: {
1045
+ min: Number(estimatedCredits.min || 0),
1046
+ max: Number(estimatedCredits.max || 0)
1047
+ },
1048
+ creditsCharged: 0,
1049
+ sideEffects: Array.isArray(data.side_effects) ? data.side_effects : [],
1050
+ raw: data
1051
+ };
1052
+ }
984
1053
  function normalizeFindEmailResult(data) {
985
1054
  const email = typeof data.email === "string" && data.email.trim() ? data.email.trim() : null;
986
1055
  const found = Boolean(email) && data.found !== false;
@@ -1049,7 +1118,9 @@ function companySignalRequestBody(params) {
1049
1118
  // REST always returns a resumable run instead of holding the connection;
1050
1119
  // waitForResult controls the SDK polling loop.
1051
1120
  wait_for_result: false,
1052
- max_wait_ms: params.maxWaitMs
1121
+ max_wait_ms: params.maxWaitMs,
1122
+ dry_run: params.dryRun,
1123
+ idempotency_key: params.idempotencyKey
1053
1124
  });
1054
1125
  }
1055
1126
  function companySignalRecoverableBatchOptions(companies, tasks) {
@@ -1221,7 +1292,9 @@ function signalToCopyRequestBody(params) {
1221
1292
  research_prompt: params.researchPrompt,
1222
1293
  signal_run_id: params.signalRunId,
1223
1294
  skip_cache: params.skipCache,
1224
- enable_deep_search: params.enableDeepSearch
1295
+ enable_deep_search: params.enableDeepSearch,
1296
+ dry_run: params.dryRun,
1297
+ idempotency_key: params.idempotencyKey
1225
1298
  });
1226
1299
  }
1227
1300
  function validateSignalToCopyParams(params) {
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  Signaliz,
3
3
  SignalizError
4
- } from "./chunk-4LXMT3S5.mjs";
4
+ } from "./chunk-KTWDTUCI.mjs";
5
5
  export {
6
6
  Signaliz,
7
7
  SignalizError
@@ -409,10 +409,17 @@ var Signaliz = class {
409
409
  }
410
410
  async findEmail(params) {
411
411
  const data = await this.client.post("api/v1/find-email", findEmailRequestBody(params));
412
- return normalizeFindEmailResult(data);
412
+ return isCoreProductDryRun(data) ? normalizeCoreProductDryRunResult(data) : normalizeFindEmailResult(data);
413
413
  }
414
414
  async findEmails(params, options) {
415
415
  validateBatchSize(params);
416
+ if (options?.dryRun === true) {
417
+ return this.runCoreProductDryRun(
418
+ "api/v1/find-email",
419
+ params.map(findEmailRequestBody),
420
+ options.idempotencyKey
421
+ );
422
+ }
416
423
  const startedAt = Date.now();
417
424
  const round = await this.runCoreBatchRound(
418
425
  "api/v1/find-email",
@@ -431,9 +438,12 @@ var Signaliz = class {
431
438
  const request = compact({
432
439
  email: email || void 0,
433
440
  verification_run_id: options?.verificationRunId,
434
- skip_cache: options?.skipCache
441
+ skip_cache: options?.skipCache,
442
+ dry_run: options?.dryRun,
443
+ idempotency_key: options?.idempotencyKey
435
444
  });
436
445
  let data = await this.client.post("api/v1/verify-email", request);
446
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
437
447
  if (options?.waitForResult !== false && isPendingSignalResponse(data) && data.verification_run_id) {
438
448
  const maxWaitMs = Math.max(1e3, options?.maxWaitMs ?? 10 * 6e4);
439
449
  const startedAt = Date.now();
@@ -453,6 +463,13 @@ var Signaliz = class {
453
463
  }
454
464
  async verifyEmails(emails, options) {
455
465
  validateBatchSize(emails);
466
+ if (options?.dryRun === true) {
467
+ return this.runCoreProductDryRun(
468
+ "api/v1/verify-email",
469
+ emails.map((email) => ({ email, skip_cache: options.skipCache })),
470
+ options.idempotencyKey
471
+ );
472
+ }
456
473
  const startedAt = Date.now();
457
474
  const round = await this.runCoreBatchRound(
458
475
  "api/v1/verify-email",
@@ -473,6 +490,7 @@ var Signaliz = class {
473
490
  async enrichCompanySignals(params) {
474
491
  const request = companySignalRequestBody(params);
475
492
  let data = await this.client.post("api/v1/company-signals", request);
493
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
476
494
  if (params.waitForResult !== false && data.run_id && isPendingSignalResponse(data)) {
477
495
  const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
478
496
  const startedAt = Date.now();
@@ -503,6 +521,13 @@ var Signaliz = class {
503
521
  }
504
522
  async enrichCompanies(companies, options) {
505
523
  validateBatchSize(companies);
524
+ if (options?.dryRun === true) {
525
+ return this.runCoreProductDryRun(
526
+ "api/v1/company-signals",
527
+ companies.map(companySignalRequestBody),
528
+ options.idempotencyKey
529
+ );
530
+ }
506
531
  const startedAt = Date.now();
507
532
  const results = new Array(companies.length);
508
533
  const initialTasks = companies.map((params, index) => ({
@@ -580,6 +605,7 @@ var Signaliz = class {
580
605
  validateSignalToCopyParams(params);
581
606
  const request = signalToCopyRequestBody(params);
582
607
  let data = await this.client.post("api/v1/signal-to-copy", request);
608
+ if (isCoreProductDryRun(data)) return normalizeCoreProductDryRunResult(data);
583
609
  if (params.waitForResult !== false && (data.signal_run_id || data.run_id) && isPendingSignalResponse(data)) {
584
610
  const maxWaitMs = Math.max(1e3, params.maxWaitMs ?? 20 * 6e4);
585
611
  const startedAt = Date.now();
@@ -598,6 +624,13 @@ var Signaliz = class {
598
624
  async createSignalCopyBatch(requests, options) {
599
625
  validateBatchSize(requests);
600
626
  requests.forEach(validateSignalToCopyParams);
627
+ if (options?.dryRun === true) {
628
+ return this.runCoreProductDryRun(
629
+ "api/v1/signal-to-copy",
630
+ requests.map(signalToCopyRequestBody),
631
+ options.idempotencyKey
632
+ );
633
+ }
601
634
  const startedAt = Date.now();
602
635
  const deduplicated = dedupeExactBatchItems(requests, (params) => JSON.stringify({
603
636
  request: signalToCopyRequestBody(params),
@@ -624,6 +657,17 @@ var Signaliz = class {
624
657
  results: compactedResults
625
658
  };
626
659
  }
660
+ async runCoreProductDryRun(path2, requests, idempotencyKey) {
661
+ const data = await this.client.post(path2, compact({
662
+ requests,
663
+ dry_run: true,
664
+ idempotency_key: idempotencyKey
665
+ }));
666
+ if (!isCoreProductDryRun(data)) {
667
+ throw new Error(`${path2} dry run returned a live-result contract`);
668
+ }
669
+ return normalizeCoreProductDryRunResult(data);
670
+ }
627
671
  async runSignalCopyBatchChunks(uniqueRequests, options) {
628
672
  const chunks = [];
629
673
  for (let offset = 0; offset < uniqueRequests.length; offset += 25) {
@@ -982,9 +1026,34 @@ function findEmailRequestBody(params) {
982
1026
  last_name: params.lastName,
983
1027
  linkedin_url: params.linkedinUrl,
984
1028
  company_name: params.companyName,
985
- skip_cache: params.skipCache
1029
+ skip_cache: params.skipCache,
1030
+ dry_run: params.dryRun,
1031
+ idempotency_key: params.idempotencyKey
986
1032
  });
987
1033
  }
1034
+ function isCoreProductDryRun(data) {
1035
+ return data.dry_run === true && data.status === "planned";
1036
+ }
1037
+ function normalizeCoreProductDryRunResult(data) {
1038
+ const estimatedCredits = data.estimated_credits && typeof data.estimated_credits === "object" ? data.estimated_credits : { min: 0, max: 0 };
1039
+ return {
1040
+ success: true,
1041
+ dryRun: true,
1042
+ status: "planned",
1043
+ capability: String(data.capability || ""),
1044
+ inputCount: Number(data.input_count || 0),
1045
+ recoveryReadCount: Number(data.recovery_read_count || 0),
1046
+ plan: data.plan && typeof data.plan === "object" ? data.plan : {},
1047
+ estimate: data.estimate && typeof data.estimate === "object" ? data.estimate : {},
1048
+ estimatedCredits: {
1049
+ min: Number(estimatedCredits.min || 0),
1050
+ max: Number(estimatedCredits.max || 0)
1051
+ },
1052
+ creditsCharged: 0,
1053
+ sideEffects: Array.isArray(data.side_effects) ? data.side_effects : [],
1054
+ raw: data
1055
+ };
1056
+ }
988
1057
  function normalizeFindEmailResult(data) {
989
1058
  const email = typeof data.email === "string" && data.email.trim() ? data.email.trim() : null;
990
1059
  const found = Boolean(email) && data.found !== false;
@@ -1053,7 +1122,9 @@ function companySignalRequestBody(params) {
1053
1122
  // REST always returns a resumable run instead of holding the connection;
1054
1123
  // waitForResult controls the SDK polling loop.
1055
1124
  wait_for_result: false,
1056
- max_wait_ms: params.maxWaitMs
1125
+ max_wait_ms: params.maxWaitMs,
1126
+ dry_run: params.dryRun,
1127
+ idempotency_key: params.idempotencyKey
1057
1128
  });
1058
1129
  }
1059
1130
  function companySignalRecoverableBatchOptions(companies, tasks) {
@@ -1225,7 +1296,9 @@ function signalToCopyRequestBody(params) {
1225
1296
  research_prompt: params.researchPrompt,
1226
1297
  signal_run_id: params.signalRunId,
1227
1298
  skip_cache: params.skipCache,
1228
- enable_deep_search: params.enableDeepSearch
1299
+ enable_deep_search: params.enableDeepSearch,
1300
+ dry_run: params.dryRun,
1301
+ idempotency_key: params.idempotencyKey
1229
1302
  });
1230
1303
  }
1231
1304
  function validateSignalToCopyParams(params) {
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  Signaliz
4
- } from "./chunk-4LXMT3S5.mjs";
4
+ } from "./chunk-KTWDTUCI.mjs";
5
5
 
6
6
  // src/mcp-config.ts
7
7
  import * as fs from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signaliz/sdk",
3
- "version": "1.0.46",
3
+ "version": "1.0.47",
4
4
  "description": "Signaliz SDK for Find Email, Verify Email, Company Signal Enrichment, and Signal to Copy AI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",