The main scope of the FRIC project is to build and deploy a library for fractal generation. Our final product will be delivered with 2 large components, meant for public use:
We can break down the structure of the project into:
A javascript module that can be implemented and used to generate fractals based on user provided definitions. The module will also expose some functionality regarding the user system, the token related quota and more info regarding the AWS server-side implementation.
A front facing platform with 2 main responsibilities:
Following the official Requirements we are going to build the final product(s) in a stack comprised of
The library is going to be exposed to the programmer through a simple ES6 module (hosted maybe on NPM) that will structure all the functionality (Reference: ModularJS).
Another approach would be to use ES6 modules and transpile them using babel for ES5 support, but we will take this into consideration at a later date, based on the progress we make.
For the sake of simplicity, we are going to use JSDOC typedef to declare some objects and variables. These will be widely used throught our documentation.
Auth
/**
* @typedef {Object} Auth
* @property {string} id - The unique user identification string
* @property {token} token - The value which will determine the quota of a user
*/
A user can own more than one token, based on the priviledges he chooses for it.
Identity
/**
* @typedef {Object} Identity
* @property {string} name - The unique user identification string
* @property {Object[]} history - A brief history of the recent usage of the token
* @property {string} history[].timestamp - Time of creation for history item
* @property {string} history[].action - Type of history item
* @property {string} history[].payload - Extra data that can describe the action
* @property {Object} quota - The remaining usage quota for that particular token
* @property {string} quota.quantity - Remaining horse power
* @property {string} quota.refresh - Timestamp for next quota refresh (if any)
*/
We will define the remainig quota based on either computation seconds or access count. Will decide this when we have a better understanding of AWS pricing.
Fractal
/**
* @typedef {Object} Fractal
* @property {string} id - A unique identifier for the generated fractal
* @property {string} url - The link for a .png image descibing the generated fractal
* @property {Object} data - Extra data about the fractal (including but not limited to its ordered rules, its length and definition etc.)
*/
Reference: HTTPStatus, @type {Fractal}
Definition
/**
* @typedef {Object} Definition - Parameters that will describe rules and attributes for the soon-to-be generated @type {Fractal}
* @property {string} type - One of ["LSystem"]
* [ if type === "LSystem" ]
* @property {number} iterations - e.g. 3
* @property {string} start - e.g. "X"
* @property {Array<Object>} rules - e.g. [{left : "X", right : "X+YF+"}]
* @property {int} x - start point on X axis e.g. 100
* @property {int} y - start point on Y axis e.g. 100
* @property {number} lineSize
* @property {number} angle - e.g. 360
*/
Response
/**
* @typedef {Object} Response
* @property {string} status - A HTTP response status code of the query
* @property {string} message - A contextual response message from the server e.g. "Succes" vs "Access not granted"
* @property {Fractal} fractal - If everything goes smooth, it will contain the fractal definition
*/
Reference: HTTPStatus, @type {Fractal}
Because our library will rely on heavy communication with the server, we are going to design most of the calls as "Promises". This way, we can allow for an intuitive and controlled async experience.
FractalBuilder.init(...params)
To instantiate the module, after import a user will have to
initialize it, either through the
init()
method.
/**
* Initializes the environment
* @param {Auth} auth
*/
FractalBuilder.init(auth)
Each time the programmer is going to make use of our library, the id and token will be checked for validity and available quota.
This authenthication object will be sent inside a header parameter and wrapped in the shape of a JWT. This will allow us to verify if the request has been tempered with through the JWT signature feature.
FractalBuilder.who()
In order to check his/her identity based on the
Auth
object data, a user can use the
.who()
method. The promise will return an object
describing the user's identity (@type {Identity}
).
/**
* Returns user identity based on the auth object
* @returns {Promise.<Identity|Error>} - If the auth object is not defined yet, we'll throw an Error describing this issue
*/
FractalBuilder.who(auth)
.then(identity => {...})
.catch(error => {...})
FractalBuilder.build(...params)
Building a fractal will be done through the build function. This
will return a response (@type {Response}
) containing some flags and (if successful) the
@type {Fractal}
object, descibing the created shape.
/**
* Returns user identity based on the auth object
* @returns {Promise.<Response|Error>} - If the auth object is not defined yet, we'll throw an Error describing this issue
*/
FractalBuilder.who(auth)
.then(response => {...})
.catch(error => {...})
Our AWS Lambda functions will handle generating the fractals.
Our library will mainly be made up of requests. The
build()
functionality will send us (among other stuff)
a Definition of the Fractal required by the user. If this is a valid
request (user is authorized and definition is valid), we'll rely on
a AWS Lambda function to compute the shape of the fractal, create an
image and drop it into our S3. Additional data will be stored in a
NoSQL DynamoDB instance.
The language used to design these functions will be Node JS.
In order to use the library, a user must first request a token. Refernce: 3.4.1 Features - Stage A
Our Platform will run in a static context and it will be hosted with AWS S3. It will also access Lambda Functions which will act as an API for our platform. We'll design it as a mixture of SPA and MPA (hybrid, but with more focus on the SPA aspect). Everything will be kept as modular as possbile by employing a "synthetic React" approach (every element will be wrapped in a pseudo-component that we'll use to manage it when needed).
For a preview of the beta version of our API, we used Swagger to map some of the endpoints and functionality we'll use both internally (for the plaform Stage A and B) and externally/publicly (inside our library).
All the following features will be linked to AWS Lamda functions.
Stage A: User/Token manager
The primary source of token generation for new users will be our Token Manager Platform. The sole purpose of this webpage will be to generate a user ID - Token pair, that will later be provided at each use of the library. (Similar to the Google API KEY system). We chose to use an ID - Token pair rather than a simple Token because of the later possibility to scale and use the same system for user accounts (Stage B of the Platform).
Rough actions:
Stage B: Fractal explorer and builder
Pages
Requests
We'll use the AWS DynamoDB service to structure our database.