@pcreative/commerce-contract 1.3.2 → 1.3.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pcreative/commerce-contract",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "Contrato de datos de commerce: los tipos que consume un tema y los adaptadores que los resuelven. Sin dependencias ni SDK del backend.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "type": "module",
@@ -225,6 +225,7 @@ export function createCommerce({
225
225
  if (params.q) qs.set("q", String(params.q))
226
226
  if (params.category) qs.set("categoria_handle", params.category)
227
227
  if (params.categoryId) qs.set("categoria", params.categoryId)
228
+ if (params.type) qs.set("tipo", params.type)
228
229
  if (params.ids?.length) qs.set("ids", params.ids.join(","))
229
230
  if (ORDEN_DEL_CONTRATO[params.sort]) qs.set("orden", ORDEN_DEL_CONTRATO[params.sort])
230
231
  const r = await api(`/tienda/productos?${qs}`)
@@ -593,6 +594,22 @@ export function createCommerce({
593
594
  throw e
594
595
  }
595
596
  },
597
+ async getLicenses(orderId) {
598
+ try {
599
+ const { licencias } = await api(`/tienda/pedidos/${encodeURIComponent(orderId)}/licencias`)
600
+ return (licencias ?? []).map((l) => ({
601
+ key: l.key,
602
+ status: l.status,
603
+ title: l.title ?? null,
604
+ sites: Number(l.sites ?? 0),
605
+ limit: Number(l.limit ?? 1),
606
+ supportedUntil: l.supportedUntil ? String(l.supportedUntil).slice(0, 10) : null,
607
+ }))
608
+ } catch (e) {
609
+ if (e.status === 404) return []
610
+ throw e
611
+ }
612
+ },
596
613
  async getCodes(orderId) {
597
614
  try {
598
615
  const { codigos } = await api(`/tienda/pedidos/${encodeURIComponent(orderId)}/codigos`)
@@ -609,6 +626,54 @@ export function createCommerce({
609
626
  )
610
627
  return codigo ?? null
611
628
  },
629
+ newsletter: {
630
+ async subscribe(email, consent = {}) {
631
+ await api("/tienda/boletin", {
632
+ method: "POST",
633
+ body: {
634
+ email,
635
+ texto: consent.text,
636
+ version: consent.version,
637
+ idioma: consent.locale,
638
+ origen: consent.source,
639
+ ip: consent.ip,
640
+ navegador: consent.userAgent,
641
+ },
642
+ })
643
+ return { status: "pendiente" }
644
+ },
645
+ async confirm(token) {
646
+ try {
647
+ await api("/tienda/boletin/confirmar", { method: "POST", body: { token } })
648
+ return true
649
+ } catch (e) {
650
+ if (e.status === 400) return false
651
+ throw e
652
+ }
653
+ },
654
+ async unsubscribe(token) {
655
+ await api("/tienda/boletin/baja", { method: "POST", body: { token } })
656
+ return true
657
+ },
658
+ },
659
+ async applyAsAuthor(a) {
660
+ const vende = [...new Set((a.sells ?? []).filter((x) => x === "tema" || x === "extension"))]
661
+ const r = await api("/tienda/autores/solicitudes", {
662
+ method: "POST",
663
+ body: {
664
+ nombre: a.name,
665
+ email: a.email,
666
+ portafolio: a.portfolio,
667
+ vende: vende.length === 2 ? ["los-dos"] : vende,
668
+ slug: a.handle,
669
+ pais: a.country,
670
+ web: a.website,
671
+ stacks: a.stacks,
672
+ experiencia: a.experience,
673
+ },
674
+ })
675
+ return { id: r.id }
676
+ },
612
677
  async getAuthor(handle) {
613
678
  try {
614
679
  const { autor } = await api(`/tienda/autores/${encodeURIComponent(handle)}`)
package/src/index.d.ts CHANGED
@@ -98,6 +98,24 @@ export interface BundleComponent {
98
98
  * ensena `hint` (los ultimos caracteres) y `revealed` dice si ya se destapo,
99
99
  * que es lo que cuenta como entregado.
100
100
  */
101
+ /**
102
+ * La licencia de una pieza del mercado comprada en un pedido. La clave es la
103
+ * credencial con la que el comprador activa el tema o la extensión en su sitio
104
+ * y con la que abre soporte con el autor: por eso se enseña entera.
105
+ */
106
+ export interface License {
107
+ key: string
108
+ status: "activa" | "caducada" | "anulada"
109
+ /** Nombre del producto al que da derecho. */
110
+ title: string | null
111
+ /** Sitios donde está activada ahora mismo. */
112
+ sites: number
113
+ /** Cuántos sitios admite. */
114
+ limit: number
115
+ /** Hasta cuándo incluye soporte y versiones nuevas (AAAA-MM-DD). null: sin fecha. */
116
+ supportedUntil: string | null
117
+ }
118
+
101
119
  export interface ProductCode {
102
120
  id: string
103
121
  lineId: string
@@ -119,6 +137,9 @@ export interface ProductCode {
119
137
  * Lo que anade un producto que viene del mercado de temas y extensiones:
120
138
  * version, cuando se actualizo, demo y changelog. Es lo que mira quien compra
121
139
  * software y lo que un producto normal no tiene.
140
+ *
141
+ * En los listados llega un resumen: `screenshots` y `changelog` vienen vacíos
142
+ * y se rellenan en `getProduct`, que es donde se enseñan.
122
143
  */
123
144
  export interface MarketInfo {
124
145
  type: "tema" | "extension"
@@ -131,6 +152,11 @@ export interface MarketInfo {
131
152
  demoUrl: string | null
132
153
  screenshots: string[]
133
154
  changelog: { version: string; date: string | null; notes: string | null }[]
155
+ /**
156
+ * Meses de soporte del autor que incluye la compra (0: sin soporte). Las
157
+ * versiones nuevas no tienen fecha: le llegan al comprador siempre.
158
+ */
159
+ supportMonths?: number
134
160
  }
135
161
 
136
162
  export interface Download {
@@ -479,6 +505,11 @@ export interface ListProductsParams {
479
505
  categoryId?: string
480
506
  ids?: string[]
481
507
  tags?: string[]
508
+ /**
509
+ * Solo piezas del mercado de ese tipo. Sin él salen todos los productos,
510
+ * sean o no del mercado. Un adaptador sin mercado lo ignora.
511
+ */
512
+ type?: "tema" | "extension"
482
513
  limit?: number
483
514
  offset?: number
484
515
  sort?: SortProductos
@@ -538,6 +569,23 @@ export interface Author {
538
569
  support: AuthorSupport | null
539
570
  }
540
571
 
572
+ /** Lo que manda quien quiere vender en el mercado. Lo revisa una persona. */
573
+ export interface AuthorApplication {
574
+ /** Nombre con el que publicará. */
575
+ name: string
576
+ email: string
577
+ /** Enlace a algo que haya hecho: sin eso no hay nada que revisar. */
578
+ portfolio: string
579
+ sells: ("tema" | "extension")[]
580
+ /** Identificador público; si falta, sale del nombre. */
581
+ handle?: string
582
+ /** Código de dos letras. */
583
+ country?: string
584
+ website?: string
585
+ stacks?: string[]
586
+ experience?: string
587
+ }
588
+
541
589
  export interface SupportMessage {
542
590
  from: "buyer" | "author" | "store"
543
591
  text: string
@@ -574,6 +622,8 @@ export interface CommerceClient {
574
622
  subirFichero?(archivo: File): Promise<{ id: string; nombre: string; tipo: string; bytes: number; firma: string }>
575
623
  /** Opcional: las descargas de un pedido con contenido digital. */
576
624
  getDownloads?(orderId: string): Promise<Download[]>
625
+ /** Opcional: las licencias de las piezas del mercado compradas en un pedido. */
626
+ getLicenses?(orderId: string): Promise<License[]>
577
627
  /** Los codigos de un pedido, tapados. */
578
628
  getCodes?(orderId: string): Promise<ProductCode[]>
579
629
  /** Destapa uno y devuelve el codigo entero. Queda apuntado quien y cuando. */
@@ -582,6 +632,34 @@ export interface CommerceClient {
582
632
  getWithdrawal?(orderId: string): Promise<WithdrawalState | null>
583
633
  /** Opcional: solicita el desistimiento de un pedido (botón obligatorio en la UE). */
584
634
  requestWithdrawal?(orderId: string, datos?: { lineas?: string[]; motivo?: string }): Promise<{ solicitud: string; aceptadas: number }>
635
+ /**
636
+ * Opcional: pedir vender en el mercado. Devuelve el id de la solicitud; la
637
+ * cuenta se crea cuando alguien la acepta. Si el correo ya pidió, falla con
638
+ * `err.status` 400 y el motivo en `err.detalle`.
639
+ */
640
+ applyAsAuthor?(application: AuthorApplication): Promise<{ id: string }>
641
+ /**
642
+ * Opcional: el boletín, con doble confirmación. `subscribe` NO apunta a nadie:
643
+ * manda un correo con un enlace, y solo al pulsarlo (`confirm`) queda dentro.
644
+ * Contesta siempre lo mismo para que no sirva para averiguar quién está.
645
+ */
646
+ newsletter?: {
647
+ subscribe(
648
+ email: string,
649
+ consent: {
650
+ /** El texto EXACTO que vio la persona junto a la casilla. Es la prueba. */
651
+ text: string
652
+ /** Versión de ese texto: cambia cuando cambia el texto. */
653
+ version: string
654
+ locale?: string
655
+ source?: string
656
+ ip?: string
657
+ userAgent?: string
658
+ },
659
+ ): Promise<{ status: "pendiente" }>
660
+ confirm(token: string): Promise<boolean>
661
+ unsubscribe(token: string): Promise<boolean>
662
+ }
585
663
  /** Opcional: la ficha pública de un autor del mercado. */
586
664
  getAuthor?(handle: string): Promise<Author | null>
587
665