ForgeTotal.js 5
el

Total.js 5

Επιχειρηματικοί κανόνες ως κείμενο με το NEWMACRO()

Total.js 5 · total5@0.0.19 macrosrulesscripting Εκτελέστηκε με το Total.js 5

Το NEWMACRO(text, [nocompile], [isasync]) μετατρέπει μερικές γραμμές μιας μικρής γλώσσας σε μια συνάρτηση function(model, helpers). Προορίζεται για κανόνες που αλλάζουν συχνότερα από τον κώδικα: μια έκπτωση, μια τιμή, έναν έλεγχο δικαιωμάτων, μια επικύρωση που κάποιος που δεν γράφει JavaScript συντηρεί σε ένα αρχείο ή σε μια βάση δεδομένων.

Η γλώσσα, όπως ελέγχθηκε:

  • Τα IF condition, ELSE IF condition, ELSE και FI (το τέλος της συνθήκης) λειτουργούν όπως σε έναν κανόνα βασισμένο σε κείμενο. Οι συνθήκες χρησιμοποιούν >, <, >=, <=, = και AND / OR.
  • Το RETURN value τελειώνει το macro με μια τιμή. Τα YES και NO (επίσης TRUE, FALSE, OK) είναι λογικές τιμές, το κείμενο ανάμεσα σε εισαγωγικά είναι κείμενο και οι αριθμοί είναι αριθμοί.
  • Μια λέξη είναι ιδιότητα του μοντέλου, γραμμένη με πεζά: το age διαβάζει το model.age και το total = price * qty γράφει το model.total.
  • Το NAME(arguments) καλεί έναν helper, τη συνάρτηση με αυτό το όνομα (με πεζά) στο αντικείμενο helpers που περνάτε· μέσα της το this είναι το μοντέλο. Με το isasync ίσο με true το macro είναι async συνάρτηση και περιμένει τους helpers.
  • Το #name είναι μια προσωρινή μεταβλητή της εκτέλεσης: #temp = num + 1 και RETURN #temp.
  • Χρησιμοποιήστε ονόματα με περισσότερα γράμματα: μια ιδιότητα ή μεταβλητή ενός γράμματος δεν αναγνωρίστηκε στους ελέγχους.

Το NEWMACRO() μεταγλωττίζει το κείμενο με new Function, άρα ένα macro είναι κώδικας: μεταγλωττίστε μόνο κείμενο που γράψατε εσείς ή που συντηρεί ένα αξιόπιστο πρόσωπο, ποτέ κείμενο που έστειλε ένας επισκέπτης. Με το nocompile ίσο με true επιστρέφει το JavaScript που παράγει αντί για τη συνάρτηση, κάτι χρήσιμο για να δείτε τι κάνει ένας κανόνας.

controllers/rules.js
const helpers = {
	percent: function(value, rate) {
		return value * rate / 100;
	}
};

const age = NEWMACRO("IF age >= 18\n\tRETURN 'adult'\nELSE\n\tRETURN 'minor'\nFI");

const level = NEWMACRO("IF points > 100\n\tRETURN 'gold'\nELSE IF points > 50\n\tRETURN 'silver'\nELSE\n\tRETURN 'bronze'\nFI");

const access = NEWMACRO("IF active AND score >= 5\n\tRETURN yes\nFI\nRETURN no");

const total = NEWMACRO("total = price * qty\nIF qty >= 10\n\ttotal = total - PERCENT(total, 10)\nFI\nRETURN total");

const temporary = NEWMACRO("#next = count + 1\nRETURN #next");

const slow = NEWMACRO("RETURN LOOKUP(code)", false, true);

exports.install = function() {
	ROUTE('POST /rules/', rules);
	ROUTE('GET /source/', source);
};

async function rules($) {
	const model = $.body;
	$.json({
		age: age(model, helpers),
		level: level(model, helpers),
		access: access(model, helpers),
		total: total(model, helpers),
		model_total: model.total,
		temporary: temporary(model, helpers),
		slow: await slow(model, { lookup: async code => 'found ' + code })
	});
}

function source($) {
	$.plain(NEWMACRO("IF points > 100\n\tRETURN 'gold'\nFI", true));
}