primcli 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -322,8 +322,8 @@ const checkForExistence = (options, name) => {
322
322
  if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) return true;
323
323
  return false;
324
324
  };
325
- const setAuthParams = async ({ security, ...options }) => {
326
- for (const auth of security) {
325
+ async function setAuthParams(options) {
326
+ for (const auth of options.security ?? []) {
327
327
  if (checkForExistence(options, auth.name)) continue;
328
328
  const token = await getAuthToken(auth, options.auth);
329
329
  if (!token) continue;
@@ -341,7 +341,7 @@ const setAuthParams = async ({ security, ...options }) => {
341
341
  break;
342
342
  }
343
343
  }
344
- };
344
+ }
345
345
  const buildUrl = (options) => getUrl({
346
346
  baseUrl: options.baseUrl,
347
347
  path: options.path,
@@ -448,10 +448,7 @@ const createClient = (config = {}) => {
448
448
  headers: mergeHeaders(_config.headers, options.headers),
449
449
  serializedBody: void 0
450
450
  };
451
- if (opts.security) await setAuthParams({
452
- ...opts,
453
- security: opts.security
454
- });
451
+ if (opts.security) await setAuthParams(opts);
455
452
  if (opts.requestValidator) await opts.requestValidator(opts);
456
453
  if (opts.body !== void 0 && opts.bodySerializer) opts.serializedBody = opts.bodySerializer(opts.body);
457
454
  if (opts.body === void 0 || opts.serializedBody === "") opts.headers.delete("Content-Type");
@@ -462,100 +459,95 @@ const createClient = (config = {}) => {
462
459
  };
463
460
  };
464
461
  const request = async (options) => {
465
- const { opts, url } = await beforeRequest(options);
466
- const requestInit = {
467
- redirect: "follow",
468
- ...opts,
469
- body: getValidRequestBody(opts)
470
- };
471
- let request = new Request(url, requestInit);
472
- for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
473
- const _fetch = opts.fetch;
462
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
463
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
464
+ let request;
474
465
  let response;
475
466
  try {
467
+ const { opts, url } = await beforeRequest(options);
468
+ const requestInit = {
469
+ redirect: "follow",
470
+ ...opts,
471
+ body: getValidRequestBody(opts)
472
+ };
473
+ request = new Request(url, requestInit);
474
+ for (const fn of interceptors.request.fns) if (fn) request = await fn(request, opts);
475
+ const _fetch = opts.fetch;
476
476
  response = await _fetch(request);
477
- } catch (error) {
478
- let finalError = error;
479
- for (const fn of interceptors.error.fns) if (fn) finalError = await fn(error, void 0, request, opts);
480
- finalError = finalError || {};
481
- if (opts.throwOnError) throw finalError;
482
- return opts.responseStyle === "data" ? void 0 : {
483
- error: finalError,
477
+ for (const fn of interceptors.response.fns) if (fn) response = await fn(response, request, opts);
478
+ const result = {
484
479
  request,
485
- response: void 0
480
+ response
486
481
  };
487
- }
488
- for (const fn of interceptors.response.fns) if (fn) response = await fn(response, request, opts);
489
- const result = {
490
- request,
491
- response
492
- };
493
- if (response.ok) {
494
- const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
495
- if (response.status === 204 || response.headers.get("Content-Length") === "0") {
496
- let emptyData;
482
+ if (response.ok) {
483
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
484
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
485
+ let emptyData;
486
+ switch (parseAs) {
487
+ case "arrayBuffer":
488
+ case "blob":
489
+ case "text":
490
+ emptyData = await response[parseAs]();
491
+ break;
492
+ case "formData":
493
+ emptyData = new FormData();
494
+ break;
495
+ case "stream":
496
+ emptyData = response.body;
497
+ break;
498
+ default:
499
+ emptyData = {};
500
+ break;
501
+ }
502
+ return opts.responseStyle === "data" ? emptyData : {
503
+ data: emptyData,
504
+ ...result
505
+ };
506
+ }
507
+ let data;
497
508
  switch (parseAs) {
498
509
  case "arrayBuffer":
499
510
  case "blob":
500
- case "text":
501
- emptyData = await response[parseAs]();
502
- break;
503
511
  case "formData":
504
- emptyData = new FormData();
505
- break;
506
- case "stream":
507
- emptyData = response.body;
512
+ case "text":
513
+ data = await response[parseAs]();
508
514
  break;
509
- default:
510
- emptyData = {};
515
+ case "json": {
516
+ const text = await response.text();
517
+ data = text ? JSON.parse(text) : {};
511
518
  break;
519
+ }
520
+ case "stream": return opts.responseStyle === "data" ? response.body : {
521
+ data: response.body,
522
+ ...result
523
+ };
512
524
  }
513
- return opts.responseStyle === "data" ? emptyData : {
514
- data: emptyData,
515
- ...result
516
- };
517
- }
518
- let data;
519
- switch (parseAs) {
520
- case "arrayBuffer":
521
- case "blob":
522
- case "formData":
523
- case "text":
524
- data = await response[parseAs]();
525
- break;
526
- case "json": {
527
- const text = await response.text();
528
- data = text ? JSON.parse(text) : {};
529
- break;
525
+ if (parseAs === "json") {
526
+ if (opts.responseValidator) await opts.responseValidator(data);
527
+ if (opts.responseTransformer) data = await opts.responseTransformer(data);
530
528
  }
531
- case "stream": return opts.responseStyle === "data" ? response.body : {
532
- data: response.body,
529
+ return opts.responseStyle === "data" ? data : {
530
+ data,
533
531
  ...result
534
532
  };
535
533
  }
536
- if (parseAs === "json") {
537
- if (opts.responseValidator) await opts.responseValidator(data);
538
- if (opts.responseTransformer) data = await opts.responseTransformer(data);
539
- }
540
- return opts.responseStyle === "data" ? data : {
541
- data,
542
- ...result
534
+ const textError = await response.text();
535
+ let jsonError;
536
+ try {
537
+ jsonError = JSON.parse(textError);
538
+ } catch {}
539
+ throw jsonError ?? textError;
540
+ } catch (error) {
541
+ let finalError = error;
542
+ for (const fn of interceptors.error.fns) if (fn) finalError = await fn(finalError, response, request, options);
543
+ finalError = finalError || {};
544
+ if (throwOnError) throw finalError;
545
+ return responseStyle === "data" ? void 0 : {
546
+ error: finalError,
547
+ request,
548
+ response
543
549
  };
544
550
  }
545
- const textError = await response.text();
546
- let jsonError;
547
- try {
548
- jsonError = JSON.parse(textError);
549
- } catch {}
550
- const error = jsonError ?? textError;
551
- let finalError = error;
552
- for (const fn of interceptors.error.fns) if (fn) finalError = await fn(error, response, request, opts);
553
- finalError = finalError || {};
554
- if (opts.throwOnError) throw finalError;
555
- return opts.responseStyle === "data" ? void 0 : {
556
- error: finalError,
557
- ...result
558
- };
559
551
  };
560
552
  const makeMethodFn = (method) => (options) => request({
561
553
  ...options,
@@ -566,7 +558,6 @@ const createClient = (config = {}) => {
566
558
  return createSseClient({
567
559
  ...opts,
568
560
  body: opts.body,
569
- headers: opts.headers,
570
561
  method,
571
562
  onRequest: async (url, init) => {
572
563
  let request = new Request(url, init);
@@ -1,4 +1,4 @@
1
- import { A as saveActiveChatState, C as resolveCliAuth, D as deleteChatState, E as chatStatePath, M as createClient, N as createConfig, O as loadActiveChatState, S as normalizeApiBaseUrl, T as saveSignupCredentials, _ as deleteCliCredentials, a as normalizeCliEnvironmentName, b as hasStoredCliLogin, c as resolveConfigEnvironment, d as validateCliHeaderName, f as validateCliHeaderValue, g as credentialsPath, h as credentialsLockPath, i as loadCliConfig, j as PrimitiveApiClient, k as loadChatConversationByLocalId, l as saveCliConfig, m as cliAccessTokenExpiresAt, n as deleteCliConfig, o as redactCliEnvironment, p as acquireCliCredentialsLock, r as emptyCliConfig, s as removeCliEnvironment, u as upsertCliEnvironment, v as deleteCliCredentialsLock, w as saveCliCredentials, x as loadCliCredentials, y as detectPrimitiveKeyEnvMisname } from "../cli-config-C-7V83Qd.js";
1
+ import { A as saveActiveChatState, C as resolveCliAuth, D as deleteChatState, E as chatStatePath, M as createClient, N as createConfig, O as loadActiveChatState, S as normalizeApiBaseUrl, T as saveSignupCredentials, _ as deleteCliCredentials, a as normalizeCliEnvironmentName, b as hasStoredCliLogin, c as resolveConfigEnvironment, d as validateCliHeaderName, f as validateCliHeaderValue, g as credentialsPath, h as credentialsLockPath, i as loadCliConfig, j as PrimitiveApiClient, k as loadChatConversationByLocalId, l as saveCliConfig, m as cliAccessTokenExpiresAt, n as deleteCliConfig, o as redactCliEnvironment, p as acquireCliCredentialsLock, r as emptyCliConfig, s as removeCliEnvironment, u as upsertCliEnvironment, v as deleteCliCredentialsLock, w as saveCliCredentials, x as loadCliCredentials, y as detectPrimitiveKeyEnvMisname } from "../cli-config-BKso8oJu.js";
2
2
  import { Args, Command, Errors, Flags, ux } from "@oclif/core";
3
3
  import { chmodSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, rmSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
4
4
  import { randomUUID } from "node:crypto";
@@ -26567,8 +26567,8 @@ const PRIMITIVE_TEAM_AUTHOR = {
26567
26567
  name: "Primitive Team",
26568
26568
  url: "https://primitive.dev"
26569
26569
  };
26570
- const SDK_VERSION_RANGE = "^1.18.0";
26571
- const CLI_VERSION_RANGE = "^1.18.0";
26570
+ const SDK_VERSION_RANGE = "^1.19.0";
26571
+ const CLI_VERSION_RANGE = "^1.19.0";
26572
26572
  const ESBUILD_VERSION_RANGE = "^0.27.0";
26573
26573
  function renderHandler() {
26574
26574
  return `// env.PRIMITIVE_API_KEY, env.PRIMITIVE_WEBHOOK_SECRET, and
@@ -26670,6 +26670,14 @@ function inboundRecipientDomains(event: EmailReceivedEvent): Set<string> {
26670
26670
  // - Track Message-ID / In-Reply-To chains to break ping-pong loops
26671
26671
  // between two cooperating handlers on different domains.
26672
26672
  // - Rate-limit replies per sender per hour as a safety net.
26673
+ //
26674
+ // Loop protection is NOT sender authentication. The address matching
26675
+ // here is deliberately loose (it exists to avoid replying to our own
26676
+ // mail, where a false positive just drops one reply). If your handler
26677
+ // gates any privileged action on WHO sent the email, do not reuse this
26678
+ // logic or regex the From header yourself; use isTrustedSender from
26679
+ // "@primitivedotdev/sdk/api", which anchors the DMARC verdict to your
26680
+ // expected domain and strict-parses the From header.
26673
26681
  export function isLoop(event: EmailReceivedEvent): boolean {
26674
26682
  // RFC 5321: bounce notifications use the null MAIL FROM (envelope
26675
26683
  // sender = empty string). Some MTAs report this as "<>" verbatim.
@@ -1,4 +1,4 @@
1
- import { S as normalizeApiBaseUrl, c as resolveConfigEnvironment, i as loadCliConfig } from "../cli-config-C-7V83Qd.js";
1
+ import { S as normalizeApiBaseUrl, c as resolveConfigEnvironment, i as loadCliConfig } from "../cli-config-BKso8oJu.js";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
3
  import { join } from "node:path";
4
4
  import { homedir } from "node:os";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "primcli",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "Official Primitive CLI: deploy Primitive Functions, send and inspect mail, manage endpoints, all from the terminal. Wraps the @primitivedotdev/sdk runtime client with one-shot commands.",
5
5
  "type": "module",
6
6
  "sideEffects": false,