data for AddressBook
[angular-mojolicious.git] / angular-server.pl
1 #!/usr/bin/env perl
2
3 use Mojolicious::Lite;
4 use Data::Dump qw(dump);
5
6 # based on
7 # http://docs.getangular.com/REST.Basic
8 # http://angular.getangular.com/data
9
10 our $data = {
11         'Cookbook' => {
12                 test => [
13                                 { '$id' => 1, foo => 1, bar => 2, baz => 3 },
14                                 { '$id' => 2, foo => 1                     },
15                                 { '$id' => 3,           bar => 2           },
16                                 { '$id' => 4,                     baz => 3 },
17                 ],
18         },
19         'AddressBook' => {
20                 people => [
21                         {name=>'Misko'},
22                         {name=>'Igor'},
23                         {name=>'Adam'},
24                         {name=>'Elliott'}
25                 ]
26         }
27 };
28 our $id2nr;
29
30 sub _render_jsonp {
31         my ( $self, $json ) = @_;
32         my $data = $self->render( json => $json, partial => 1 );
33         if ( my $callback = $self->param('callback') ) {
34                 $data = "$callback($data)";
35         }
36         $self->render( data => $data, format => 'js' );
37 }
38
39 #get '/' => 'index';
40
41 get '/_replicate' => sub {
42         my $self = shift;
43
44         if ( my $from = $self->param('from') ) {
45                 my $got = $self->client->get( $from )->res->json;
46                 warn "# from $from ",dump($got);
47                 _render_jsonp( $self,  $got );
48
49                 my $database = $got->{name};
50                 my $entities = $got->{entities};
51
52                 if ( $database && $entities ) {
53                         foreach my $entity ( keys %$entities ) {
54                                 my $url = $from;
55                                 $url =~ s{/?$}{/}; # add slash at end
56                                 $url .= $entity;
57                                 my $e = $self->client->get( $url )->res->json;
58                                 warn "# replicated $url ", dump($e);
59                                 $data->{$database}->{$entity} = $e;
60                                 delete $id2nr->{$database}->{$entity};
61                         }
62                 }
63         }
64 };
65
66 get '/_data' => sub {
67         my $self = shift;
68         _render_jsonp( $self, $data )
69 };
70
71 get '/data/' => sub {
72         my $self = shift;
73         _render_jsonp( $self,  [ keys %$data ] );
74 };
75
76 get '/data/:database' => sub {
77         my $self = shift;
78         my $database = $self->param('database');
79         my $list_databases = { name => $database };
80         foreach my $entity ( keys %{ $data->{ $database }} ) {
81 warn "# entry $entity ", dump( $data->{$database}->{$entity} );
82                 my $count = $#{ $data->{$database}->{$entity} } + 1;
83                 $list_databases->{entities}->{$entity} = $count;
84                 $list_databases->{document_count} += $count;
85         }
86         warn dump($list_databases);
87         _render_jsonp( $self,  $list_databases );
88 };
89
90 get '/data/:database/:entity' => sub {
91         my $self = shift;
92         _render_jsonp( $self,  $data->{ $self->param('database') }->{ $self->param('entity' ) } );
93 };
94
95 get '/data/:database/:entity/:id' => sub {
96     my $self = shift;
97
98         my $database = $self->param('database');
99         my $entity   = $self->param('entity');
100         my $id       = $self->param('id');
101
102         my $e = $data->{$database}->{$entity} || die "no entity $entity";
103
104         if ( ! defined $id2nr->{$database}->{$entity}  ) {
105                 foreach my $i ( 0 .. $#$e ) {
106                         $id2nr->{$database}->{$entity}->{ $e->[$i]->{'$id'} } = $i;
107                 }
108         }
109
110         if ( exists $id2nr->{$database}->{$entity}->{$id} ) {
111                 my $nr = $id2nr->{$database}->{$entity}->{$id};
112                 warn "# entity $id -> $nr\n";
113                 _render_jsonp( $self,  $data->{$database}->{$entity}->[$nr] );
114         } else {
115                 die "no entity $entity $id in ", dump( $id2nr->{$database}->{$entity} );
116         }
117 };
118
119 any [ 'put', 'post' ] => '/data/:database/:entity/:id' => sub {
120         my $self = shift;
121         my $data = $self->req->json;
122         warn "# body ",dump($self->req->body, $data);
123         die "no data" unless $data;
124         $data->{ $self->param('database') }->{ $self->param('entity') }->{ $self->param('id') } = $data;
125         _render_jsonp( $self,  $data );
126 };
127
128 get '/demo/:groovy' => sub {
129         my $self = shift;
130     $self->render(text => $self->param('groovy'), layout => 'funky');
131 };
132
133 get '/' => sub { shift->redirect_to('/Cookbook') };
134 get '/Cookbook' => 'Cookbook';
135 get '/Cookbook/:example' => sub {
136         my $self = shift;
137         $self->stash('ANGULAR_JS', $ENV{ANGULAR_JS} || ( -e 'public/angular/build/angular.js' ? '/angular/build/angular.js' : '/angular/src/angular-bootstrap.js' ) );
138         $self->render( "Cookbook/" . $self->param('example'), layout => 'angular' );
139 };
140
141
142 app->start;
143 __DATA__
144
145 @@ index.html.ep
146 % layout 'funky';
147 Yea baby!
148
149 @@ layouts/funky.html.ep
150 <!doctype html><html>
151     <head><title>Funky!</title></head>
152     <body><%== content %></body>
153 </html>
154
155 @@ layouts/angular.html.ep
156 <!DOCTYPE HTML>
157 <html xmlns:ng="http://angularjs.org">
158   <head>
159     <script type="text/javascript"
160          src="<%== $ANGULAR_JS %>" ng:autobind></script>
161   </head>
162   <body><%== content %></body>
163 </html>