5 package App::LazyShoppingList::API::v1;
6 use App::LazyShoppingList::API;
13 use experimental 'signatures';
15 set charset => 'UTF-8';
16 set serializer => 'JSON';
17 set content_type => 'application/json';
20 # get the URI for the list of shopping lists
22 return { lists => uri_for('/list') };
25 # get the list of shopping lists
27 my $dbh = get_database;
30 my %r = ( lists_version => get_lists_version($dbh), lists => [] );
32 $dbh->resultset('ShoppingList')
34 { order_by => { -asc => 'name' } } )->all
37 push @{ $r{lists} }, uri_for( "/list/" . $list->id );
44 # create shopping list
46 my $req = request_data;
48 my $name = $req->{name};
51 content_type 'text/plain';
52 return "Missing list name";
55 my $dbh = get_database;
57 my $list = $dbh->resultset('ShoppingList')->create({
59 $list->discard_changes;
61 my $lists_ver = increment_lists_version($dbh);
66 uri => uri_for( '/list/' . $list->id ),
67 version => $list->version,
68 lists_version => $lists_ver
72 # get shopping list items
73 get '/list/:list_id' => sub {
74 my $list_id = route_parameters->get('list_id');
75 length($list_id) and $list_id =~ /^\d{1,18}$/ or return invalid_input;
77 my $dbh = get_database;
80 my %r = ( items => [] );
83 $r{lists_version} = get_lists_version($dbh);
85 my $list = $dbh->resultset('ShoppingList')->find($list_id);
90 content_type 'text/plain';
91 return "No list with that ID found";
94 $r{version} = $list->version;
96 my @items = $dbh->resultset('ShoppingListItem')
97 ->search( undef, { order_by => { -asc => 'id' } } )->all;
98 for my $item (@items) {
101 uri_for( sprintf( "/list/%s/%s", $list->id, $item->id ) ),
102 description => $item->description,
103 done => JSON->boolean( $item->done ),
104 version => $item->version,
113 # create shopping list item
114 post '/list/:id' => sub {
115 my $list_id = route_parameters->get('id');
116 length($list_id) and $list_id =~ /^\d{1,18}$/
117 or return invalid_input('bad list ID');
119 my $req = request_data;
121 my $descr = $req->{description};
122 my $done = JSON->boolean( $req->{done} // 0 );
124 my $dbh = get_database;
128 lists_version => get_lists_version($dbh),
131 my $list = $dbh->resultset('ShoppingList')->find($list_id);
136 content_type 'text/plain';
137 return "No such list";
140 my $item = $dbh->resultset('ShoppingListItem')->create(
141 { shopping_list => $list->id,
142 description => $descr,
146 $item->discard_changes;
148 $list->update( { version => $list->version + 1 } );
150 $r{uri} = uri_for( sprintf( "list/%s/%s", $list->id, $item->id ) );
151 $r{version} = $item->version;
152 $r{list_version} = $list->version;
159 # modify shopping list item
160 put '/list/:list_id/:item_id' => sub {
161 my $list_id = route_parameters->get('list_id');
162 length($list_id) and $list_id =~ /^\d{1,18}$/
163 or return invalid_input('bad list ID');
165 my $item_id = route_parameters->get('item_id');
166 length($item_id) and $item_id =~ /^\d{1,18}$/
167 or return invalid_input('bad item ID');
169 my $req = request_data;
171 my $descr = $req->{description};
172 my $done = JSON->boolean( $req->{done} // 0 );
173 my $version = $req->{version};
175 length($version) and $version =~ /^\d{1,18}$/
176 or return invalid_input('bad version');
178 my $dbh = get_database;
182 lists_version => get_lists_version($dbh),
185 my $list = $dbh->resultset('ShoppingList')->find($list_id);
189 content_type 'text/plain';
190 return "No such list";
193 my $item = $dbh->resultset('ShoppingListItem')->find({shopping_list => $list->id, id => $item_id});
197 content_type 'text/plain';
198 return "No such item";
201 # in case no real changes are needed will return the current state
202 if ( defined($descr) and $descr ne ( $item->description // '' )
203 or defined($done) and $done != $item->done )
205 unless ($version == $item->version) {
208 content_type 'text/plain';
210 sprintf( 'Outdated version (current is %d)', $item->version );
214 defined($descr) ? (description => $descr) : (),
215 defined($done) ? (done => $done) : (),
216 version => $version + 1,
219 $list->update( { version => $list->version + 1 } );
222 $r{uri} = uri_for( sprintf( "list/%s/%s", $list->id, $item->id ) );
223 $r{version} = $item->version;
224 $r{list_version} = $list->version;