@easybits.cloud/mailmask 0.4.1 → 0.4.3

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/dist/index.cjs CHANGED
@@ -44,6 +44,14 @@ async function request(baseUrl, apiKey, path, opts, doFetch = fetch) {
44
44
  }
45
45
  return res.json();
46
46
  }
47
+ async function requestRaw(baseUrl, apiKey, path, doFetch = fetch) {
48
+ const res = await doFetch(`${baseUrl}${path}`, { headers: { "Authorization": `Bearer ${apiKey}` } });
49
+ if (!res.ok) {
50
+ const body = await res.json().catch(() => ({ error: res.statusText }));
51
+ throw new MailMaskError(res.status, body.error || res.statusText);
52
+ }
53
+ return res;
54
+ }
47
55
  var MailMask = class {
48
56
  constructor(config) {
49
57
  this.apiKey = config.apiKey;
@@ -51,7 +59,7 @@ var MailMask = class {
51
59
  const doFetch = config.fetch ? config.fetch : fetch;
52
60
  const req = (path, opts) => request(this.baseUrl, this.apiKey, path, opts, doFetch);
53
61
  this.domains = new DomainsResource(req);
54
- this.aliases = new AliasesResource(req);
62
+ this.aliases = new AliasesResource(req, (path) => requestRaw(this.baseUrl, this.apiKey, path, doFetch));
55
63
  this.rules = new RulesResource(req);
56
64
  this.logs = new LogsResource(req);
57
65
  this.send = new SendResource(req);
@@ -61,6 +69,13 @@ var MailMask = class {
61
69
  this.smtp = new SmtpResource(req);
62
70
  this.apiKeys = new ApiKeysResource(req);
63
71
  this.dns = new DnsResource(req);
72
+ this.billing = new BillingResource(req);
73
+ this.registrations = new RegistrationsResource(req);
74
+ this.transfers = new TransfersResource(req);
75
+ this.members = new MembersResource(req);
76
+ this.signature = new SignatureResource(req);
77
+ this.canned = new CannedResource(req);
78
+ this.account = new AccountResource(req);
64
79
  }
65
80
  };
66
81
  var DomainsResource = class {
@@ -85,6 +100,10 @@ var DomainsResource = class {
85
100
  verify(id) {
86
101
  return this.req(`/api/domains/${id}/verify`, { method: "POST" });
87
102
  }
103
+ /** Registros a pegar en el registrador. Con `live` los compara con el DNS público y deduce el panel. */
104
+ dnsSetup(id, opts) {
105
+ return this.req(`/api/domains/${id}/dns-setup${opts?.live ? "?live=1" : ""}`);
106
+ }
88
107
  };
89
108
  var DnsResource = class {
90
109
  constructor(req) {
@@ -114,8 +133,17 @@ var DnsResource = class {
114
133
  }
115
134
  };
116
135
  var AliasesResource = class {
117
- constructor(req) {
136
+ constructor(req, raw) {
118
137
  this.req = req;
138
+ this.raw = raw;
139
+ }
140
+ /** Perfil de configuración de Apple Mail (plist) para el buzón de una máscara. */
141
+ async appleProfile(domainId, alias) {
142
+ return (await this.raw(`/api/domains/${domainId}/apple-profile?alias=${encodeURIComponent(alias)}`)).text();
143
+ }
144
+ /** Exporta el buzón en formato mbox. Devuelve la respuesta en streaming: un buzón puede pesar GB. */
145
+ exportMbox(domainId, alias) {
146
+ return this.raw(`/api/domains/${domainId}/alias/${alias}/mailbox/export`);
119
147
  }
120
148
  list(domainId) {
121
149
  return this.req(`/api/domains/${domainId}/alias`);
@@ -263,6 +291,141 @@ var ApiKeysResource = class {
263
291
  return this.req(`/api/api-keys/${id}`, { method: "DELETE" });
264
292
  }
265
293
  };
294
+ var BillingResource = class {
295
+ constructor(req) {
296
+ this.req = req;
297
+ }
298
+ status() {
299
+ return this.req("/api/billing/status");
300
+ }
301
+ addons() {
302
+ return this.req("/api/addons");
303
+ }
304
+ /**
305
+ * Liga de MercadoPago para un add-on de un dominio (`domain` = activarlo, $99/mes).
306
+ * El usuario la abre y paga; hasta entonces no cambia nada.
307
+ */
308
+ checkout(domainId, kind = "domain", opts) {
309
+ return this.req("/api/addons/checkout", { method: "POST", body: JSON.stringify({ kind, domainId, payerEmail: opts?.payerEmail }) });
310
+ }
311
+ };
312
+ var RegistrationsResource = class {
313
+ constructor(req) {
314
+ this.req = req;
315
+ }
316
+ search(domain) {
317
+ return this.req(`/api/domains/search?q=${encodeURIComponent(domain)}`);
318
+ }
319
+ tlds() {
320
+ return this.req("/api/domains/tlds");
321
+ }
322
+ /** Crea el registro pendiente y devuelve la liga de pago; el dominio se registra al pagar. */
323
+ register(domain) {
324
+ return this.req("/api/domains/register", { method: "POST", body: JSON.stringify({ domain }) });
325
+ }
326
+ list() {
327
+ return this.req("/api/domains/registrations");
328
+ }
329
+ /** Pide el traslado a otro registrador. El código EPP llega por correo al dueño, nunca en la respuesta. */
330
+ transferOut(regId) {
331
+ return this.req(`/api/domains/registrations/${regId}/transfer-out`, { method: "POST" });
332
+ }
333
+ /** Liga de MercadoPago para la suscripción de renovación anual. */
334
+ renewal(regId, opts) {
335
+ return this.req(`/api/domains/registrations/${regId}/renewal`, { method: "POST", body: JSON.stringify({ payerEmail: opts?.payerEmail }) });
336
+ }
337
+ };
338
+ var TransfersResource = class {
339
+ constructor(req) {
340
+ this.req = req;
341
+ }
342
+ /** Requisitos, precio e inventario del DNS actual. No cobra ni crea nada. */
343
+ check(domain) {
344
+ return this.req("/api/domains/transfer/check", { method: "POST", body: JSON.stringify({ domain }) });
345
+ }
346
+ dns(regId) {
347
+ return this.req(`/api/domains/transfer/${regId}/dns`);
348
+ }
349
+ /** Reemplaza el inventario completo (RRSets). Vuelve a quedar pendiente de aprobar. */
350
+ setDns(regId, records) {
351
+ return this.req(`/api/domains/transfer/${regId}/dns`, { method: "PUT", body: JSON.stringify({ records }) });
352
+ }
353
+ approveDns(regId) {
354
+ return this.req(`/api/domains/transfer/${regId}/dns/approve`, { method: "POST" });
355
+ }
356
+ resendEmail(regId) {
357
+ return this.req(`/api/domains/transfer/${regId}/resend-email`, { method: "POST" });
358
+ }
359
+ };
360
+ var MembersResource = class {
361
+ constructor(req) {
362
+ this.req = req;
363
+ }
364
+ list(domainId) {
365
+ return this.req(`/api/domains/${domainId}/agents`);
366
+ }
367
+ invite(domainId, input) {
368
+ return this.req(`/api/domains/${domainId}/agents/invite`, { method: "POST", body: JSON.stringify(input) });
369
+ }
370
+ remove(domainId, memberId) {
371
+ return this.req(`/api/domains/${domainId}/agents/${memberId}`, { method: "DELETE" });
372
+ }
373
+ cancelInvite(domainId, token) {
374
+ return this.req(`/api/domains/${domainId}/agents/invites/${token}`, { method: "DELETE" });
375
+ }
376
+ };
377
+ var SignatureResource = class {
378
+ constructor(req) {
379
+ this.req = req;
380
+ }
381
+ async get(domainId) {
382
+ const d = await this.req(`/api/domains/${domainId}`);
383
+ return { signature: d.signature ?? null };
384
+ }
385
+ /** Markdown, máx. 2000 caracteres. Cadena vacía la borra. */
386
+ set(domainId, signature) {
387
+ return this.req(`/api/domains/${domainId}/signature`, { method: "PUT", body: JSON.stringify({ signature }) });
388
+ }
389
+ };
390
+ var CannedResource = class {
391
+ constructor(req) {
392
+ this.req = req;
393
+ }
394
+ list(domainId) {
395
+ return this.req(`/api/domains/${domainId}/canned`);
396
+ }
397
+ create(domainId, input) {
398
+ return this.req(`/api/domains/${domainId}/canned`, { method: "POST", body: JSON.stringify(input) });
399
+ }
400
+ delete(domainId, cannedId) {
401
+ return this.req(`/api/domains/${domainId}/canned/${cannedId}`, { method: "DELETE" });
402
+ }
403
+ };
404
+ var AccountResource = class {
405
+ constructor(req) {
406
+ this.req = req;
407
+ }
408
+ getProfile() {
409
+ return this.req("/api/profile");
410
+ }
411
+ /** Nombre visible (máx. 60 caracteres). Cadena vacía lo borra. */
412
+ updateProfile(input) {
413
+ return this.req("/api/profile", { method: "PUT", body: JSON.stringify(input) });
414
+ }
415
+ /** Foto desde un adjunto que el usuario subió al asistente (URL firmada de `/api/asistente/files/*`). */
416
+ setAvatarFromUrl(url) {
417
+ return this.req("/api/profile/avatar", { method: "POST", body: JSON.stringify({ fromUrl: url }) });
418
+ }
419
+ /** Foto desde bytes (PNG, JPG o WebP; máx. 2 MB). */
420
+ setAvatar(file, filename = "avatar") {
421
+ const form = new FormData();
422
+ form.append("file", file, filename);
423
+ return this.req("/api/profile/avatar", { method: "POST", body: form });
424
+ }
425
+ removeAvatar() {
426
+ return this.req("/api/profile/avatar", { method: "DELETE" });
427
+ }
428
+ };
266
429
 
267
430
  // src/verify.ts
268
431
  function hex(buf) {
package/dist/index.d.cts CHANGED
@@ -354,6 +354,173 @@ interface DnsChangeResult {
354
354
  propagacion: string;
355
355
  }
356
356
  type DnsPreset = "vercel" | "netlify" | "github-pages" | "cloudflare-pages" | "render" | "fly" | "redirect-a-www" | "dmarc";
357
+ interface DnsSetupRecord {
358
+ id: string;
359
+ type: "MX" | "TXT" | "CNAME";
360
+ /** Relativo al dominio, como lo piden casi todos los paneles ('@', '_amazonses'). */
361
+ name: string;
362
+ fqdn: string;
363
+ value: string;
364
+ /** Sólo MX, para paneles con campo de prioridad aparte (entonces el valor es `host`). */
365
+ priority?: number;
366
+ host?: string;
367
+ level: "requerido" | "recomendado" | "opcional";
368
+ purpose: string;
369
+ benefit?: string;
370
+ /** Ayuda en texto con **negritas** estilo markdown. */
371
+ hints: string[];
372
+ /** Sólo con `live`: si el DNS público ya lo tiene; null = no se pudo consultar. */
373
+ ok?: boolean | null;
374
+ observed?: string[];
375
+ /** SPF: valor fusionado cuando ya existe otro SPF (se edita ése, no se crea otro). */
376
+ suggestedValue?: string;
377
+ }
378
+ interface DnsSetup {
379
+ domain: string;
380
+ records: DnsSetupRecord[];
381
+ live: boolean;
382
+ nameservers?: string[];
383
+ /** Panel donde se pegan, deducido de los nameservers. */
384
+ registrarHint?: {
385
+ provider: string;
386
+ label: string;
387
+ note: string;
388
+ } | null;
389
+ summary?: string;
390
+ }
391
+ interface BillingStatus {
392
+ subscription: {
393
+ plan: string;
394
+ status: string;
395
+ currentPeriodEnd?: string;
396
+ [k: string]: unknown;
397
+ };
398
+ }
399
+ interface Addon {
400
+ id: string;
401
+ kind: string;
402
+ /** Dominio al que aplica; sin él es un add-on legado de toda la cuenta. */
403
+ domainId?: string;
404
+ status: "pending" | "active" | "cancelled" | "expired";
405
+ priceCents: number;
406
+ currentPeriodEnd?: string;
407
+ createdAt: string;
408
+ cancelledAt?: string;
409
+ source: "purchase" | "courtesy" | "migration";
410
+ }
411
+ interface AddonsResponse {
412
+ catalog: Record<string, {
413
+ price: number;
414
+ label: string;
415
+ }>;
416
+ forSale: string[];
417
+ mine: Addon[];
418
+ }
419
+ /** Liga de pago de MercadoPago. Nada cambia hasta que el usuario la abre y paga. */
420
+ interface CheckoutLink {
421
+ init_point: string;
422
+ addonId: string;
423
+ }
424
+ interface DomainSearchResult {
425
+ available: boolean;
426
+ domain: string;
427
+ tld: string;
428
+ /** Centavos MXN por año. */
429
+ price: number;
430
+ currency: "MXN";
431
+ }
432
+ interface TldPrice {
433
+ tld: string;
434
+ /** Centavos MXN. */
435
+ price: number;
436
+ renewPrice: number;
437
+ transferPrice: number;
438
+ popular: boolean;
439
+ }
440
+ interface DomainRegistrationCreated {
441
+ /** Liga de pago de MercadoPago; el registro arranca al pagar. */
442
+ initPoint: string;
443
+ registrationId: string;
444
+ }
445
+ interface DomainRegistration {
446
+ id: string;
447
+ domainId: string | null;
448
+ domainName: string;
449
+ kind: "register" | "transfer";
450
+ status: string;
451
+ expiresAt: string | null;
452
+ priceCents: number;
453
+ renewalStatus: string;
454
+ renewalPriceCents: number | null;
455
+ nextChargeAt: string | null;
456
+ dnsImportStatus: string;
457
+ transferAuthCodeHint: string | null;
458
+ lastError: string | null;
459
+ createdAt: string;
460
+ [k: string]: unknown;
461
+ }
462
+ interface TransferRequirement {
463
+ texto: string;
464
+ ok: boolean | null;
465
+ ayuda?: string;
466
+ }
467
+ interface TransferCheck {
468
+ domain: string;
469
+ /** Centavos MXN; incluye un año de renovación. */
470
+ price: number;
471
+ currency: "MXN";
472
+ requisitos: TransferRequirement[];
473
+ dns: {
474
+ found: unknown[];
475
+ nameservers?: string[];
476
+ warning?: string;
477
+ truncado?: boolean;
478
+ };
479
+ [k: string]: unknown;
480
+ }
481
+ interface TransferDnsInventory {
482
+ records: unknown[];
483
+ status: string;
484
+ takenAt: string | null;
485
+ }
486
+ interface RenewalLink {
487
+ init_point: string;
488
+ nextChargeAt: string;
489
+ }
490
+ interface DomainMember {
491
+ id: string;
492
+ domainId: string;
493
+ email: string;
494
+ name: string;
495
+ role: "admin" | "agent";
496
+ createdAt: string;
497
+ /** Del perfil de su cuenta de MailMask, si lo llenó. */
498
+ displayName?: string | null;
499
+ avatarUrl?: string | null;
500
+ }
501
+ interface DomainInvite {
502
+ token: string;
503
+ email: string;
504
+ name: string;
505
+ role: "admin" | "agent";
506
+ expiresAt: string;
507
+ inviteUrl: string;
508
+ }
509
+ interface CannedReply {
510
+ id: string;
511
+ domainId: string;
512
+ title: string;
513
+ /** Markdown. */
514
+ body: string;
515
+ createdAt: string;
516
+ }
517
+ /** Perfil de la cuenta de MailMask (el usuario, no una máscara). */
518
+ interface AccountProfile {
519
+ email: string;
520
+ displayName: string | null;
521
+ /** Ruta relativa al host de MailMask (`/api/avatar/...`), o null sin foto. */
522
+ avatarUrl: string | null;
523
+ }
357
524
 
358
525
  declare class MailMaskError extends Error {
359
526
  status: number;
@@ -373,6 +540,13 @@ declare class MailMask {
373
540
  smtp: SmtpResource;
374
541
  apiKeys: ApiKeysResource;
375
542
  dns: DnsResource;
543
+ billing: BillingResource;
544
+ registrations: RegistrationsResource;
545
+ transfers: TransfersResource;
546
+ members: MembersResource;
547
+ signature: SignatureResource;
548
+ canned: CannedResource;
549
+ account: AccountResource;
376
550
  constructor(config: MailMaskConfig);
377
551
  }
378
552
  type Req = <T>(path: string, opts?: RequestInit) => Promise<T>;
@@ -387,6 +561,10 @@ declare class DomainsResource {
387
561
  }>;
388
562
  health(id: string): Promise<Record<string, unknown>>;
389
563
  verify(id: string): Promise<DomainVerification>;
564
+ /** Registros a pegar en el registrador. Con `live` los compara con el DNS público y deduce el panel. */
565
+ dnsSetup(id: string, opts?: {
566
+ live?: boolean;
567
+ }): Promise<DnsSetup>;
390
568
  }
391
569
  declare class DnsResource {
392
570
  private req;
@@ -410,7 +588,12 @@ declare class DnsResource {
410
588
  }
411
589
  declare class AliasesResource {
412
590
  private req;
413
- constructor(req: Req);
591
+ private raw;
592
+ constructor(req: Req, raw: (path: string) => Promise<Response>);
593
+ /** Perfil de configuración de Apple Mail (plist) para el buzón de una máscara. */
594
+ appleProfile(domainId: string, alias: string): Promise<string>;
595
+ /** Exporta el buzón en formato mbox. Devuelve la respuesta en streaming: un buzón puede pesar GB. */
596
+ exportMbox(domainId: string, alias: string): Promise<Response>;
414
597
  list(domainId: string): Promise<Alias[]>;
415
598
  create(domainId: string, input: CreateAliasInput): Promise<AliasCreated>;
416
599
  /** Crea un buzón IMAP para una máscara existente. La contraseña sólo se devuelve aquí. */
@@ -508,6 +691,125 @@ declare class ApiKeysResource {
508
691
  ok: boolean;
509
692
  }>;
510
693
  }
694
+ declare class BillingResource {
695
+ private req;
696
+ constructor(req: Req);
697
+ status(): Promise<BillingStatus>;
698
+ addons(): Promise<AddonsResponse>;
699
+ /**
700
+ * Liga de MercadoPago para un add-on de un dominio (`domain` = activarlo, $99/mes).
701
+ * El usuario la abre y paga; hasta entonces no cambia nada.
702
+ */
703
+ checkout(domainId: string, kind?: "domain" | "storage50" | "sends100", opts?: {
704
+ payerEmail?: string;
705
+ }): Promise<CheckoutLink>;
706
+ }
707
+ declare class RegistrationsResource {
708
+ private req;
709
+ constructor(req: Req);
710
+ search(domain: string): Promise<DomainSearchResult>;
711
+ tlds(): Promise<TldPrice[]>;
712
+ /** Crea el registro pendiente y devuelve la liga de pago; el dominio se registra al pagar. */
713
+ register(domain: string): Promise<DomainRegistrationCreated>;
714
+ list(): Promise<DomainRegistration[]>;
715
+ /** Pide el traslado a otro registrador. El código EPP llega por correo al dueño, nunca en la respuesta. */
716
+ transferOut(regId: string): Promise<{
717
+ ok: boolean;
718
+ aviso: string;
719
+ }>;
720
+ /** Liga de MercadoPago para la suscripción de renovación anual. */
721
+ renewal(regId: string, opts?: {
722
+ payerEmail?: string;
723
+ }): Promise<RenewalLink>;
724
+ }
725
+ declare class TransfersResource {
726
+ private req;
727
+ constructor(req: Req);
728
+ /** Requisitos, precio e inventario del DNS actual. No cobra ni crea nada. */
729
+ check(domain: string): Promise<TransferCheck>;
730
+ dns(regId: string): Promise<TransferDnsInventory>;
731
+ /** Reemplaza el inventario completo (RRSets). Vuelve a quedar pendiente de aprobar. */
732
+ setDns(regId: string, records: {
733
+ name: string;
734
+ type: string;
735
+ ttl?: number;
736
+ values: string[];
737
+ }[]): Promise<{
738
+ records: unknown[];
739
+ }>;
740
+ approveDns(regId: string): Promise<{
741
+ ok: boolean;
742
+ }>;
743
+ resendEmail(regId: string): Promise<{
744
+ ok: boolean;
745
+ }>;
746
+ }
747
+ declare class MembersResource {
748
+ private req;
749
+ constructor(req: Req);
750
+ list(domainId: string): Promise<{
751
+ members: DomainMember[];
752
+ invites: DomainInvite[];
753
+ }>;
754
+ invite(domainId: string, input: {
755
+ email: string;
756
+ name: string;
757
+ role?: "admin" | "agent";
758
+ }): Promise<{
759
+ ok: boolean;
760
+ inviteUrl: string;
761
+ }>;
762
+ remove(domainId: string, memberId: string): Promise<{
763
+ ok: boolean;
764
+ }>;
765
+ cancelInvite(domainId: string, token: string): Promise<{
766
+ ok: boolean;
767
+ }>;
768
+ }
769
+ declare class SignatureResource {
770
+ private req;
771
+ constructor(req: Req);
772
+ get(domainId: string): Promise<{
773
+ signature: string | null;
774
+ }>;
775
+ /** Markdown, máx. 2000 caracteres. Cadena vacía la borra. */
776
+ set(domainId: string, signature: string): Promise<{
777
+ ok: boolean;
778
+ signature: string | null;
779
+ }>;
780
+ }
781
+ declare class CannedResource {
782
+ private req;
783
+ constructor(req: Req);
784
+ list(domainId: string): Promise<CannedReply[]>;
785
+ create(domainId: string, input: {
786
+ title: string;
787
+ body: string;
788
+ }): Promise<CannedReply>;
789
+ delete(domainId: string, cannedId: string): Promise<{
790
+ ok: boolean;
791
+ }>;
792
+ }
793
+ declare class AccountResource {
794
+ private req;
795
+ constructor(req: Req);
796
+ getProfile(): Promise<AccountProfile>;
797
+ /** Nombre visible (máx. 60 caracteres). Cadena vacía lo borra. */
798
+ updateProfile(input: {
799
+ displayName: string | null;
800
+ }): Promise<AccountProfile>;
801
+ /** Foto desde un adjunto que el usuario subió al asistente (URL firmada de `/api/asistente/files/*`). */
802
+ setAvatarFromUrl(url: string): Promise<AccountProfile & {
803
+ ok: boolean;
804
+ }>;
805
+ /** Foto desde bytes (PNG, JPG o WebP; máx. 2 MB). */
806
+ setAvatar(file: Blob, filename?: string): Promise<AccountProfile & {
807
+ ok: boolean;
808
+ }>;
809
+ removeAvatar(): Promise<AccountProfile & {
810
+ ok: boolean;
811
+ }>;
812
+ }
511
813
 
512
814
  interface WebhookSignatureHeaders {
513
815
  /** Header `X-MailMask-Signature`, con forma `sha256=<hex>`. */
@@ -522,4 +824,4 @@ interface WebhookSignatureHeaders {
522
824
  */
523
825
  declare function verifyWebhookSignature(secret: string, headers: WebhookSignatureHeaders, rawBody: string, toleranceMs?: number): Promise<boolean>;
524
826
 
525
- export { type Alias, type AliasCreated, type ApiKey, type AttachmentRef, type BulkJob, type BulkJobCreated, type BulkSendInput, type CreateAliasInput, type CreateRuleInput, type CreateWebhookInput, type DnsChangeResult, type DnsDelegation, type DnsImportResult, type DnsListResponse, type DnsPreset, type DnsRRSet, type DnsRRSetAnotado, type DnsRecord, type DnsRecordType, type DnsZoneCreated, type DnsZoneState, type Domain, type DomainCreated, type DomainVerification, type EmailLog, MailMask, type MailMaskConfig, MailMaskError, type MailboxCreated, type Rule, type RuleAction, type RuleField, type RuleMatch, type SendEmailInput, type SendOptions, type SmtpCredential, type SmtpCredentialCreated, type Suppression, type UpdateAliasInput, type UpdateRuleInput, type UpdateWebhookInput, type UploadAttachmentInput, type UploadedAttachment, type Webhook, type WebhookCreated, type WebhookDelivery, type WebhookEvent, type WebhookPayload, type WebhookSignatureHeaders, verifyWebhookSignature };
827
+ export { type AccountProfile, type Addon, type AddonsResponse, type Alias, type AliasCreated, type ApiKey, type AttachmentRef, type BillingStatus, type BulkJob, type BulkJobCreated, type BulkSendInput, type CannedReply, type CheckoutLink, type CreateAliasInput, type CreateRuleInput, type CreateWebhookInput, type DnsChangeResult, type DnsDelegation, type DnsImportResult, type DnsListResponse, type DnsPreset, type DnsRRSet, type DnsRRSetAnotado, type DnsRecord, type DnsRecordType, type DnsSetup, type DnsSetupRecord, type DnsZoneCreated, type DnsZoneState, type Domain, type DomainCreated, type DomainInvite, type DomainMember, type DomainRegistration, type DomainRegistrationCreated, type DomainSearchResult, type DomainVerification, type EmailLog, MailMask, type MailMaskConfig, MailMaskError, type MailboxCreated, type RenewalLink, type Rule, type RuleAction, type RuleField, type RuleMatch, type SendEmailInput, type SendOptions, type SmtpCredential, type SmtpCredentialCreated, type Suppression, type TldPrice, type TransferCheck, type TransferDnsInventory, type TransferRequirement, type UpdateAliasInput, type UpdateRuleInput, type UpdateWebhookInput, type UploadAttachmentInput, type UploadedAttachment, type Webhook, type WebhookCreated, type WebhookDelivery, type WebhookEvent, type WebhookPayload, type WebhookSignatureHeaders, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -354,6 +354,173 @@ interface DnsChangeResult {
354
354
  propagacion: string;
355
355
  }
356
356
  type DnsPreset = "vercel" | "netlify" | "github-pages" | "cloudflare-pages" | "render" | "fly" | "redirect-a-www" | "dmarc";
357
+ interface DnsSetupRecord {
358
+ id: string;
359
+ type: "MX" | "TXT" | "CNAME";
360
+ /** Relativo al dominio, como lo piden casi todos los paneles ('@', '_amazonses'). */
361
+ name: string;
362
+ fqdn: string;
363
+ value: string;
364
+ /** Sólo MX, para paneles con campo de prioridad aparte (entonces el valor es `host`). */
365
+ priority?: number;
366
+ host?: string;
367
+ level: "requerido" | "recomendado" | "opcional";
368
+ purpose: string;
369
+ benefit?: string;
370
+ /** Ayuda en texto con **negritas** estilo markdown. */
371
+ hints: string[];
372
+ /** Sólo con `live`: si el DNS público ya lo tiene; null = no se pudo consultar. */
373
+ ok?: boolean | null;
374
+ observed?: string[];
375
+ /** SPF: valor fusionado cuando ya existe otro SPF (se edita ése, no se crea otro). */
376
+ suggestedValue?: string;
377
+ }
378
+ interface DnsSetup {
379
+ domain: string;
380
+ records: DnsSetupRecord[];
381
+ live: boolean;
382
+ nameservers?: string[];
383
+ /** Panel donde se pegan, deducido de los nameservers. */
384
+ registrarHint?: {
385
+ provider: string;
386
+ label: string;
387
+ note: string;
388
+ } | null;
389
+ summary?: string;
390
+ }
391
+ interface BillingStatus {
392
+ subscription: {
393
+ plan: string;
394
+ status: string;
395
+ currentPeriodEnd?: string;
396
+ [k: string]: unknown;
397
+ };
398
+ }
399
+ interface Addon {
400
+ id: string;
401
+ kind: string;
402
+ /** Dominio al que aplica; sin él es un add-on legado de toda la cuenta. */
403
+ domainId?: string;
404
+ status: "pending" | "active" | "cancelled" | "expired";
405
+ priceCents: number;
406
+ currentPeriodEnd?: string;
407
+ createdAt: string;
408
+ cancelledAt?: string;
409
+ source: "purchase" | "courtesy" | "migration";
410
+ }
411
+ interface AddonsResponse {
412
+ catalog: Record<string, {
413
+ price: number;
414
+ label: string;
415
+ }>;
416
+ forSale: string[];
417
+ mine: Addon[];
418
+ }
419
+ /** Liga de pago de MercadoPago. Nada cambia hasta que el usuario la abre y paga. */
420
+ interface CheckoutLink {
421
+ init_point: string;
422
+ addonId: string;
423
+ }
424
+ interface DomainSearchResult {
425
+ available: boolean;
426
+ domain: string;
427
+ tld: string;
428
+ /** Centavos MXN por año. */
429
+ price: number;
430
+ currency: "MXN";
431
+ }
432
+ interface TldPrice {
433
+ tld: string;
434
+ /** Centavos MXN. */
435
+ price: number;
436
+ renewPrice: number;
437
+ transferPrice: number;
438
+ popular: boolean;
439
+ }
440
+ interface DomainRegistrationCreated {
441
+ /** Liga de pago de MercadoPago; el registro arranca al pagar. */
442
+ initPoint: string;
443
+ registrationId: string;
444
+ }
445
+ interface DomainRegistration {
446
+ id: string;
447
+ domainId: string | null;
448
+ domainName: string;
449
+ kind: "register" | "transfer";
450
+ status: string;
451
+ expiresAt: string | null;
452
+ priceCents: number;
453
+ renewalStatus: string;
454
+ renewalPriceCents: number | null;
455
+ nextChargeAt: string | null;
456
+ dnsImportStatus: string;
457
+ transferAuthCodeHint: string | null;
458
+ lastError: string | null;
459
+ createdAt: string;
460
+ [k: string]: unknown;
461
+ }
462
+ interface TransferRequirement {
463
+ texto: string;
464
+ ok: boolean | null;
465
+ ayuda?: string;
466
+ }
467
+ interface TransferCheck {
468
+ domain: string;
469
+ /** Centavos MXN; incluye un año de renovación. */
470
+ price: number;
471
+ currency: "MXN";
472
+ requisitos: TransferRequirement[];
473
+ dns: {
474
+ found: unknown[];
475
+ nameservers?: string[];
476
+ warning?: string;
477
+ truncado?: boolean;
478
+ };
479
+ [k: string]: unknown;
480
+ }
481
+ interface TransferDnsInventory {
482
+ records: unknown[];
483
+ status: string;
484
+ takenAt: string | null;
485
+ }
486
+ interface RenewalLink {
487
+ init_point: string;
488
+ nextChargeAt: string;
489
+ }
490
+ interface DomainMember {
491
+ id: string;
492
+ domainId: string;
493
+ email: string;
494
+ name: string;
495
+ role: "admin" | "agent";
496
+ createdAt: string;
497
+ /** Del perfil de su cuenta de MailMask, si lo llenó. */
498
+ displayName?: string | null;
499
+ avatarUrl?: string | null;
500
+ }
501
+ interface DomainInvite {
502
+ token: string;
503
+ email: string;
504
+ name: string;
505
+ role: "admin" | "agent";
506
+ expiresAt: string;
507
+ inviteUrl: string;
508
+ }
509
+ interface CannedReply {
510
+ id: string;
511
+ domainId: string;
512
+ title: string;
513
+ /** Markdown. */
514
+ body: string;
515
+ createdAt: string;
516
+ }
517
+ /** Perfil de la cuenta de MailMask (el usuario, no una máscara). */
518
+ interface AccountProfile {
519
+ email: string;
520
+ displayName: string | null;
521
+ /** Ruta relativa al host de MailMask (`/api/avatar/...`), o null sin foto. */
522
+ avatarUrl: string | null;
523
+ }
357
524
 
358
525
  declare class MailMaskError extends Error {
359
526
  status: number;
@@ -373,6 +540,13 @@ declare class MailMask {
373
540
  smtp: SmtpResource;
374
541
  apiKeys: ApiKeysResource;
375
542
  dns: DnsResource;
543
+ billing: BillingResource;
544
+ registrations: RegistrationsResource;
545
+ transfers: TransfersResource;
546
+ members: MembersResource;
547
+ signature: SignatureResource;
548
+ canned: CannedResource;
549
+ account: AccountResource;
376
550
  constructor(config: MailMaskConfig);
377
551
  }
378
552
  type Req = <T>(path: string, opts?: RequestInit) => Promise<T>;
@@ -387,6 +561,10 @@ declare class DomainsResource {
387
561
  }>;
388
562
  health(id: string): Promise<Record<string, unknown>>;
389
563
  verify(id: string): Promise<DomainVerification>;
564
+ /** Registros a pegar en el registrador. Con `live` los compara con el DNS público y deduce el panel. */
565
+ dnsSetup(id: string, opts?: {
566
+ live?: boolean;
567
+ }): Promise<DnsSetup>;
390
568
  }
391
569
  declare class DnsResource {
392
570
  private req;
@@ -410,7 +588,12 @@ declare class DnsResource {
410
588
  }
411
589
  declare class AliasesResource {
412
590
  private req;
413
- constructor(req: Req);
591
+ private raw;
592
+ constructor(req: Req, raw: (path: string) => Promise<Response>);
593
+ /** Perfil de configuración de Apple Mail (plist) para el buzón de una máscara. */
594
+ appleProfile(domainId: string, alias: string): Promise<string>;
595
+ /** Exporta el buzón en formato mbox. Devuelve la respuesta en streaming: un buzón puede pesar GB. */
596
+ exportMbox(domainId: string, alias: string): Promise<Response>;
414
597
  list(domainId: string): Promise<Alias[]>;
415
598
  create(domainId: string, input: CreateAliasInput): Promise<AliasCreated>;
416
599
  /** Crea un buzón IMAP para una máscara existente. La contraseña sólo se devuelve aquí. */
@@ -508,6 +691,125 @@ declare class ApiKeysResource {
508
691
  ok: boolean;
509
692
  }>;
510
693
  }
694
+ declare class BillingResource {
695
+ private req;
696
+ constructor(req: Req);
697
+ status(): Promise<BillingStatus>;
698
+ addons(): Promise<AddonsResponse>;
699
+ /**
700
+ * Liga de MercadoPago para un add-on de un dominio (`domain` = activarlo, $99/mes).
701
+ * El usuario la abre y paga; hasta entonces no cambia nada.
702
+ */
703
+ checkout(domainId: string, kind?: "domain" | "storage50" | "sends100", opts?: {
704
+ payerEmail?: string;
705
+ }): Promise<CheckoutLink>;
706
+ }
707
+ declare class RegistrationsResource {
708
+ private req;
709
+ constructor(req: Req);
710
+ search(domain: string): Promise<DomainSearchResult>;
711
+ tlds(): Promise<TldPrice[]>;
712
+ /** Crea el registro pendiente y devuelve la liga de pago; el dominio se registra al pagar. */
713
+ register(domain: string): Promise<DomainRegistrationCreated>;
714
+ list(): Promise<DomainRegistration[]>;
715
+ /** Pide el traslado a otro registrador. El código EPP llega por correo al dueño, nunca en la respuesta. */
716
+ transferOut(regId: string): Promise<{
717
+ ok: boolean;
718
+ aviso: string;
719
+ }>;
720
+ /** Liga de MercadoPago para la suscripción de renovación anual. */
721
+ renewal(regId: string, opts?: {
722
+ payerEmail?: string;
723
+ }): Promise<RenewalLink>;
724
+ }
725
+ declare class TransfersResource {
726
+ private req;
727
+ constructor(req: Req);
728
+ /** Requisitos, precio e inventario del DNS actual. No cobra ni crea nada. */
729
+ check(domain: string): Promise<TransferCheck>;
730
+ dns(regId: string): Promise<TransferDnsInventory>;
731
+ /** Reemplaza el inventario completo (RRSets). Vuelve a quedar pendiente de aprobar. */
732
+ setDns(regId: string, records: {
733
+ name: string;
734
+ type: string;
735
+ ttl?: number;
736
+ values: string[];
737
+ }[]): Promise<{
738
+ records: unknown[];
739
+ }>;
740
+ approveDns(regId: string): Promise<{
741
+ ok: boolean;
742
+ }>;
743
+ resendEmail(regId: string): Promise<{
744
+ ok: boolean;
745
+ }>;
746
+ }
747
+ declare class MembersResource {
748
+ private req;
749
+ constructor(req: Req);
750
+ list(domainId: string): Promise<{
751
+ members: DomainMember[];
752
+ invites: DomainInvite[];
753
+ }>;
754
+ invite(domainId: string, input: {
755
+ email: string;
756
+ name: string;
757
+ role?: "admin" | "agent";
758
+ }): Promise<{
759
+ ok: boolean;
760
+ inviteUrl: string;
761
+ }>;
762
+ remove(domainId: string, memberId: string): Promise<{
763
+ ok: boolean;
764
+ }>;
765
+ cancelInvite(domainId: string, token: string): Promise<{
766
+ ok: boolean;
767
+ }>;
768
+ }
769
+ declare class SignatureResource {
770
+ private req;
771
+ constructor(req: Req);
772
+ get(domainId: string): Promise<{
773
+ signature: string | null;
774
+ }>;
775
+ /** Markdown, máx. 2000 caracteres. Cadena vacía la borra. */
776
+ set(domainId: string, signature: string): Promise<{
777
+ ok: boolean;
778
+ signature: string | null;
779
+ }>;
780
+ }
781
+ declare class CannedResource {
782
+ private req;
783
+ constructor(req: Req);
784
+ list(domainId: string): Promise<CannedReply[]>;
785
+ create(domainId: string, input: {
786
+ title: string;
787
+ body: string;
788
+ }): Promise<CannedReply>;
789
+ delete(domainId: string, cannedId: string): Promise<{
790
+ ok: boolean;
791
+ }>;
792
+ }
793
+ declare class AccountResource {
794
+ private req;
795
+ constructor(req: Req);
796
+ getProfile(): Promise<AccountProfile>;
797
+ /** Nombre visible (máx. 60 caracteres). Cadena vacía lo borra. */
798
+ updateProfile(input: {
799
+ displayName: string | null;
800
+ }): Promise<AccountProfile>;
801
+ /** Foto desde un adjunto que el usuario subió al asistente (URL firmada de `/api/asistente/files/*`). */
802
+ setAvatarFromUrl(url: string): Promise<AccountProfile & {
803
+ ok: boolean;
804
+ }>;
805
+ /** Foto desde bytes (PNG, JPG o WebP; máx. 2 MB). */
806
+ setAvatar(file: Blob, filename?: string): Promise<AccountProfile & {
807
+ ok: boolean;
808
+ }>;
809
+ removeAvatar(): Promise<AccountProfile & {
810
+ ok: boolean;
811
+ }>;
812
+ }
511
813
 
512
814
  interface WebhookSignatureHeaders {
513
815
  /** Header `X-MailMask-Signature`, con forma `sha256=<hex>`. */
@@ -522,4 +824,4 @@ interface WebhookSignatureHeaders {
522
824
  */
523
825
  declare function verifyWebhookSignature(secret: string, headers: WebhookSignatureHeaders, rawBody: string, toleranceMs?: number): Promise<boolean>;
524
826
 
525
- export { type Alias, type AliasCreated, type ApiKey, type AttachmentRef, type BulkJob, type BulkJobCreated, type BulkSendInput, type CreateAliasInput, type CreateRuleInput, type CreateWebhookInput, type DnsChangeResult, type DnsDelegation, type DnsImportResult, type DnsListResponse, type DnsPreset, type DnsRRSet, type DnsRRSetAnotado, type DnsRecord, type DnsRecordType, type DnsZoneCreated, type DnsZoneState, type Domain, type DomainCreated, type DomainVerification, type EmailLog, MailMask, type MailMaskConfig, MailMaskError, type MailboxCreated, type Rule, type RuleAction, type RuleField, type RuleMatch, type SendEmailInput, type SendOptions, type SmtpCredential, type SmtpCredentialCreated, type Suppression, type UpdateAliasInput, type UpdateRuleInput, type UpdateWebhookInput, type UploadAttachmentInput, type UploadedAttachment, type Webhook, type WebhookCreated, type WebhookDelivery, type WebhookEvent, type WebhookPayload, type WebhookSignatureHeaders, verifyWebhookSignature };
827
+ export { type AccountProfile, type Addon, type AddonsResponse, type Alias, type AliasCreated, type ApiKey, type AttachmentRef, type BillingStatus, type BulkJob, type BulkJobCreated, type BulkSendInput, type CannedReply, type CheckoutLink, type CreateAliasInput, type CreateRuleInput, type CreateWebhookInput, type DnsChangeResult, type DnsDelegation, type DnsImportResult, type DnsListResponse, type DnsPreset, type DnsRRSet, type DnsRRSetAnotado, type DnsRecord, type DnsRecordType, type DnsSetup, type DnsSetupRecord, type DnsZoneCreated, type DnsZoneState, type Domain, type DomainCreated, type DomainInvite, type DomainMember, type DomainRegistration, type DomainRegistrationCreated, type DomainSearchResult, type DomainVerification, type EmailLog, MailMask, type MailMaskConfig, MailMaskError, type MailboxCreated, type RenewalLink, type Rule, type RuleAction, type RuleField, type RuleMatch, type SendEmailInput, type SendOptions, type SmtpCredential, type SmtpCredentialCreated, type Suppression, type TldPrice, type TransferCheck, type TransferDnsInventory, type TransferRequirement, type UpdateAliasInput, type UpdateRuleInput, type UpdateWebhookInput, type UploadAttachmentInput, type UploadedAttachment, type Webhook, type WebhookCreated, type WebhookDelivery, type WebhookEvent, type WebhookPayload, type WebhookSignatureHeaders, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -16,6 +16,14 @@ async function request(baseUrl, apiKey, path, opts, doFetch = fetch) {
16
16
  }
17
17
  return res.json();
18
18
  }
19
+ async function requestRaw(baseUrl, apiKey, path, doFetch = fetch) {
20
+ const res = await doFetch(`${baseUrl}${path}`, { headers: { "Authorization": `Bearer ${apiKey}` } });
21
+ if (!res.ok) {
22
+ const body = await res.json().catch(() => ({ error: res.statusText }));
23
+ throw new MailMaskError(res.status, body.error || res.statusText);
24
+ }
25
+ return res;
26
+ }
19
27
  var MailMask = class {
20
28
  constructor(config) {
21
29
  this.apiKey = config.apiKey;
@@ -23,7 +31,7 @@ var MailMask = class {
23
31
  const doFetch = config.fetch ? config.fetch : fetch;
24
32
  const req = (path, opts) => request(this.baseUrl, this.apiKey, path, opts, doFetch);
25
33
  this.domains = new DomainsResource(req);
26
- this.aliases = new AliasesResource(req);
34
+ this.aliases = new AliasesResource(req, (path) => requestRaw(this.baseUrl, this.apiKey, path, doFetch));
27
35
  this.rules = new RulesResource(req);
28
36
  this.logs = new LogsResource(req);
29
37
  this.send = new SendResource(req);
@@ -33,6 +41,13 @@ var MailMask = class {
33
41
  this.smtp = new SmtpResource(req);
34
42
  this.apiKeys = new ApiKeysResource(req);
35
43
  this.dns = new DnsResource(req);
44
+ this.billing = new BillingResource(req);
45
+ this.registrations = new RegistrationsResource(req);
46
+ this.transfers = new TransfersResource(req);
47
+ this.members = new MembersResource(req);
48
+ this.signature = new SignatureResource(req);
49
+ this.canned = new CannedResource(req);
50
+ this.account = new AccountResource(req);
36
51
  }
37
52
  };
38
53
  var DomainsResource = class {
@@ -57,6 +72,10 @@ var DomainsResource = class {
57
72
  verify(id) {
58
73
  return this.req(`/api/domains/${id}/verify`, { method: "POST" });
59
74
  }
75
+ /** Registros a pegar en el registrador. Con `live` los compara con el DNS público y deduce el panel. */
76
+ dnsSetup(id, opts) {
77
+ return this.req(`/api/domains/${id}/dns-setup${opts?.live ? "?live=1" : ""}`);
78
+ }
60
79
  };
61
80
  var DnsResource = class {
62
81
  constructor(req) {
@@ -86,8 +105,17 @@ var DnsResource = class {
86
105
  }
87
106
  };
88
107
  var AliasesResource = class {
89
- constructor(req) {
108
+ constructor(req, raw) {
90
109
  this.req = req;
110
+ this.raw = raw;
111
+ }
112
+ /** Perfil de configuración de Apple Mail (plist) para el buzón de una máscara. */
113
+ async appleProfile(domainId, alias) {
114
+ return (await this.raw(`/api/domains/${domainId}/apple-profile?alias=${encodeURIComponent(alias)}`)).text();
115
+ }
116
+ /** Exporta el buzón en formato mbox. Devuelve la respuesta en streaming: un buzón puede pesar GB. */
117
+ exportMbox(domainId, alias) {
118
+ return this.raw(`/api/domains/${domainId}/alias/${alias}/mailbox/export`);
91
119
  }
92
120
  list(domainId) {
93
121
  return this.req(`/api/domains/${domainId}/alias`);
@@ -235,6 +263,141 @@ var ApiKeysResource = class {
235
263
  return this.req(`/api/api-keys/${id}`, { method: "DELETE" });
236
264
  }
237
265
  };
266
+ var BillingResource = class {
267
+ constructor(req) {
268
+ this.req = req;
269
+ }
270
+ status() {
271
+ return this.req("/api/billing/status");
272
+ }
273
+ addons() {
274
+ return this.req("/api/addons");
275
+ }
276
+ /**
277
+ * Liga de MercadoPago para un add-on de un dominio (`domain` = activarlo, $99/mes).
278
+ * El usuario la abre y paga; hasta entonces no cambia nada.
279
+ */
280
+ checkout(domainId, kind = "domain", opts) {
281
+ return this.req("/api/addons/checkout", { method: "POST", body: JSON.stringify({ kind, domainId, payerEmail: opts?.payerEmail }) });
282
+ }
283
+ };
284
+ var RegistrationsResource = class {
285
+ constructor(req) {
286
+ this.req = req;
287
+ }
288
+ search(domain) {
289
+ return this.req(`/api/domains/search?q=${encodeURIComponent(domain)}`);
290
+ }
291
+ tlds() {
292
+ return this.req("/api/domains/tlds");
293
+ }
294
+ /** Crea el registro pendiente y devuelve la liga de pago; el dominio se registra al pagar. */
295
+ register(domain) {
296
+ return this.req("/api/domains/register", { method: "POST", body: JSON.stringify({ domain }) });
297
+ }
298
+ list() {
299
+ return this.req("/api/domains/registrations");
300
+ }
301
+ /** Pide el traslado a otro registrador. El código EPP llega por correo al dueño, nunca en la respuesta. */
302
+ transferOut(regId) {
303
+ return this.req(`/api/domains/registrations/${regId}/transfer-out`, { method: "POST" });
304
+ }
305
+ /** Liga de MercadoPago para la suscripción de renovación anual. */
306
+ renewal(regId, opts) {
307
+ return this.req(`/api/domains/registrations/${regId}/renewal`, { method: "POST", body: JSON.stringify({ payerEmail: opts?.payerEmail }) });
308
+ }
309
+ };
310
+ var TransfersResource = class {
311
+ constructor(req) {
312
+ this.req = req;
313
+ }
314
+ /** Requisitos, precio e inventario del DNS actual. No cobra ni crea nada. */
315
+ check(domain) {
316
+ return this.req("/api/domains/transfer/check", { method: "POST", body: JSON.stringify({ domain }) });
317
+ }
318
+ dns(regId) {
319
+ return this.req(`/api/domains/transfer/${regId}/dns`);
320
+ }
321
+ /** Reemplaza el inventario completo (RRSets). Vuelve a quedar pendiente de aprobar. */
322
+ setDns(regId, records) {
323
+ return this.req(`/api/domains/transfer/${regId}/dns`, { method: "PUT", body: JSON.stringify({ records }) });
324
+ }
325
+ approveDns(regId) {
326
+ return this.req(`/api/domains/transfer/${regId}/dns/approve`, { method: "POST" });
327
+ }
328
+ resendEmail(regId) {
329
+ return this.req(`/api/domains/transfer/${regId}/resend-email`, { method: "POST" });
330
+ }
331
+ };
332
+ var MembersResource = class {
333
+ constructor(req) {
334
+ this.req = req;
335
+ }
336
+ list(domainId) {
337
+ return this.req(`/api/domains/${domainId}/agents`);
338
+ }
339
+ invite(domainId, input) {
340
+ return this.req(`/api/domains/${domainId}/agents/invite`, { method: "POST", body: JSON.stringify(input) });
341
+ }
342
+ remove(domainId, memberId) {
343
+ return this.req(`/api/domains/${domainId}/agents/${memberId}`, { method: "DELETE" });
344
+ }
345
+ cancelInvite(domainId, token) {
346
+ return this.req(`/api/domains/${domainId}/agents/invites/${token}`, { method: "DELETE" });
347
+ }
348
+ };
349
+ var SignatureResource = class {
350
+ constructor(req) {
351
+ this.req = req;
352
+ }
353
+ async get(domainId) {
354
+ const d = await this.req(`/api/domains/${domainId}`);
355
+ return { signature: d.signature ?? null };
356
+ }
357
+ /** Markdown, máx. 2000 caracteres. Cadena vacía la borra. */
358
+ set(domainId, signature) {
359
+ return this.req(`/api/domains/${domainId}/signature`, { method: "PUT", body: JSON.stringify({ signature }) });
360
+ }
361
+ };
362
+ var CannedResource = class {
363
+ constructor(req) {
364
+ this.req = req;
365
+ }
366
+ list(domainId) {
367
+ return this.req(`/api/domains/${domainId}/canned`);
368
+ }
369
+ create(domainId, input) {
370
+ return this.req(`/api/domains/${domainId}/canned`, { method: "POST", body: JSON.stringify(input) });
371
+ }
372
+ delete(domainId, cannedId) {
373
+ return this.req(`/api/domains/${domainId}/canned/${cannedId}`, { method: "DELETE" });
374
+ }
375
+ };
376
+ var AccountResource = class {
377
+ constructor(req) {
378
+ this.req = req;
379
+ }
380
+ getProfile() {
381
+ return this.req("/api/profile");
382
+ }
383
+ /** Nombre visible (máx. 60 caracteres). Cadena vacía lo borra. */
384
+ updateProfile(input) {
385
+ return this.req("/api/profile", { method: "PUT", body: JSON.stringify(input) });
386
+ }
387
+ /** Foto desde un adjunto que el usuario subió al asistente (URL firmada de `/api/asistente/files/*`). */
388
+ setAvatarFromUrl(url) {
389
+ return this.req("/api/profile/avatar", { method: "POST", body: JSON.stringify({ fromUrl: url }) });
390
+ }
391
+ /** Foto desde bytes (PNG, JPG o WebP; máx. 2 MB). */
392
+ setAvatar(file, filename = "avatar") {
393
+ const form = new FormData();
394
+ form.append("file", file, filename);
395
+ return this.req("/api/profile/avatar", { method: "POST", body: form });
396
+ }
397
+ removeAvatar() {
398
+ return this.req("/api/profile/avatar", { method: "DELETE" });
399
+ }
400
+ };
238
401
 
239
402
  // src/verify.ts
240
403
  function hex(buf) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@easybits.cloud/mailmask",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "description": "Official SDK for the MailMask email alias/forwarding API",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",