Comparing version 1.3.1 to 2.0.0-alpha.0
10
index.js
@@ -1,1 +0,9 @@ | ||
module.exports = require('./lib/clay.js') | ||
var path = require('path'); | ||
var srcDir = path.join(__dirname, 'src'); | ||
module.exports = { | ||
includePaths: [path.join(srcDir, 'scss')], | ||
buildDir: path.join(__dirname, 'build'), | ||
srcDir: srcDir | ||
}; |
{ | ||
"name": "clay" | ||
, "version": "1.3.1" | ||
, "description": "A Node.js Active Record with a charming declaration and simple usage. Supports Redis as backend but can be easily extended" | ||
, "keywords": ["Active Record", "Redis", "database", "ORM", "model", "models", "persistence", "db"] | ||
, "homepage": "http://github.com/Yipit/clay.js" | ||
, "bugs": "http://github.com/Yipit/clay.js/issues" | ||
, "main": "./index.js" | ||
, "repository": { | ||
"type" : "git" | ||
, "url" : "git://github.com/Yipit/clay.js.git" | ||
} | ||
, "dependencies": { | ||
"underscore": ">= 1.2.2" | ||
, "redis": ">= 0.6.7" | ||
, "date-utils": ">= 1.2.5" | ||
, "async": ">= 0.1.15" | ||
} | ||
, "devDependencies": { | ||
"mocha": ">= 0.12.0" | ||
, "should": ">= 0.3.2" | ||
, "wrench": ">= 1.3.1" | ||
, "colors": ">= 0.5.1" | ||
} | ||
, "maintainers": [ | ||
{ | ||
"name": "Gabriel Falcão" | ||
, "email": "gabriel@yipit.com" | ||
, "web": "http://github.com/gabrielfalcao" | ||
}, | ||
{ | ||
"name": "Yipit" | ||
, "email": "coders@yipit.com" | ||
, "web": "http://github.com/Yipit" | ||
} | ||
] | ||
, "licenses": [ | ||
{ | ||
"type": "MIT" | ||
, "url": "http://www.opensource.org/licenses/mit-license.php" | ||
} | ||
] | ||
, "engines": { | ||
"node": ">= 0.4.12" | ||
} | ||
} | ||
"author": { | ||
"name": "Nate Cavanaugh", | ||
"email": "nathan.cavanaugh@liferay.com", | ||
"url": "https://github.com/natecavanaugh" | ||
}, | ||
"bugs": "https://github.com/liferay/clay/issues", | ||
"contributors": [ | ||
{ | ||
"name": "Patrick Yeo", | ||
"email": "patrick.yeo@liferay.com", | ||
"web": "https://github.com/pat270" | ||
}, | ||
{ | ||
"name": "Rob Frampton", | ||
"email": "rob.g.frampton@gmail.com", | ||
"web": "https://github.com/Robert-Frampton" | ||
} | ||
], | ||
"description": "Liferay's web implementation of the Lexicon Design Language", | ||
"homepage": "http://liferay.github.io/clay", | ||
"license": "MIT", | ||
"main": "index.js", | ||
"name": "clay", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/liferay/clay" | ||
}, | ||
"version": "2.0.0-alpha.0" | ||
} |
537
README.md
@@ -1,504 +0,93 @@ | ||
![logo](http://gabrielfalcao.github.com/img/clay.png) | ||
## Notice: 2.0.0-alpha Release | ||
# clay.js | ||
> version 1.3 | ||
> This project is under active development, we recommended not using alpha | ||
releases in your project. | ||
# DISCLAIMER | ||
<!-- START doctoc generated TOC please keep comment here to allow auto update --> | ||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> | ||
### Jump to Section | ||
clay is being rewritten and its relationship support is not working | ||
yet. | ||
- [About](#about) | ||
- [Building](#building) | ||
- [Clone the repo](#clone-the-repo) | ||
- [Install Node.js and NPM](#install-nodejs-and-npm) | ||
- [Install the NPM modules](#install-the-npm-modules) | ||
- [Modify files in src/](#modify-files-in-src) | ||
- [Build the static files](#build-the-static-files) | ||
- [View the files](#view-the-files) | ||
- [File Heading Options](#file-heading-options) | ||
- [Available Build Tasks](#available-build-tasks) | ||
- [Changelog](#changelog) | ||
With the most sincer apologies, [Gabe](http://github.com/gabrielfalcao) | ||
<!-- END doctoc generated TOC please keep comment here to allow auto update --> | ||
# What | ||
## About | ||
Clay is Liferay's web implementation of the Lexicon Design Language. It is built with HTML, CSS, and Javascript with [Bootstrap](http://getbootstrap.com) as a foundation. | ||
Clay is a lightweight active record for Node.js applications. It | ||
leverages the effort of declaring models and its relationships, and | ||
store them in any backend. | ||
You can view the various components on [the Clay site](https://liferay.github.io/clay). | ||
Clay comes with builtin support for [Redis](http://redis.io) but has a | ||
very simple interface with storage mechanisms, so that you can write | ||
your own backend. | ||
<!-- TODO: provide link to Lexicon site for documentation on design patterns --> | ||
# Hands On ! | ||
## Building | ||
If you would like to contribute, or make changes on your system you need to do the following: | ||
## installation | ||
### Clone the repo | ||
Clone the repo to your computer | ||
```bash | ||
npm install clay | ||
``` | ||
### Install Node.js (v4.6.0 LTS) and NPM | ||
If you don't already have it installed. You can find more info here: http://nodejs.org/ | ||
Node and NPM come bundled together, so you only need to install one package. | ||
## declaration | ||
### Install the NPM modules | ||
Run `npm install` inside of the `clay` directory | ||
Let's go by example: | ||
### Modify files in src/ | ||
The files are generated from the `src/` directory, however, most of the files you'd be interested in changing are in `src/content/`. Files can be either HTML (`.html`) or Markdown (`.md`). | ||
Every file in `src/content/` has a heading at the top in YAML format that looks something like: | ||
```javascript | ||
var redis = require('redis').createConnection(); | ||
var models = require('clay'); | ||
--- | ||
title: Title of the Page | ||
--- | ||
var User = models.declare("User", function(it, kind){ | ||
it.has.field("name", kind.string); | ||
it.has.field("email", kind.email); | ||
it.has.field("password", kind.string); | ||
it.has.method('greet', function() { | ||
return [ | ||
"Hello, my name is ", this.name, ", it's nice to meet you" | ||
].join(''); | ||
}); | ||
}); | ||
This section has a couple of options that can be leveraged for different purposes. Those will be covered below. | ||
var Build = models.declare("Build", function(it, kind){ | ||
it.has.field("status", kind.numeric); | ||
it.has.field("error", kind.string); | ||
it.has.field("output", kind.string); | ||
it.has.one("author", User, "builds"); | ||
}); | ||
var BuildInstruction = models.declare("BuildInstruction", function(it, kind){ | ||
it.has.field("name", kind.string); | ||
it.has.field("repository_address", kind.string); | ||
it.has.field("build_command", kind.string); | ||
it.validates.uniquenessOf("name"); | ||
it.has.index("repository_address"); | ||
it.has.many("builds", Build, "instruction"); | ||
it.has.one("owner", User, "created_instructions"); | ||
}); | ||
### Build the static files | ||
Run `gulp build` to generate the static files. | ||
``` | ||
### View the files | ||
The generated files are placed into the `build/` directory. | ||
Sass files in the `.scss` format are generated to CSS, Markdown files with the extension of `.md` are generated to HTML, and HTML files have one bit of processing applied, which is that HTML inside of triple ticks is escaped, like so: | ||
# anatomy | ||
``` | ||
<div>Foo</div> | ||
``` | ||
Clay provides syntactic sugar function calls that will help you | ||
declare models in a very classy, fashion and expressive way. | ||
### File Heading Options | ||
There are a couple of properties you can add to the headings of files, only one of which is required: | ||
It is possible through the callback passed to the `models.declare` | ||
call, and it has the arguments `it` and `kind`. These two will help | ||
you out to declare your model. | ||
`title:`: **(Required)** This is used for the title of the page in the heading and in the navigation sidebar | ||
## field types | ||
`navIndex:`: The navigation is sorted alphabetically by default, but if you pass a `navIndex:` property, it will manually sort the item into that position. | ||
The property is any number, with `0` as the first position, but you can also pass in a keyword of `last` to force an item to the end. | ||
Clay's field kinds are no more than just functions responsible to | ||
transform and validate data. | ||
`section:`: If you want to group multiple files into sections, in each of those files, pass the same title to the `section:` property. That title will be used for the section heading, and the files will be sorted in there. The `navIndex:` property works inside of sections as well. | ||
You can implement your own field kind, or use the builtin kinds. They come with valitation out of the box: | ||
### Available Build Tasks | ||
You can pass these options when running `gulp`. | ||
### alphanumeric | ||
`build`: This is the default task, so running just `gulp` will fire off the build task. | ||
This will generate all of the HTML/CSS/etc into the `build/` directory. | ||
shorthand for the regexp `/^[a-zA-z-0-9]+$/` | ||
`watch`: Because running a script after every change can get tedious, run `gulp watch` to rebuild the files automatically as you change files. | ||
`USAGE:` | ||
`serve`: Starts a local server on port 3000 and also runs the watch task. | ||
`release`: This task will create a zip file located in the root of the repo with the version number located in the package.json. | ||
We use this to deploy into Liferay. | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('example', kind.alphanumeric); | ||
}); | ||
``` | ||
`toc`: If you add a section to the README file, running `gulp toc` will generate a new table of contents. | ||
### numeric | ||
## Changelog | ||
shorthand for the regexp `/^[0-9]+$/` | ||
also returns an integer through `parseInt` | ||
`USAGE:` | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('example', kind.numeric); | ||
}); | ||
``` | ||
### datetime | ||
returns a `new Date(value)`, be aware that clay is [date-utils](https://github.com/JerrySievert/node-date-utils) powered | ||
`USAGE:` | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('birth_day', kind.datetime); | ||
}); | ||
``` | ||
### auto | ||
auto-assigns a `new Date()` to the given field whenever a `new Model` is issued | ||
`USAGE:` | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('created_at', kind.auto); | ||
}); | ||
var x = new Foo(); | ||
x.created_at.toFormat("DD/MM/YYYY") /* should be "today" */ | ||
``` | ||
shorthand for the regexp `/^\w+[@]\w+[.]\w{2,}$/` | ||
`USAGE:` | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('example', kind.email); | ||
}); | ||
``` | ||
### string | ||
any string of any size, although it's trimmed | ||
`USAGE:` | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('example', kind.string); | ||
}); | ||
``` | ||
### slug | ||
any string of any size, will me returned as a slug, | ||
for example the input `Hello World` turns into `hello-world` | ||
`USAGE:` | ||
```javascript | ||
var Foo = models.declare('Foo', function(it, kind){ | ||
it.has.field('example', kind.slug); | ||
}); | ||
``` | ||
## saving instances | ||
```javascript | ||
var assert = require('assert'); | ||
var lettuce_instructions = new BuildInstruction({ | ||
name: 'Lettuce Unit Tests', | ||
repository_address: 'git://github.com/gabrielfalcao/lettuce.git', | ||
build_command: 'make unit' | ||
}); | ||
lettuce_instructions.save(function(err, pk, model_instance, storage, redis_connection){ | ||
assert.equal(pk, 'clay:BuildInstruction:id:1'); | ||
}); | ||
``` | ||
## relationships | ||
Clay ["kind of](http://en.wikipedia.org/wiki/NoSQL) supports | ||
one-to-many and many-to-one "relationships", in order to declare them | ||
you can just use either: `it.has.one()` or `it.has.many()` | ||
declaration. | ||
Nevertheless there are two important things you must know about how | ||
Clay leverages the relationship feature: | ||
### 1. Relationships go through both lanes | ||
In my opinion, a snippet is worth than words: | ||
Supposing you have this declaration | ||
```javascript | ||
var Person = models.declare("Person", function(it, kind){ | ||
it.has.field("name", kind.string); | ||
}); | ||
var Belonging = models.declare("Belonging", function(it, kind){ | ||
it.has.field("description", kind.string); | ||
it.has.one("owner", Person, "belongings"); | ||
}); | ||
``` | ||
This is telling Clay that *a Belonging has an owner*, as well as that *a Person has many belongings* | ||
Technically speaking, it means that internally Clay will make the declaration above idempodent to the example below: | ||
```javascript | ||
var Belonging = models.declare("Belonging", function(it, kind){ | ||
it.has.field("description", kind.string); | ||
}); | ||
var Person = models.declare("Person", function(it, kind){ | ||
it.has.field("name", kind.string); | ||
it.has.many("belonging", Person, "owner"); | ||
}); | ||
``` | ||
Now, ain't that so cool? | ||
Now whenever you persist your data, as long as the dynamically | ||
assigned objects were already persisted, their references will be kept | ||
tracked by its related objects. | ||
## behavior: methods and properties | ||
Clay provides an object-oriented-friendly object declaration. | ||
So as expected, you can define class-level methods, instance-level | ||
methods, getters and setters. | ||
Once again, using code to show the magic: | ||
### class methods: | ||
```javascript | ||
var Animal = models.declare("Animal", function(it, kind){ | ||
it.has.field("name", kind.string); | ||
it.has.field("sex", kind.string); | ||
it.has.class_method("create_male", function(name){ | ||
return new this({sex: "male", name: name}); | ||
}); | ||
}); | ||
// now you can do: | ||
var leo = Animal.create_male("Lion"); | ||
assert.equal(leo.name, "Lion"); | ||
assert.equal(leo.sex, "male"); | ||
``` | ||
### instance methods: | ||
```javascript | ||
var Person = models.declare("Person", function(it, kind){ | ||
it.has.field("name", kind.string); | ||
it.has.method("say_hello", function(){ | ||
// yes, "this" is bound to the actual instance | ||
console.log("Hello, I am " + this.name); | ||
}); | ||
}); | ||
var john = new Person({name: "John Doe"}); | ||
john.say_hello(); | ||
``` | ||
would produce the output | ||
```bash | ||
Hello, I am John Doe | ||
``` | ||
### getters: | ||
```javascript | ||
var BankAccount = models.declare("BankAccount", function(it, kind){ | ||
it.has.field("balance", kind.numeric); | ||
it.has.getter("is_positive", function(){ | ||
return this.balance > 0; | ||
}); | ||
it.has.getter("is_negative", function(){ | ||
return this.balance < 0; | ||
}); | ||
}); | ||
var red = new BankAccount({balance: -5000}); | ||
red.is_negative() // true | ||
var green = new BankAccount({balance: 99}); | ||
green.is_positive() // true | ||
``` | ||
would produce the output | ||
```bash | ||
Hello, I am John Doe | ||
``` | ||
### setters: | ||
```javascript | ||
var Person = models.declare("Person", function(it, kind){ | ||
it.has.field("first_name", kind.string); | ||
it.has.field("last_name", kind.string); | ||
it.has.setter("name", function(name){ | ||
var parts = name.trim().split(/\s+/); | ||
if (parts.length == 2) { | ||
this.first_name = parts[0]; | ||
this.last_name = parts[1]; | ||
} else { | ||
this.first_name = name; | ||
this.last_name = ""; | ||
} | ||
}); | ||
it.has.getter("name", function(){ | ||
return [this.first_name, this.last_name].join(' '); | ||
}); | ||
}); | ||
var john = new Person(); | ||
john.name = "John Doe"; | ||
assert.equal(john.first_name, "John"); | ||
assert.equal(john.last_name, "John"); | ||
``` | ||
## saving instances and its relationships | ||
```javascript | ||
var assert = require('assert'); | ||
var gabrielfalcao = new Build({ | ||
name: 'Gabriel Falcão', | ||
email: 'gabriel@yipit.com', | ||
password: '123' | ||
}); | ||
var b1 = new Build({ | ||
status: 0, | ||
error: '', | ||
output: 'Worked!', | ||
author: gabrielfalcao | ||
}); | ||
var b2 = new Build({ | ||
status: 32, | ||
error: 'Failed!', | ||
output: 'OOps', | ||
author: gabrielfalcao | ||
}); | ||
var lettuce_unit = new BuildInstruction({ | ||
name: "Lettuce Unit Tests", | ||
repository_address: 'git://github.com/gabrielfalcao/lettuce.git', | ||
build_command: 'make unit', | ||
owner: gabrielfalcao, | ||
builds: [b1, b2] | ||
}); | ||
gabrielfalcao.save(function(e, gabrielfalcao_pk){ | ||
b1.save(function(e, b1_pk){ | ||
b2.save(function(e, b2_pk){ | ||
lettuce_unit.save(function(e4, lettuce_unit_pk){ | ||
// from now on, whenever you fetch the | ||
// BuildInstruction 'Lettuce Unit Tests', the related objects | ||
// will be automatically fetched from the database | ||
}); | ||
}); | ||
}); | ||
}); | ||
``` | ||
## finding by id | ||
```javascript | ||
BuildInstruction.find_by_id(1, function(e, found){ | ||
assert.equal(found.name, 'Lettuce Unit Tests'); | ||
assert.equal(found.repository_address, 'git://github.com/gabrielfalcao/lettuce.git'); | ||
assert.equal( | ||
"Will now build: {name}".render(found), | ||
"Will now build: Lettuce Unit Tests" | ||
); | ||
}); | ||
``` | ||
## finding by any field | ||
Clay attempts to be really simple to use, and for the sake of this | ||
fact there is a lot of *magic* here. | ||
When you declare any model with Clay, you have special class-methods | ||
available right away. | ||
In order to search by any declared field, all you need to do is call | ||
`YourModel.find_by_fieldname`, where `YourModel` is the return of | ||
`models.declare()` and `fieldname` is the name of any fields you have | ||
declared. All of them will be available. | ||
It takes just 2 parameters: the `RegExp` that will be used to match | ||
against values and a callback. | ||
The callback, takes 2 parameters: an error and an array with instances | ||
of models. | ||
## example | ||
```javascript | ||
var adam = new User({ | ||
name: "Adam Nelson", | ||
email: "adam@yipit.com", | ||
password: '123' | ||
}); | ||
adam.save(function(e, pk, instance){ | ||
User.find_by_email(/yipit.com$/, function(e, found){ | ||
assert.equal(found.length, 1); | ||
assert.equal(found.first.name, 'Adam Nelson'); | ||
assert.equal(found.first.email, 'adam@yipit.com'); | ||
}); | ||
}); | ||
``` | ||
# Hacking / Contributing | ||
## 1. fork and clone the project | ||
## 2. install [npm](http://npmjs.org) | ||
## 3. install the dependencies with npm: | ||
```bash | ||
cd clay.js | ||
npm install | ||
``` | ||
## 4. install [Jake](https://github.com/mde/jake): | ||
```bash | ||
npm install -g jshint | ||
``` | ||
## 5. run the tests | ||
```bash | ||
jake unit | ||
jake functional | ||
``` | ||
**PS.:** *you need to have redis running in order to make the functional tests running* | ||
## 6. set up the pre-commit hook: | ||
```console | ||
cd path/to/emerald | ||
``` | ||
```console | ||
ln -s .development/pre-commit-hook .git/hooks/pre-commit | ||
chmod +x .git/hooks/pre-commit | ||
``` | ||
## 7. send the pull request | ||
# License | ||
<clay - active record for node.js with redis backend> | ||
Copyright (C) <2011> Gabriel Falcão <gabriel@yipit.com> | ||
Permission is hereby granted, free of charge, to any person | ||
obtaining a copy of this software and associated documentation | ||
files (the "Software"), to deal in the Software without | ||
restriction, including without limitation the rights to use, | ||
copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the | ||
Software is furnished to do so, subject to the following | ||
conditions: | ||
The above copyright notice and this permission notice shall be | ||
included in all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | ||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | ||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | ||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | ||
OTHER DEALINGS IN THE SOFTWARE. | ||
You can view the [full changelog here](CHANGELOG.md). |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 18 instances in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No contributors or author data
MaintenancePackage does not specify a list of contributors or an author in package.json.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
13957885
0
0
748
109088
1
0
1
93
20
- Removedasync@>= 0.1.15
- Removeddate-utils@>= 1.2.5
- Removedredis@>= 0.6.7
- Removedunderscore@>= 1.2.2
- Removed@redis/bloom@1.2.0(transitive)
- Removed@redis/client@1.6.0(transitive)
- Removed@redis/graph@1.1.1(transitive)
- Removed@redis/json@1.0.7(transitive)
- Removed@redis/search@1.2.0(transitive)
- Removed@redis/time-series@1.1.0(transitive)
- Removedasync@3.2.6(transitive)
- Removedcluster-key-slot@1.1.2(transitive)
- Removeddate-utils@1.2.21(transitive)
- Removedgeneric-pool@3.9.0(transitive)
- Removedredis@4.7.0(transitive)
- Removedunderscore@1.13.7(transitive)
- Removedyallist@4.0.0(transitive)