revbank/plugins/json
2022-01-19 17:58:18 +01:00

91 lines
2.7 KiB
Perl

#!perl
=head1 CAVEATS
This module requires the Perl module "JSON" to be installed.
Note that cent amounts are emitted as strings, not floats. This is on purpose.
They are, however, in a format that is easy to parse and convert (e.g.
JavaScript "parseFloat").
Note that things may be happening that don't have any JSON output.
Note that if plugins explicitly print to STDOUT, that will break the JSON
output. Regular print (without specified filehandle) will be suppressed.
Note that one command line may result in several separate transactions.
Note that plugins don't know it's non-interactive, and will often emit
RETRY instead of REJECT.
Note that this plugin will always be highly experimental; re-evaluate your
assumptions when upgrading. :)
This plugin is intended to be used together with "revbank -c 'command line'",
but you could try to use it interactively; if you do, please let me know about
your use case.
Set the environment variable REVBANK_JSON to either "array" or "lines" (see
jsonlines.org).
=cut
use JSON;
my $json = JSON->new->utf8->convert_blessed->canonical;
BEGIN {
if ($ENV{REVBANK_JSON} and $ENV{REVBANK_JSON} =~ /^(?:array|lines)$/) {
my $array = $ENV{REVBANK_JSON} eq "array";
# Suppress normal print output
open my $null, ">", "/dev/null";
select $null;
print STDOUT "[\n" if $array;
my $count = 0;
*_log = sub($hash) {
# JSON does not allow trailing commas, argh
print STDOUT ",\n" if $array and $count++;
print STDOUT $json->encode($hash);
print STDOUT "\n" if not $array;
};
END { print STDOUT "\n]\n" if $array }
# Monkey patch
*RevBank::Amount::TO_JSON = sub($self, @) {
$self->string("+");
};
} else {
*_log = sub { };
}
}
sub hook_abort(@) {
_log({ _ => "ABORT" });
}
sub hook_reject($class, $plugin, $reason, $abort, @) {
_log({ _ => "REJECT", plugin => $plugin, reason => $reason, abort => $abort });
}
sub hook_retry($class, $plugin, $reason, $abort, @) {
_log({ _ => "RETRY", plugin => $plugin, reason => $reason, abort => $abort });
}
sub hook_user_created($class, $username, @) {
_log({ _ => "NEWUSER", account => $username });
}
# NB: stringify transaction_id because future ids might not be numeric.
sub hook_user_balance($class, $user, $old, $delta, $new, $transaction_id, @) {
_log({ _ => "BALANCE", account => $user, old => $old, delta => $delta, new => $new, transaction_id => "$transaction_id" });
}
sub hook_checkout($class, $cart, $username, $transaction_id, @) {
_log({ _ => "CHECKOUT", account => $username, transaction_id => "$transaction_id" });
}