# Les petits assistants mondiaux : MAIN, REPO, FUNC, NOW, CLONE, COPY, QUERIFY et PROMISIFY

> Utilisez les globaux d'application, les dates, les copies profondes, les lignes de requête et les assistants promis.

Framework: total5
Product: Total.js 5 (total5@0.0.19)
Language: fr
Content-SHA256: 12b8687eca0f891edad044fd05dbe50f96fa8481d482cd3ae29ba51dfa78552c
Snapshot: c0700e321579725c5cf4f5ace1ad7d2866d1b4f93c24a63c0b41b6b7998e976c
Sources: total5-installed@total5@0.0.19
Review: not-recorded

`total5` crée quelques objets globaux pour votre usage et quelques helpers qui économisent une ligne de code. Rien de tout cela ne demande de configuration.

- `MAIN`, `REPO` et `FUNC` sont des objets vides que le framework crée une fois : gardez les données de l'application dans `MAIN`, d'autres données dans `REPO` et vos propres fonctions dans `FUNC`. `TEMP` est un objet pour des données temporaires que le framework remplace de temps en temps, n'y gardez donc rien dont vous aurez besoin plus tard.
- `NOW` est la date courante sous forme de `Date`. Elle est rafraîchie environ une fois par minute (et par certains appels), utilisez donc `new Date()` quand vous avez besoin de l'heure exacte.
- `EMPTYARRAY` et `EMPTYOBJECT` sont des valeurs vides gelées à renvoyer au lieu d'en créer de nouvelles : elles ne peuvent pas être modifiées.
- `MODS` et `PLUGINS` sont des objets contenant les modules et plugins chargés par identifiant. `F` et `Total` sont le même objet, le framework, et `print` est `console.log`. `NOOP` est une fonction qui ne fait rien.
- `REQUIRE(name)` est `require`, qui résout aussi les paquets depuis le `node_modules` de l'application et accepte des noms comme `node:path`.
- `CLONE(value)` fait une copie profonde : les objets imbriqués, les tableaux et les dates sont copiés. `COPY(from, to)` copie les propriétés du premier objet dans le second et renvoie le second.
- `QUERIFY([url], object)` construit une chaîne de requête à partir d'un objet : les valeurs vides et `null` sont ignorées et un tableau devient une valeur séparée par des virgules. Avec une url, il renvoie `url?...`, sans url il renvoie `?...`.
- `PROMISIFY(fn, a, b, c)` appelle `fn(a, b, c, callback)` et renvoie une promesse qui se résout avec la réponse du callback ou est rejetée avec son erreur.

```js controllers/helpers.js
MAIN.started = 'yes';
REPO.counter = 1;
FUNC.double = n => n * 2;

exports.install = function() {
	ROUTE('GET /helpers/', helpers);
	ROUTE('GET /promisify/', promisify);
};

function helpers($) {

	const source = { a: 1, nested: { b: [1, 2] }, date: new Date(2026, 0, 5) };
	const cloned = CLONE(source);
	const target = { x: 1 };
	const returned = COPY({ y: 2 }, target);

	$.json({
		shared: [MAIN.started, REPO.counter, FUNC.double(4), typeof TEMP],
		now: [NOW instanceof Date, Math.abs(Date.now() - NOW.getTime()) < 120000],
		emptyarray: [EMPTYARRAY.length, Object.isFrozen(EMPTYARRAY)],
		emptyobject: [Object.keys(EMPTYOBJECT).length, Object.isFrozen(EMPTYOBJECT)],
		registries: [typeof MODS, typeof PLUGINS],
		same: [F === Total, typeof print, NOOP() === undefined],
		require: typeof REQUIRE('node:path').join,
		clone: [cloned !== source, cloned.nested !== source.nested, cloned.nested.b !== source.nested.b, cloned.date instanceof Date, cloned.nested.b.join()],
		copy: [returned === target, target.x, target.y],
		querify: QUERIFY('/search/', { q: 'a b', page: 2, empty: '', nothing: null, list: [1, 2] }),
		querify2: QUERIFY({ q: 'x' })
	});
}

async function promisify($) {

	const add = (a, b, callback) => setImmediate(callback, null, a + b);
	const fail = (callback) => setImmediate(callback, 'It failed');

	const sum = await PROMISIFY(add, 2, 3);
	let error = null;

	try {
		await PROMISIFY(fail);
	} catch (e) {
		error = e.message || String(e);
	}

	$.json({ sum: sum, error: error });
}
```
