materiahq / materia-server Goto Github PK
View Code? Open in Web Editor NEWMateria Server is the core of Materia. It handles your Materia Application and host them anywhere.
Home Page: https://getmateria.com
License: Apache License 2.0
Materia Server is the core of Materia. It handles your Materia Application and host them anywhere.
Home Page: https://getmateria.com
License: Apache License 2.0
Currently, we have 2 server profile: dev and prod defined respectively in materia.json and materia.prod.json
We could handle more server profile by detecting materia.json + materia.*.json
files
Each files materia.*.json
is a new server profile where *
is the profile name
In Materia Designer, we could connect in live mode to any server profile (e.g. prod / staging / prod2 etc...).
An endpoint is linked to a list of query. In this list, only one query can be a findAll
or a findOne
query. When the endpoint is called, every query are executed in parallel.
An endpoint is linked to a single query.
It would be easier to write models and custom queries if they were in the same file (hopefully Typescript).
This is an example of what I mean by merging queries and models in a single file:
@Entity('user')
class UserModel {
@Field({type: DataType.NUMBER, primary: true, autoIncrement: true}) id;
@Field({type: DataType.TEXT, required: true}) email;
@Field({type: DataType.TEXT, required: true}) password;
@Field({type: DataType.BOOLEAN}) public_email = false
constructor(private app: App) {}
@CustomQuery({
params: [{
name: 'email',
type: DataType.TEXT
required: true
},{
name: 'password',
type: DataType.TEXT
required: true
}]
})
signin(params) {
// todo
}
}
Many requirements are needed to implement this new syntax:
The automatic migration may sometimes break. When updating entities, we should generate a migration file that can be applied when deploying the application.
We can use this to generate migrations step:
http://docs.sequelizejs.com/manual/tutorial/migrations.html
Migrations should be displayed in Materia designer and should be editable easily.
The migrations could be automatically applied at deployments time to get the same behavior than what we currently have with automatic migration but it would add some control on how the migration is done.
An entity should have an id (unique). So when an entity or a field is rename, as the id doesn't change, materia can know it's just a rename and apply this change in the database without data loss.
An entity is currently identified by its name. The issue is when a user update a json file to rename an entity or a field, materia synchronize the database with the json file and don't see that it's a rename. Instead, it will delete the entity and create a new entity with the new name.
This is dangerous because data can be lost by removing an entire table.
launch the server with the command line materia start
Error in the console when running materia start
:
command not found
/usr/local/bin/materia: line 3: syntax error near unexpected token `('
/usr/local/bin/materia: line 3: `let argv = require('minimist')(process.argv.slice(2))'
Actually the server can be run with forever start ./node_modules/materia-server/cli/index.js start
sudo npm install -g materia-server
materia start
If we integrate @materia/users in this repository and install it by default in every applications, we can use admin role to connect materia-server admin API instead of using rootPassword.
Advantage:
If no database setup, we can still connect to a local sqlite database to have the minimal user structure
If no admin user defined, need a cli command to initialize the first admin user (to let materia-designer connect the admin API)
when creating the CustomQuery
object with opts.query
which contain the code. It should write the code in the file opts.file
.
The custom query can load the Javascript file and execute it. When saving the query, it return the JSON with the filename in opts.file
but there is no way to store the query or retrieve the code of the query.
$> materia deploy {provider} [--{param}={value}]*
Deploy an app directly from the CLI. The feature would be developed in /lib
to be used programmatically from Materia designer and from the CLI
Use windows path with backslash.
Some path use linux-style slash
app.addons.findAll()
-> get the list of installed addons with the associated metadata: name, description, logo, author
These metadata are in the package.json
file in the addon directory.
app.addons.findAll()
doesn't exist.
app.addons.addons
is an array containing installed addons without the metadata (we can't even know the name of the addon without checking the class name)
No warning
(node:97572) DeprecationWarning: Using Buffer without `new` will soon stop working. Use `new Buffer()`, or preferably `Buffer.from()`, `Buffer.allocUnsafe()` or `Buffer.alloc()` instead.
- connection.js:299 Object.<anonymous>
[materia-server]/[pg]/lib/connection.js:299:19
- module.js:20 require
internal/module.js:20:19
- client.js:18 Object.<anonymous>
[materia-server]/[pg]/lib/client.js:18:18
with node v7.0.0:
materia start
in any app
It's related to brianc/node-postgres#1163
This should alter the table to add/remove the primary key in db, to match the entity.
Does not change the primary key(s)
Update a field to add or remove a primary key, and check in db that did not changed the pk, or launch a synchronization and watch the diff.
Materia Server should handle optional database.
If database.json
is missing, it should:
--no-db
option in the CLI should be available to remove the warning (and skip the verification of database.json
etc.)
It crash silently and the process is terminated
~/materia-apps/MateriaWebMap> materia start
Starting materia in /Users/thyb/materia-apps/MateriaWebMap
~/materia-apps/MateriaWebMap>
mv database.json database.json.bak
materia start
Support Field type Image and File which represent image and file upload via the API.
Behind the scene, the SQL column is a TEXT containing the link/path of an image or a file.
A file upload input needs to be displayed as query/endpoint params (for create/update queries)
Endpoints need to handle file upload correctly.
Some options can be added when creating/updating a field of this type:
Validators associated with these new type:
app.api.permissions.findAll()
should list all permissions added by name
app.api.permissions.add(permissionName, middlewareFunction)
should add a permission by its name
app.api.permissions.remove(permissionName)
should remove a permission by its name
middlewareFunction
should have this prototype:
function(req, res, next) {
//todo
}
Not able to list permission
app.api.permissions.addFilter(middlewareFunction)
without setting up a name
Not able to remove a permission
Currently, the middlewareFunction
have this prototype:
function(permissions, req, res) {
//TODO
}
It allows the same permissions features but it adds the possibility to list and remove existing permission (e.g. if an addon is removed, it is expected to remove the associated permissions)
The API changes are also more similar to other Materia Object (e.g. app.endpoints.findAll()
etc...)
Define an index name to group unicity on more fields. e.g.
uniqueOne: { type: Sequelize.STRING, unique: 'compositeIndex'},
uniqueTwo: { type: Sequelize.INTEGER, unique: 'compositeIndex'}
the unique
property accepts only a boolean
Do not have a field default stored in entities and use only defaultValue, and replace default
field by a hasDefault
method
Rely on default
boolean
Create an entity
Separate endpoint.getAllParams()
and endpoint.getAllData()
A method endpoint.getMergedParams()
could still exists with the actual behavior
endpoint.getAllParams()
send a merge of params and data.
When an application begin to have lots of endpoints, api.json can be long and hard to read.
As #31, endpoints would be probably easier to read/write if api.json + controllers were merged
Something like the following example could work if as #31 we are able to edit / read the information contained in the class
@Controller('user')
class UserController {
constructor(private app: App) {}
@Get('/user/:email')
getUser = {
entity: 'user',
query: 'getByEmail'
}
@Post({
endpoint: '/user/signin',
params: [{
name: 'email',
type: DataType.TEXT,
required: true
},{
name: 'password',
type: DataType.TEXT,
required: true
}]
})
signin(req, res) {
//todo
res.status(200).send('ok')
}
}
Addons like Mailjet or Stripe generate lots of Virtual Entities and it can be hard to visualize everything easily when combined with the entities made by the users.
As a simple workaround, we can add filters in Entities Structure view in Materia Designer to hide unwanted entities
A better solution would be to be able to create Folder which contains Entity
e.g. add a folder
key in the model file to display this entity in a folder
{
...
folder: 'Stripe'
}
When updating a field type from text to integer (or boolean, date...), this should cast the data to the new type (c.f. http://stackoverflow.com/questions/13170570/change-type-of-varchar-field-to-integer-cannot-be-cast-automatically-to-type-i)
The SQL request looks like ALTER TABLE "..." ALTER COLUMN "..." TYPE TEXT
Changing a field type from type text to number, date or boolean throws an error when it should cast the data to the new type:
column "..." cannot be cast automatically to type ...
$> materia addons install {addon-name|addon-url}[#{version}]
Install an addon by its name or url to the latest version or to the specified version if it is specified
$> materia addons update {addon-name|addon-url}[#{version}]
Update an addon by its name or url to the latest version or to the specified version if it is specified
$> materia addons remove {addon-name|addon-url}
Remove an addon by its name or url
$> materia addons search {query}
Search an addon
The feature would be developed in /lib to be used programmatically from Materia designer and from the CLI.
All addons would be installed first in the Materia directory, then a symbolic link is created to the current app. Then, if another app is using the same addon, just a symbolic link is needed.
Ignore auto increment flag when creating / updating a field that is not a number
Try to add serial in DB
On designer, change a field type number which has auto increment to type text (without uncheck it before)
What is the OSS license for this project?
Related with https://github.com/thyb/materia-designer/issues/11 and https://github.com/thyb/materia-designer/issues/12
If GET
method:
All params from the query goes as endpoint params
If POST
method:
All params from the query goes as endpoint data
If PUT
method:
All params from the query goes as endpoint data
If DELETE
method:
All params from the query goes as endpoint params
If there is params in the URL (e.g. /customers/:id
), they are pushed as endpoint params
The actual behavior is still needed when the query is a custom Javascript function
For the moment, endpoints declare their params and data while the query associated also declare its params
It looks like that a query in a transaction (sequelize.query
) that is failing neither resolves its promise nor rollbacks the transaction. Only on travis.
The tests are passing on the same environment (same node / npm / linux ... versions). This needs some deeper tests and comparisons.
The following query config should works without addition "opts.values" field:
{
"id": "companiesSince",
"type": "sql",
"params": [
{
"name": "date",
"type": "date",
"required": true
}
],
"opts": {
"query": "SELECT speaker.company\nFROM speaker, event\nWHERE event.date_start >= :date\n AND event.slug = speaker.slug_event\nGROUP BY speaker.company"
}
}
This query config is working
{
"id": "companiesSince",
"type": "sql",
"params": [
{
"name": "date",
"type": "date",
"required": true
}
],
"opts": {
"values": {
"date": "="
},
"query": "SELECT speaker.company\nFROM speaker, event\nWHERE event.date_start >= :date\n AND event.slug = speaker.slug_event\nGROUP BY speaker.company"
}
}
but without opts.values
(as in the expected behavior
), it throws:
Error: Named parameter ":date" has no value in the given object.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.