@colis/react
Le retrait dans votre propre application.
La page de livraison est une façon de remettre un travail. Si vos clients se connectent déjà à un espace à vous, les hooks y apportent le même envoi et le même retrait : un champ fichier, un champ de code qui répare les fautes, un téléchargement. Le SDK AWS reste sur votre serveur.
import { ColisProvider } from '@colis/react'
export default function Providers({ children }) {
return <ColisProvider baseUrl="/api/transfers">{children}</ColisProvider>
}Pas encore sur npm : les paquets se construisent depuis le dépôt en attendant leur publication.
01Envoi
Un champ fichier, un code.
sendFile() prend un File directement depuis un champ, avec son nom et son type. Les échecs arrivent dans error plutôt qu’en rejet : un gestionnaire d’événement ne devrait pas avoir besoin d’un try/catch.
import { useSendTransfer } from '@colis/react'
function SendDeliverable() {
const { sendFile, transfer, isPending, error } = useSendTransfer()
return (
<>
<input
type="file"
disabled={isPending}
onChange={(event) => event.target.files?.[0] && sendFile(event.target.files[0])}
/>
{transfer && <p>Send your client this code: {transfer.code}</p>}
{error && <p>{error.message}</p>}
</>
)
}Le hook poste vers les routes de transfert de votre serveur, qui détiennent les identifiants du bucket. Le navigateur ne voit jamais une clé, et votre fonction authorize décide qui peut envoyer.
transfer porte le code, la taille et l’expiration. Affichez le code par groupes de quatre ; la réception l’accepte avec ou sans espaces.
02Retrait
Chercher, montrer, puis télécharger.
load() récupère ce que contient un code sans déplacer les octets : le client voit un nom et une taille avant tout téléchargement. loadBytes() rapatrie le fichier.
import { useReceiveTransfer, useSyncCodeInput } from '@colis/react'
function ClientPickup() {
const input = useSyncCodeInput()
const { load, loadBytes, transfer, notFound, isPending } = useReceiveTransfer()
async function download() {
const bytes = await loadBytes(input.code!)
if (bytes) saveToDisk(new Blob([bytes]), transfer?.filename ?? 'file') // your helper
}
return (
<>
<input {...input.inputProps} placeholder="K7QP 2M4X" />
<button onClick={() => load(input.code!)} disabled={!input.isComplete || isPending}>
Find my delivery
</button>
{notFound && <p>Unknown or expired code.</p>}
{transfer?.kind === 'file' && (
<button onClick={download}>
Download {transfer.filename} · {transfer.size} bytes
</button>
)}
</>
)
}L’accusé de réception et les deux réponses sont des routes propres à la page de livraison, pas aux hooks : postez vous-même vers /:code/opened et /:code/verdict, ou envoyez vos clients sur la page.
03Le champ de code
Ce que le client a tapé reste intact.
useSyncCodeInput répare dans le navigateur, avant toute requête. Réécrire le champ sous le curseur est précisément ce qui rend ces champs pénibles : il ne le fait jamais.
Complet. Séparateurs retirés, casse unifiée, et O, I et L lus comme 0, 1 et 1, puisque la base32 de Crockford n’a ni O, ni I, ni L avec lesquels les confondre.
Alphabet 0123456789ABCDEFGHJKMNPQRSTVWXYZ · 8 caractères · 40 bits
value est le texte tel quel. code est la forme canonique à envoyer, null tant que la saisie ne peut pas en être un. isComplete indique quand activer le bouton.
inputProps porte les indications de clavier et d’auto-remplissage qu’attend un code à usage unique : autoComplete="one-time-code", majuscules, pas de correction automatique, et un pavé numérique quand l’alphabet n’a que des chiffres.
Passez la même forme que votre serveur, { length: 4, alphabet }, et les deux moitiés suivent.
04Garanties
Un client qui martèle un bouton obtient une seule réponse.
Chaque appel annule le précédent, une réponse tardive d’un appel dépassé est ignorée plutôt que publiée, et rien n’est écrit après le démontage.
Hooks client, prêts pour l’App Router
Chaque export est un hook client et le build porte 'use client' : ils s’intègrent directement à l’App Router de Next.js. React 18 ou plus.
Jetons et clients sur mesure
Passez headers au provider pour un jeton, ou client pour fournir le vôtre, ce qui permet aussi de les tester sans aucun réseau.
Un statut à afficher
status vaut idle, pending, success ou error, et notFound couvre à la fois un code inconnu et un code expiré, comme le protocole.
- useSendTransfer()
- send, sendFile, transfer, status, isPending, error, reset
- useReceiveTransfer()
- load, loadBytes, burn, transfer, data, notFound, status, isPending, error, reset
- useSyncCodeInput()
- value, setValue, code, isComplete, error, reset, inputProps
- useTransferClient()
- le client sous-jacent, pour tout ce que les hooks ne couvrent pas
Vous envoyez. Ils valident. Vous le savez.
Votre stockage, une page de livraison à votre nom, un webhook à chaque étape. Rien d’hébergé chez un tiers.