-
Notifications
You must be signed in to change notification settings - Fork 126
A tour of Opa
Opa is a full-stack open source web development framework for JavaScript that lets you write secure and scalable web applications.
Opa generates standard Node.js/MongoDB applications, natively supports HTML5 and CSS and automates many aspects of modern web application programming: Ajax/Comet client-server communication, event-driven and non-blocking programming models.
Opa enables to write full-stack applications:
- server (backend) programming (running on Node.js),
- client (frontend) programming (compiled to JavaScript) and
- database programming (using MongoDB).
Throughout the pages of this manual, we will introduce you to the many features of Opa. It will help if you have some knowledge of programming and web technology (HTML and CSS in particular).
Opa handles all aspects of web programming: frontend (client code), backend (server code) and database queries are all written in one consistent language and compiled to standards of the web: JavaScript frontend, Node.js backend and MongoDB for the database. Other targets are planned, making Opa a gateway to web programming.
You can write a complete Opa program without thinking about the client-server distinction and the Opa compiler will distribute the code as needed for you and take care of all the communication. Should you need to tweak the choices made by the compiler (for instance to improve the application performance) it's very easy with simple keywords like client
, server
and more for fine-tuning.
// Opa decides
function client_or_server(x, y) { ... }
// Client-side
client function client_function(x, y) { ... }
// Server-side
server function server_function(x, y) { ... }
The database code can also be written directly in Opa. Opa supports the major NoSQL databases: CouchDB and MongoDB. The latter requires no configuration at all and is recommended for beginners, while the former offers state-of-the-art reliability and performance.
To write an application, first type the code in your favorite editor. The simplest "Hello, world" application in Opa is written in just a few lines:
Server.start(
Server.http,
{ title: "Hello, world"
, page: function() { <h1>Hello, world</h1> }
}
)
The program can be compiled and run with the following single command line:
opa hello.opa --
The resulting application can be opened in your favorite browser at http://localhost:8080
Opa syntax is inspired by popular programming languages, most notably, JavaScript. Below is an extract of a real Opa program:
function createUser(username, password) {
match (findUser(username)) {
case {none}:
user =
{ username: username
, fullname: ""
, password: Crypto.Hash.sha2(password)
};
saveUser(user);
default:
displayMessage("This username exists");
};
Client.goto("/login");
}
Opa however extends the classical syntax with advanced features specific to the web. HTML fragments can be inserted directly without quotes:
line = <div id="foo">bar</div>;
CSS selectors readily available:
selector = #foo;
And a pointer-like syntax allows to apply a given content to a selector:
*selector = line;
Opa provides event-driven programming. For instance, running a function when an event is triggered is accomplished in the following way:
function action(event) {
#foo = <div id="bar" />;
}
...
<div onclick={action} />
The best place to start looking at the features of Opa and their syntax is the reference card.
One of the most important features of Opa is its typing system. Although Opa may look like and has many advantages of dynamic programming languages, it is a compiled language which relies on a state-of-the-art type system.
Opa checks the types at compile time, which means that no type error can happen at runtime. For instance, the following code
foo = 1 + "bar";
raises the following error at compile time:
Type Conflict
(1:7-1:7) int
(1:11-1:15) string
The types of the first argument and the second argument
of function + of stdlib.core should be the same
Unlike C or Java, you don't have to annotate types yourself as Opa features almost complete type inference. For instance, you can just write:
function foo(s) {
String.length(s);
}
function bar(x, y) {
foo(x) + y;
}
and the Opa compilers automatically infers the types, as if you've written:
int function foo(string s) {
String.length(s);
}
int function bar(string x, int y) {
foo(x) + y;
}
This system will become your wingman while you code. For instance, we will present four types of errors that are caught at compile time. The examples are taken from a real work on Opa program named webshell, available at http://github.com/hbbio/webshell.
If you write:
element =
<div>
<span>{prompt({none})}</span>
<span>{expr}
</div>
<div>{Calc.compute(expr)}</div>;
The compiler will tell you that there is an "Open and close tag mismatch ,found at (48:8-48:11), vs .".
If you write:
case {some: 13}: #status = "Enter"; callback(get());
case {some: 37}: #status = "Left"; move({lef});
case {some: 38}: #status = "Up"; move({up});
case {some: 39}: #status = "Right"; move({right});
The compiler will tell you that the type of this function is not right. You are using a type { lef }
when a type { left } or { right } or { rightmost } or { up } or { down }
is expected. The latter type is not declared anywhere in the code, but rather was inferred by the Opa compiler from the rest of the code.
If you write:
previous = Dom.get_content(#precaret);
#precaret = String.sub(0, String.lenght(previous) - 1, previous);
#postcaret += String.get(String.length(previous) - 1, previous);
the compiler will tell you that String
module has no lenght
function and will suggest that maybe you meant length or init
instead?
If you write:
previous = Dom.get_content(#postcaret);
#postcaret = String.sub(1, String.length(previous) - 1, previous);
#precaret =+ String.get(previous);
the compiler will tell you that String.get
takes 2 arguments, but only 1 is given. And will suggest that the 1st-argument is of type int
.
Opa type system not only manages basic types but complex data-structures, functions and even modules! Check the following chapter for a full presentation.
Opa has extensive support for MongoDB (and, to lesser extent, CouchDB) offering a state-of-the-art solution for data storage and retrieval.
Database values are declared by stating their type:
database type /path;
for instance
database int /counter;
In the line above, /counter
is called a path, as accessing stored values bears similarities to browsing a filesystem.
Getting a value from the database is simply accomplished with:
/counter
while storing (or replacing) a value with:
/path <- value
You can store complex datastructures in the database, like maps. A map is a datastructure that associates a value to each key. The path system recognize such datastructures and allows to specify a key directly in the path. For instance, you can write:
database stringmap(string) /dictionary;
...
/dictionary[key];
...
/dictionary[key] <- value;
...
Opa offers scaffolding for easy project creation. Just write opa create myapp
This will create a skeleton of a new app named myapp
based on the MVC architecture. Run it with:
cd myapp
make run
Edit the sources in the src
and resources in the resources
directory. You can also try opa create --help
for more options.
In the following chapters, we will introduce you to various features and use-cases of Opa. Each chapter concentrates on writing one specific application, and on how best to achieve this using combination of skills developed in previous and current chapter. At the end of the manual, additional reference chapters introduce all the concepts of the language and the platform in more detail.
If you have any question or feedback, do not hesitate to contact us. A few ways to get in touch:
- Opa forum;
- Opa mailing list;
-
Stack Overflow, an excellent site for seeking help with programming problems (do not forget to mark Opa related questions with the
Opa
tag); - Follow Opa on Twitter (@opalang) or Facebook or Google+ if you want to be always up to date.
We will be there. Now it's up to you to write great apps!
- A tour of Opa
- Getting started
- Hello, chat
- Hello, wiki
- Hello, web services
- Hello, web services -- client
- Hello, database
- Hello, reCaptcha, and the rest of the world
- The core language
- Developing for the web
- Xml parsers
- The database
- Low-level MongoDB support
- Running Executables
- The type system
- Filename extensions