不要怂,就是干,撸起袖子干!

Commit 7b798eb0 by Mick Hansen

Merge pull request #1595 from janmeier/apidocs

Updated the in-code API docs, and added a new way to generate them
2 parents 1824379a ff755e29
......@@ -9,3 +9,5 @@ test/binary/tmp/*
test/tmp/*
test/sqlite/test.sqlite
coverage-*
docs/*.md
docs/*.html
\ No newline at end of file
YUI.add("yuidoc-meta", function(Y) {
Y.YUIDoc = { meta: {
"classes": [
"QueryInterface",
"Sequelize"
],
"modules": [
"Sequelize"
],
"allModules": [
{
"displayName": "Sequelize",
"name": "Sequelize",
"description": "The entry point."
}
]
} };
});
\ No newline at end of file
/*
Font sizes for all selectors other than the body are given in percentages,
with 100% equal to 13px. To calculate a font size percentage, multiply the
desired size in pixels by 7.6923076923.
Here's a quick lookup table:
10px - 76.923%
11px - 84.615%
12px - 92.308%
13px - 100%
14px - 107.692%
15px - 115.385%
16px - 123.077%
17px - 130.769%
18px - 138.462%
19px - 146.154%
20px - 153.846%
*/
html {
background: #fff;
color: #333;
overflow-y: scroll;
}
body {
font: 13px/1.4 'Lucida Grande', 'Lucida Sans Unicode', 'DejaVu Sans', 'Bitstream Vera Sans', 'Helvetica', 'Arial', sans-serif;
margin: 0;
padding: 0;
}
/* -- Links ----------------------------------------------------------------- */
a {
color: #356de4;
text-decoration: none;
}
.hidden {
display: none;
}
a:hover { text-decoration: underline; }
/* "Jump to Table of Contents" link is shown to assistive tools, but hidden from
sight until it's focused. */
.jump {
position: absolute;
padding: 3px 6px;
left: -99999px;
top: 0;
}
.jump:focus { left: 40%; }
/* -- Paragraphs ------------------------------------------------------------ */
p { margin: 1.3em 0; }
dd p, td p { margin-bottom: 0; }
dd p:first-child, td p:first-child { margin-top: 0; }
/* -- Headings -------------------------------------------------------------- */
h1, h2, h3, h4, h5, h6 {
color: #D98527;/*was #f80*/
font-family: 'Trebuchet MS', sans-serif;
font-weight: bold;
line-height: 1.1;
margin: 1.1em 0 0.5em;
}
h1 {
font-size: 184.6%;
color: #30418C;
margin: 0.75em 0 0.5em;
}
h2 {
font-size: 153.846%;
color: #E48A2B;
}
h3 { font-size: 138.462%; }
h4 {
border-bottom: 1px solid #DBDFEA;
color: #E48A2B;
font-size: 115.385%;
font-weight: normal;
padding-bottom: 2px;
}
h5, h6 { font-size: 107.692%; }
/* -- Code and examples ----------------------------------------------------- */
code, kbd, pre, samp {
font-family: Menlo, Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Courier New', Courier, monospace;
font-size: 92.308%;
line-height: 1.35;
}
p code, p kbd, p samp {
background: #FCFBFA;
border: 1px solid #EFEEED;
padding: 0 3px;
}
a code, a kbd, a samp,
pre code, pre kbd, pre samp,
table code, table kbd, table samp,
.intro code, .intro kbd, .intro samp,
.toc code, .toc kbd, .toc samp {
background: none;
border: none;
padding: 0;
}
pre.code, pre.terminal, pre.cmd {
overflow-x: auto;
*overflow-x: scroll;
padding: 0.3em 0.6em;
}
pre.code {
background: #FCFBFA;
border: 1px solid #EFEEED;
border-left-width: 5px;
}
pre.terminal, pre.cmd {
background: #F0EFFC;
border: 1px solid #D0CBFB;
border-left: 5px solid #D0CBFB;
}
/* Don't reduce the font size of <code>/<kbd>/<samp> elements inside <pre>
blocks. */
pre code, pre kbd, pre samp { font-size: 100%; }
/* Used to denote text that shouldn't be selectable, such as line numbers or
shell prompts. Guess which browser this doesn't work in. */
.noselect {
-moz-user-select: -moz-none;
-khtml-user-select: none;
-webkit-user-select: none;
-o-user-select: none;
user-select: none;
}
/* -- Lists ----------------------------------------------------------------- */
dd { margin: 0.2em 0 0.7em 1em; }
dl { margin: 1em 0; }
dt { font-weight: bold; }
/* -- Tables ---------------------------------------------------------------- */
caption, th { text-align: left; }
table {
border-collapse: collapse;
width: 100%;
}
td, th {
border: 1px solid #fff;
padding: 5px 12px;
vertical-align: top;
}
td { background: #E6E9F5; }
td dl { margin: 0; }
td dl dl { margin: 1em 0; }
td pre:first-child { margin-top: 0; }
th {
background: #D2D7E6;/*#97A0BF*/
border-bottom: none;
border-top: none;
color: #000;/*#FFF1D5*/
font-family: 'Trebuchet MS', sans-serif;
font-weight: bold;
line-height: 1.3;
white-space: nowrap;
}
/* -- Layout and Content ---------------------------------------------------- */
#doc {
margin: auto;
min-width: 1024px;
}
.content { padding: 0 20px 0 25px; }
.sidebar {
padding: 0 15px 0 10px;
}
#bd {
padding: 7px 0 130px;
position: relative;
width: 99%;
}
/* -- Table of Contents ----------------------------------------------------- */
/* The #toc id refers to the single global table of contents, while the .toc
class refers to generic TOC lists that could be used throughout the page. */
.toc code, .toc kbd, .toc samp { font-size: 100%; }
.toc li { font-weight: bold; }
.toc li li { font-weight: normal; }
/* -- Intro and Example Boxes ----------------------------------------------- */
/*
.intro, .example { margin-bottom: 2em; }
.example {
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
-moz-box-shadow: 0 0 5px #bfbfbf;
-webkit-box-shadow: 0 0 5px #bfbfbf;
box-shadow: 0 0 5px #bfbfbf;
padding: 1em;
}
.intro {
background: none repeat scroll 0 0 #F0F1F8; border: 1px solid #D4D8EB; padding: 0 1em;
}
*/
/* -- Other Styles ---------------------------------------------------------- */
/* These are probably YUI-specific, and should be moved out of Selleck's default
theme. */
.button {
border: 1px solid #dadada;
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
color: #444;
display: inline-block;
font-family: Helvetica, Arial, sans-serif;
font-size: 92.308%;
font-weight: bold;
padding: 4px 13px 3px;
-moz-text-shadow: 1px 1px 0 #fff;
-webkit-text-shadow: 1px 1px 0 #fff;
text-shadow: 1px 1px 0 #fff;
white-space: nowrap;
background: #EFEFEF; /* old browsers */
background: -moz-linear-gradient(top, #f5f5f5 0%, #efefef 50%, #e5e5e5 51%, #dfdfdf 100%); /* firefox */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f5f5f5), color-stop(50%,#efefef), color-stop(51%,#e5e5e5), color-stop(100%,#dfdfdf)); /* webkit */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f5f5f5', endColorstr='#dfdfdf',GradientType=0 ); /* ie */
}
.button:hover {
border-color: #466899;
color: #fff;
text-decoration: none;
-moz-text-shadow: 1px 1px 0 #222;
-webkit-text-shadow: 1px 1px 0 #222;
text-shadow: 1px 1px 0 #222;
background: #6396D8; /* old browsers */
background: -moz-linear-gradient(top, #6396D8 0%, #5A83BC 50%, #547AB7 51%, #466899 100%); /* firefox */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#6396D8), color-stop(50%,#5A83BC), color-stop(51%,#547AB7), color-stop(100%,#466899)); /* webkit */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#6396D8', endColorstr='#466899',GradientType=0 ); /* ie */
}
.newwindow { text-align: center; }
.header .version em {
display: block;
text-align: right;
}
#classdocs .item {
border-bottom: 1px solid #466899;
margin: 1em 0;
padding: 1.5em;
}
#classdocs .item .params p,
#classdocs .item .returns p,{
display: inline;
}
#classdocs .item em code, #classdocs .item em.comment {
color: green;
}
#classdocs .item em.comment a {
color: green;
text-decoration: underline;
}
#classdocs .foundat {
font-size: 11px;
font-style: normal;
}
.attrs .emits {
margin-left: 2em;
padding: .5em;
border-left: 1px dashed #ccc;
}
abbr {
border-bottom: 1px dashed #ccc;
font-size: 80%;
cursor: help;
}
.prettyprint li.L0,
.prettyprint li.L1,
.prettyprint li.L2,
.prettyprint li.L3,
.prettyprint li.L5,
.prettyprint li.L6,
.prettyprint li.L7,
.prettyprint li.L8 {
list-style: decimal;
}
ul li p {
margin-top: 0;
}
.method .name {
font-size: 110%;
}
.apidocs .methods .extends .method,
.apidocs .properties .extends .property,
.apidocs .attrs .extends .attr,
.apidocs .events .extends .event {
font-weight: bold;
}
.apidocs .methods .extends .inherited,
.apidocs .properties .extends .inherited,
.apidocs .attrs .extends .inherited,
.apidocs .events .extends .inherited {
font-weight: normal;
}
#hd {
background: whiteSmoke;
background: -moz-linear-gradient(top,#DCDBD9 0,#F6F5F3 100%);
background: -webkit-gradient(linear,left top,left bottom,color-stop(0%,#DCDBD9),color-stop(100%,#F6F5F3));
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#dcdbd9',endColorstr='#F6F5F3',GradientType=0);
border-bottom: 1px solid #DFDFDF;
padding: 0 15px 1px 20px;
margin-bottom: 15px;
}
#hd img {
margin-right: 10px;
vertical-align: middle;
}
/* -- API Docs CSS ---------------------------------------------------------- */
/*
This file is organized so that more generic styles are nearer the top, and more
specific styles are nearer the bottom of the file. This allows us to take full
advantage of the cascade to avoid redundant style rules. Please respect this
convention when making changes.
*/
/* -- Generic TabView styles ------------------------------------------------ */
/*
These styles apply to all API doc tabviews. To change styles only for a
specific tabview, see the other sections below.
*/
.yui3-js-enabled .apidocs .tabview {
visibility: hidden; /* Hide until the TabView finishes rendering. */
_visibility: visible;
}
.apidocs .tabview.yui3-tabview-content { visibility: visible; }
.apidocs .tabview .yui3-tabview-panel { background: #fff; }
/* -- Generic Content Styles ------------------------------------------------ */
/* Headings */
h2, h3, h4, h5, h6 {
border: none;
color: #30418C;
font-weight: bold;
text-decoration: none;
}
.link-docs {
float: right;
font-size: 15px;
margin: 4px 4px 6px;
padding: 6px 30px 5px;
}
.apidocs { zoom: 1; }
/* Generic box styles. */
.apidocs .box {
border: 1px solid;
border-radius: 3px;
margin: 1em 0;
padding: 0 1em;
}
/* A flag is a compact, capsule-like indicator of some kind. It's used to
indicate private and protected items, item return types, etc. in an
attractive and unobtrusive way. */
.apidocs .flag {
background: #bababa;
border-radius: 3px;
color: #fff;
font-size: 11px;
margin: 0 0.5em;
padding: 2px 4px 1px;
}
/* Class/module metadata such as "Uses", "Extends", "Defined in", etc. */
.apidocs .meta {
background: #f9f9f9;
border-color: #efefef;
color: #555;
font-size: 11px;
padding: 3px 6px;
}
.apidocs .meta p { margin: 0; }
/* Deprecation warning. */
.apidocs .box.deprecated,
.apidocs .flag.deprecated {
background: #fdac9f;
border: 1px solid #fd7775;
}
.apidocs .box.deprecated p { margin: 0.5em 0; }
.apidocs .flag.deprecated { color: #333; }
/* Module/Class intro description. */
.apidocs .intro {
background: #f0f1f8;
border-color: #d4d8eb;
}
/* Loading spinners. */
#bd.loading .apidocs,
#api-list.loading .yui3-tabview-panel {
background: #fff url(../img/spinner.gif) no-repeat center 70px;
min-height: 150px;
}
#bd.loading .apidocs .content,
#api-list.loading .yui3-tabview-panel .apis {
display: none;
}
.apidocs .no-visible-items { color: #666; }
/* Generic inline list. */
.apidocs ul.inline {
display: inline;
list-style: none;
margin: 0;
padding: 0;
}
.apidocs ul.inline li { display: inline; }
/* Comma-separated list. */
.apidocs ul.commas li:after { content: ','; }
.apidocs ul.commas li:last-child:after { content: ''; }
/* Keyboard shortcuts. */
kbd .cmd { font-family: Monaco, Helvetica; }
/* -- Generic Access Level styles ------------------------------------------- */
.apidocs .item.protected,
.apidocs .item.private,
.apidocs .index-item.protected,
.apidocs .index-item.deprecated,
.apidocs .index-item.private {
display: none;
}
.show-deprecated .item.deprecated,
.show-deprecated .index-item.deprecated,
.show-protected .item.protected,
.show-protected .index-item.protected,
.show-private .item.private,
.show-private .index-item.private {
display: block;
}
.hide-inherited .item.inherited,
.hide-inherited .index-item.inherited {
display: none;
}
/* -- Generic Item Index styles --------------------------------------------- */
.apidocs .index { margin: 1.5em 0 3em; }
.apidocs .index h3 {
border-bottom: 1px solid #efefef;
color: #333;
font-size: 13px;
margin: 2em 0 0.6em;
padding-bottom: 2px;
}
.apidocs .index .no-visible-items { margin-top: 2em; }
.apidocs .index-list {
border-color: #efefef;
font-size: 12px;
list-style: none;
margin: 0;
padding: 0;
-moz-column-count: 4;
-moz-column-gap: 10px;
-moz-column-width: 170px;
-ms-column-count: 4;
-ms-column-gap: 10px;
-ms-column-width: 170px;
-o-column-count: 4;
-o-column-gap: 10px;
-o-column-width: 170px;
-webkit-column-count: 4;
-webkit-column-gap: 10px;
-webkit-column-width: 170px;
column-count: 4;
column-gap: 10px;
column-width: 170px;
}
.apidocs .no-columns .index-list {
-moz-column-count: 1;
-ms-column-count: 1;
-o-column-count: 1;
-webkit-column-count: 1;
column-count: 1;
}
.apidocs .index-item { white-space: nowrap; }
.apidocs .index-item .flag {
background: none;
border: none;
color: #afafaf;
display: inline;
margin: 0 0 0 0.2em;
padding: 0;
}
/* -- Generic API item styles ----------------------------------------------- */
.apidocs .args {
display: inline;
margin: 0 0.5em;
}
.apidocs .flag.chainable { background: #46ca3b; }
.apidocs .flag.protected { background: #9b86fc; }
.apidocs .flag.private { background: #fd6b1b; }
.apidocs .flag.async { background: #356de4; }
.apidocs .flag.required { background: #e60923; }
.apidocs .item {
border-bottom: 1px solid #efefef;
margin: 1.5em 0 2em;
padding-bottom: 2em;
}
.apidocs .item h4,
.apidocs .item h5,
.apidocs .item h6 {
color: #333;
font-family: inherit;
font-size: 100%;
}
.apidocs .item .description p,
.apidocs .item pre.code {
margin: 1em 0 0;
}
.apidocs .item .meta {
background: none;
border: none;
padding: 0;
}
.apidocs .item .name {
display: inline;
font-size: 14px;
}
.apidocs .item .type,
.apidocs .item .type a,
.apidocs .returns-inline {
color: #555;
}
.apidocs .item .type,
.apidocs .returns-inline {
font-size: 11px;
margin: 0 0 0 0;
}
.apidocs .item .type a { border-bottom: 1px dotted #afafaf; }
.apidocs .item .type a:hover { border: none; }
/* -- Item Parameter List --------------------------------------------------- */
.apidocs .params-list {
list-style: square;
margin: 1em 0 0 2em;
padding: 0;
}
.apidocs .param { margin-bottom: 1em; }
.apidocs .param .type,
.apidocs .param .type a {
color: #666;
}
.apidocs .param .type {
margin: 0 0 0 0.5em;
*margin-left: 0.5em;
}
.apidocs .param-name { font-weight: bold; }
/* -- Item "Emits" block ---------------------------------------------------- */
.apidocs .item .emits {
background: #f9f9f9;
border-color: #eaeaea;
}
/* -- Item "Returns" block -------------------------------------------------- */
.apidocs .item .returns .type,
.apidocs .item .returns .type a {
font-size: 100%;
margin: 0;
}
/* -- Class Constructor block ----------------------------------------------- */
.apidocs .constructor .item {
border: none;
padding-bottom: 0;
}
/* -- File Source View ------------------------------------------------------ */
.apidocs .file pre.code,
#doc .apidocs .file pre.prettyprint {
background: inherit;
border: none;
overflow: visible;
padding: 0;
}
.apidocs .L0,
.apidocs .L1,
.apidocs .L2,
.apidocs .L3,
.apidocs .L4,
.apidocs .L5,
.apidocs .L6,
.apidocs .L7,
.apidocs .L8,
.apidocs .L9 {
background: inherit;
}
/* -- Submodule List -------------------------------------------------------- */
.apidocs .module-submodule-description {
font-size: 12px;
margin: 0.3em 0 1em;
}
.apidocs .module-submodule-description p:first-child { margin-top: 0; }
/* -- Sidebar TabView ------------------------------------------------------- */
#api-tabview { margin-top: 0.6em; }
#api-tabview-filter,
#api-tabview-panel {
border: 1px solid #dfdfdf;
}
#api-tabview-filter {
border-bottom: none;
border-top: none;
padding: 0.6em 10px 0 10px;
}
#api-tabview-panel { border-top: none; }
#api-filter { width: 97%; }
/* -- Content TabView ------------------------------------------------------- */
#classdocs .yui3-tabview-panel { border: none; }
/* -- Source File Contents -------------------------------------------------- */
.prettyprint li.L0,
.prettyprint li.L1,
.prettyprint li.L2,
.prettyprint li.L3,
.prettyprint li.L5,
.prettyprint li.L6,
.prettyprint li.L7,
.prettyprint li.L8 {
list-style: decimal;
}
/* -- API options ----------------------------------------------------------- */
#api-options {
font-size: 11px;
margin-top: 2.2em;
position: absolute;
right: 1.5em;
}
/*#api-options label { margin-right: 0.6em; }*/
/* -- API list -------------------------------------------------------------- */
#api-list {
margin-top: 1.5em;
*zoom: 1;
}
.apis {
font-size: 12px;
line-height: 1.4;
list-style: none;
margin: 0;
padding: 0.5em 0 0.5em 0.4em;
}
.apis a {
border: 1px solid transparent;
display: block;
margin: 0 0 0 -4px;
padding: 1px 4px 0;
text-decoration: none;
_border: none;
_display: inline;
}
.apis a:hover,
.apis a:focus {
background: #E8EDFC;
background: -moz-linear-gradient(top, #e8edfc 0%, #becef7 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#E8EDFC), color-stop(100%,#BECEF7));
border-color: #AAC0FA;
border-radius: 3px;
color: #333;
outline: none;
}
.api-list-item a:hover,
.api-list-item a:focus {
font-weight: bold;
text-shadow: 1px 1px 1px #fff;
}
.apis .message { color: #888; }
.apis .result a { padding: 3px 5px 2px; }
.apis .result .type {
right: 4px;
top: 7px;
}
.api-list-item .yui3-highlight {
font-weight: bold;
}
<!doctype html>
<html>
<head>
<title>Redirector</title>
<meta http-equiv="refresh" content="0;url=../">
</head>
<body>
<a href="../">Click here to redirect</a>
</body>
</html>
YUI.add('api-filter', function (Y) {
Y.APIFilter = Y.Base.create('apiFilter', Y.Base, [Y.AutoCompleteBase], {
// -- Initializer ----------------------------------------------------------
initializer: function () {
this._bindUIACBase();
this._syncUIACBase();
},
getDisplayName: function(name) {
Y.each(Y.YUIDoc.meta.allModules, function(i) {
if (i.name === name && i.displayName) {
name = i.displayName;
}
});
return name;
}
}, {
// -- Attributes -----------------------------------------------------------
ATTRS: {
resultHighlighter: {
value: 'phraseMatch'
},
// May be set to "classes" or "modules".
queryType: {
value: 'classes'
},
source: {
valueFn: function() {
var self = this;
return function(q) {
var data = Y.YUIDoc.meta[self.get('queryType')],
out = [];
Y.each(data, function(v) {
if (v.toLowerCase().indexOf(q.toLowerCase()) > -1) {
out.push(v);
}
});
return out;
};
}
}
}
});
}, '3.4.0', {requires: [
'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources'
]});
YUI.add('api-list', function (Y) {
var Lang = Y.Lang,
YArray = Y.Array,
APIList = Y.namespace('APIList'),
classesNode = Y.one('#api-classes'),
inputNode = Y.one('#api-filter'),
modulesNode = Y.one('#api-modules'),
tabviewNode = Y.one('#api-tabview'),
tabs = APIList.tabs = {},
filter = APIList.filter = new Y.APIFilter({
inputNode : inputNode,
maxResults: 1000,
on: {
results: onFilterResults
}
}),
search = APIList.search = new Y.APISearch({
inputNode : inputNode,
maxResults: 100,
on: {
clear : onSearchClear,
results: onSearchResults
}
}),
tabview = APIList.tabview = new Y.TabView({
srcNode : tabviewNode,
panelNode: '#api-tabview-panel',
render : true,
on: {
selectionChange: onTabSelectionChange
}
}),
focusManager = APIList.focusManager = tabviewNode.plug(Y.Plugin.NodeFocusManager, {
circular : true,
descendants: '#api-filter, .yui3-tab-panel-selected .api-list-item a, .yui3-tab-panel-selected .result a',
keys : {next: 'down:40', previous: 'down:38'}
}).focusManager,
LIST_ITEM_TEMPLATE =
'<li class="api-list-item {typeSingular}">' +
'<a href="{rootPath}{typePlural}/{name}.html">{displayName}</a>' +
'</li>';
// -- Init ---------------------------------------------------------------------
// Duckpunch FocusManager's key event handling to prevent it from handling key
// events when a modifier is pressed.
Y.before(function (e, activeDescendant) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
return new Y.Do.Prevent();
}
}, focusManager, '_focusPrevious', focusManager);
Y.before(function (e, activeDescendant) {
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) {
return new Y.Do.Prevent();
}
}, focusManager, '_focusNext', focusManager);
// Create a mapping of tabs in the tabview so we can refer to them easily later.
tabview.each(function (tab, index) {
var name = tab.get('label').toLowerCase();
tabs[name] = {
index: index,
name : name,
tab : tab
};
});
// Switch tabs on Ctrl/Cmd-Left/Right arrows.
tabviewNode.on('key', onTabSwitchKey, 'down:37,39');
// Focus the filter input when the `/` key is pressed.
Y.one(Y.config.doc).on('key', onSearchKey, 'down:83');
// Keep the Focus Manager up to date.
inputNode.on('focus', function () {
focusManager.set('activeDescendant', inputNode);
});
// Update all tabview links to resolved URLs.
tabview.get('panelNode').all('a').each(function (link) {
link.setAttribute('href', link.get('href'));
});
// -- Private Functions --------------------------------------------------------
function getFilterResultNode() {
return filter.get('queryType') === 'classes' ? classesNode : modulesNode;
}
// -- Event Handlers -----------------------------------------------------------
function onFilterResults(e) {
var frag = Y.one(Y.config.doc.createDocumentFragment()),
resultNode = getFilterResultNode(),
typePlural = filter.get('queryType'),
typeSingular = typePlural === 'classes' ? 'class' : 'module';
if (e.results.length) {
YArray.each(e.results, function (result) {
frag.append(Lang.sub(LIST_ITEM_TEMPLATE, {
rootPath : APIList.rootPath,
displayName : filter.getDisplayName(result.highlighted),
name : result.text,
typePlural : typePlural,
typeSingular: typeSingular
}));
});
} else {
frag.append(
'<li class="message">' +
'No ' + typePlural + ' found.' +
'</li>'
);
}
resultNode.empty(true);
resultNode.append(frag);
focusManager.refresh();
}
function onSearchClear(e) {
focusManager.refresh();
}
function onSearchKey(e) {
var target = e.target;
if (target.test('input,select,textarea')
|| target.get('isContentEditable')) {
return;
}
e.preventDefault();
inputNode.focus();
focusManager.refresh();
}
function onSearchResults(e) {
var frag = Y.one(Y.config.doc.createDocumentFragment());
if (e.results.length) {
YArray.each(e.results, function (result) {
frag.append(result.display);
});
} else {
frag.append(
'<li class="message">' +
'No results found. Maybe you\'ll have better luck with a ' +
'different query?' +
'</li>'
);
}
focusManager.refresh();
}
function onTabSelectionChange(e) {
var tab = e.newVal,
name = tab.get('label').toLowerCase();
tabs.selected = {
index: tab.get('index'),
name : name,
tab : tab
};
switch (name) {
case 'classes': // fallthru
case 'modules':
filter.setAttrs({
minQueryLength: 0,
queryType : name
});
search.set('minQueryLength', -1);
// Only send a request if this isn't the initially-selected tab.
if (e.prevVal) {
filter.sendRequest(filter.get('value'));
}
break;
case 'everything':
filter.set('minQueryLength', -1);
search.set('minQueryLength', 1);
if (search.get('value')) {
search.sendRequest(search.get('value'));
} else {
inputNode.focus();
}
break;
default:
// WTF? We shouldn't be here!
filter.set('minQueryLength', -1);
search.set('minQueryLength', -1);
}
if (focusManager) {
setTimeout(function () {
focusManager.refresh();
}, 1);
}
}
function onTabSwitchKey(e) {
var currentTabIndex = tabs.selected.index;
if (!(e.ctrlKey || e.metaKey)) {
return;
}
e.preventDefault();
switch (e.keyCode) {
case 37: // left arrow
if (currentTabIndex > 0) {
tabview.selectChild(currentTabIndex - 1);
inputNode.focus();
}
break;
case 39: // right arrow
if (currentTabIndex < (Y.Object.size(tabs) - 2)) {
tabview.selectChild(currentTabIndex + 1);
inputNode.focus();
}
break;
}
}
}, '3.4.0', {requires: [
'api-filter', 'api-search', 'event-key', 'node-focusmanager', 'tabview'
]});
YUI.add('api-search', function (Y) {
var Lang = Y.Lang,
Node = Y.Node,
YArray = Y.Array;
Y.APISearch = Y.Base.create('apiSearch', Y.Base, [Y.AutoCompleteBase], {
// -- Public Properties ----------------------------------------------------
RESULT_TEMPLATE:
'<li class="result {resultType}">' +
'<a href="{url}">' +
'<h3 class="title">{name}</h3>' +
'<span class="type">{resultType}</span>' +
'<div class="description">{description}</div>' +
'<span class="className">{class}</span>' +
'</a>' +
'</li>',
// -- Initializer ----------------------------------------------------------
initializer: function () {
this._bindUIACBase();
this._syncUIACBase();
},
// -- Protected Methods ----------------------------------------------------
_apiResultFilter: function (query, results) {
// Filter components out of the results.
return YArray.filter(results, function (result) {
return result.raw.resultType === 'component' ? false : result;
});
},
_apiResultFormatter: function (query, results) {
return YArray.map(results, function (result) {
var raw = Y.merge(result.raw), // create a copy
desc = raw.description || '';
// Convert description to text and truncate it if necessary.
desc = Node.create('<div>' + desc + '</div>').get('text');
if (desc.length > 65) {
desc = Y.Escape.html(desc.substr(0, 65)) + ' &hellip;';
} else {
desc = Y.Escape.html(desc);
}
raw['class'] || (raw['class'] = '');
raw.description = desc;
// Use the highlighted result name.
raw.name = result.highlighted;
return Lang.sub(this.RESULT_TEMPLATE, raw);
}, this);
},
_apiTextLocator: function (result) {
return result.displayName || result.name;
}
}, {
// -- Attributes -----------------------------------------------------------
ATTRS: {
resultFormatter: {
valueFn: function () {
return this._apiResultFormatter;
}
},
resultFilters: {
valueFn: function () {
return this._apiResultFilter;
}
},
resultHighlighter: {
value: 'phraseMatch'
},
resultListLocator: {
value: 'data.results'
},
resultTextLocator: {
valueFn: function () {
return this._apiTextLocator;
}
},
source: {
value: '/api/v1/search?q={query}&count={maxResults}'
}
}
});
}, '3.4.0', {requires: [
'autocomplete-base', 'autocomplete-highlighters', 'autocomplete-sources',
'escape'
]});
YUI().use(
'yuidoc-meta',
'api-list', 'history-hash', 'node-screen', 'node-style', 'pjax',
function (Y) {
var win = Y.config.win,
localStorage = win.localStorage,
bdNode = Y.one('#bd'),
pjax,
defaultRoute,
classTabView,
selectedTab;
// Kill pjax functionality unless serving over HTTP.
if (!Y.getLocation().protocol.match(/^https?\:/)) {
Y.Router.html5 = false;
}
// Create the default route with middleware which enables syntax highlighting
// on the loaded content.
defaultRoute = Y.Pjax.defaultRoute.concat(function (req, res, next) {
prettyPrint();
bdNode.removeClass('loading');
next();
});
pjax = new Y.Pjax({
container : '#docs-main',
contentSelector: '#docs-main > .content',
linkSelector : '#bd a',
titleSelector : '#xhr-title',
navigateOnHash: true,
root : '/',
routes : [
// -- / ----------------------------------------------------------------
{
path : '/(index.html)?',
callbacks: defaultRoute
},
// -- /classes/* -------------------------------------------------------
{
path : '/classes/:class.html*',
callbacks: [defaultRoute, 'handleClasses']
},
// -- /files/* ---------------------------------------------------------
{
path : '/files/*file',
callbacks: [defaultRoute, 'handleFiles']
},
// -- /modules/* -------------------------------------------------------
{
path : '/modules/:module.html*',
callbacks: defaultRoute
}
]
});
// -- Utility Functions --------------------------------------------------------
pjax.checkVisibility = function (tab) {
tab || (tab = selectedTab);
if (!tab) { return; }
var panelNode = tab.get('panelNode'),
visibleItems;
// If no items are visible in the tab panel due to the current visibility
// settings, display a message to that effect.
visibleItems = panelNode.all('.item,.index-item').some(function (itemNode) {
if (itemNode.getComputedStyle('display') !== 'none') {
return true;
}
});
panelNode.all('.no-visible-items').remove();
if (!visibleItems) {
if (Y.one('#index .index-item')) {
panelNode.append(
'<div class="no-visible-items">' +
'<p>' +
'Some items are not shown due to the current visibility ' +
'settings. Use the checkboxes at the upper right of this ' +
'page to change the visibility settings.' +
'</p>' +
'</div>'
);
} else {
panelNode.append(
'<div class="no-visible-items">' +
'<p>' +
'This class doesn\'t provide any methods, properties, ' +
'attributes, or events.' +
'</p>' +
'</div>'
);
}
}
// Hide index sections without any visible items.
Y.all('.index-section').each(function (section) {
var items = 0,
visibleItems = 0;
section.all('.index-item').each(function (itemNode) {
items += 1;
if (itemNode.getComputedStyle('display') !== 'none') {
visibleItems += 1;
}
});
section.toggleClass('hidden', !visibleItems);
section.toggleClass('no-columns', visibleItems < 4);
});
};
pjax.initClassTabView = function () {
if (!Y.all('#classdocs .api-class-tab').size()) {
return;
}
if (classTabView) {
classTabView.destroy();
selectedTab = null;
}
classTabView = new Y.TabView({
srcNode: '#classdocs',
on: {
selectionChange: pjax.onTabSelectionChange
}
});
pjax.updateTabState();
classTabView.render();
};
pjax.initLineNumbers = function () {
var hash = win.location.hash.substring(1),
container = pjax.get('container'),
hasLines, node;
// Add ids for each line number in the file source view.
container.all('.linenums>li').each(function (lineNode, index) {
lineNode.set('id', 'l' + (index + 1));
lineNode.addClass('file-line');
hasLines = true;
});
// Scroll to the desired line.
if (hasLines && /^l\d+$/.test(hash)) {
if ((node = container.getById(hash))) {
win.scroll(0, node.getY());
}
}
};
pjax.initRoot = function () {
var terminators = /^(?:classes|files|modules)$/,
parts = pjax._getPathRoot().split('/'),
root = [],
i, len, part;
for (i = 0, len = parts.length; i < len; i += 1) {
part = parts[i];
if (part.match(terminators)) {
// Makes sure the path will end with a "/".
root.push('');
break;
}
root.push(part);
}
pjax.set('root', root.join('/'));
};
pjax.updateTabState = function (src) {
var hash = win.location.hash.substring(1),
defaultTab, node, tab, tabPanel;
function scrollToNode() {
if (node.hasClass('protected')) {
Y.one('#api-show-protected').set('checked', true);
pjax.updateVisibility();
}
if (node.hasClass('private')) {
Y.one('#api-show-private').set('checked', true);
pjax.updateVisibility();
}
setTimeout(function () {
// For some reason, unless we re-get the node instance here,
// getY() always returns 0.
var node = Y.one('#classdocs').getById(hash);
win.scrollTo(0, node.getY() - 70);
}, 1);
}
if (!classTabView) {
return;
}
if (src === 'hashchange' && !hash) {
defaultTab = 'index';
} else {
if (localStorage) {
defaultTab = localStorage.getItem('tab_' + pjax.getPath()) ||
'index';
} else {
defaultTab = 'index';
}
}
if (hash && (node = Y.one('#classdocs').getById(hash))) {
if ((tabPanel = node.ancestor('.api-class-tabpanel', true))) {
if ((tab = Y.one('#classdocs .api-class-tab.' + tabPanel.get('id')))) {
if (classTabView.get('rendered')) {
Y.Widget.getByNode(tab).set('selected', 1);
} else {
tab.addClass('yui3-tab-selected');
}
}
}
// Scroll to the desired element if this is a hash URL.
if (node) {
if (classTabView.get('rendered')) {
scrollToNode();
} else {
classTabView.once('renderedChange', scrollToNode);
}
}
} else {
tab = Y.one('#classdocs .api-class-tab.' + defaultTab);
// When the `defaultTab` node isn't found, `localStorage` is stale.
if (!tab && defaultTab !== 'index') {
tab = Y.one('#classdocs .api-class-tab.index');
}
if (classTabView.get('rendered')) {
Y.Widget.getByNode(tab).set('selected', 1);
} else {
tab.addClass('yui3-tab-selected');
}
}
};
pjax.updateVisibility = function () {
var container = pjax.get('container');
container.toggleClass('hide-inherited',
!Y.one('#api-show-inherited').get('checked'));
container.toggleClass('show-deprecated',
Y.one('#api-show-deprecated').get('checked'));
container.toggleClass('show-protected',
Y.one('#api-show-protected').get('checked'));
container.toggleClass('show-private',
Y.one('#api-show-private').get('checked'));
pjax.checkVisibility();
};
// -- Route Handlers -----------------------------------------------------------
pjax.handleClasses = function (req, res, next) {
var status = res.ioResponse.status;
// Handles success and local filesystem XHRs.
if (!status || (status >= 200 && status < 300)) {
pjax.initClassTabView();
}
next();
};
pjax.handleFiles = function (req, res, next) {
var status = res.ioResponse.status;
// Handles success and local filesystem XHRs.
if (!status || (status >= 200 && status < 300)) {
pjax.initLineNumbers();
}
next();
};
// -- Event Handlers -----------------------------------------------------------
pjax.onNavigate = function (e) {
var hash = e.hash,
originTarget = e.originEvent && e.originEvent.target,
tab;
if (hash) {
tab = originTarget && originTarget.ancestor('.yui3-tab', true);
if (hash === win.location.hash) {
pjax.updateTabState('hashchange');
} else if (!tab) {
win.location.hash = hash;
}
e.preventDefault();
return;
}
// Only scroll to the top of the page when the URL doesn't have a hash.
this.set('scrollToTop', !e.url.match(/#.+$/));
bdNode.addClass('loading');
};
pjax.onOptionClick = function (e) {
pjax.updateVisibility();
};
pjax.onTabSelectionChange = function (e) {
var tab = e.newVal,
tabId = tab.get('contentBox').getAttribute('href').substring(1);
selectedTab = tab;
// If switching from a previous tab (i.e., this is not the default tab),
// replace the history entry with a hash URL that will cause this tab to
// be selected if the user navigates away and then returns using the back
// or forward buttons.
if (e.prevVal && localStorage) {
localStorage.setItem('tab_' + pjax.getPath(), tabId);
}
pjax.checkVisibility(tab);
};
// -- Init ---------------------------------------------------------------------
pjax.on('navigate', pjax.onNavigate);
pjax.initRoot();
pjax.upgrade();
pjax.initClassTabView();
pjax.initLineNumbers();
pjax.updateVisibility();
Y.APIList.rootPath = pjax.get('root');
Y.one('#api-options').delegate('click', pjax.onOptionClick, 'input');
Y.on('hashchange', function (e) {
pjax.updateTabState('hashchange');
}, win);
});
YUI().use('node', function(Y) {
var code = Y.all('.prettyprint.linenums');
if (code.size()) {
code.each(function(c) {
var lis = c.all('ol li'),
l = 1;
lis.each(function(n) {
n.prepend('<a name="LINENUM_' + l + '"></a>');
l++;
});
});
var h = location.hash;
location.hash = '';
h = h.replace('LINE_', 'LINENUM_');
location.hash = h;
}
});
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Change Log</title>
</head>
<body bgcolor="white">
<a style="float:right" href="README.html">README</a>
<h1>Known Issues</h1>
<ul>
<li>Perl formatting is really crappy. Partly because the author is lazy and
partly because Perl is
<a href="http://www.perlmonks.org/?node_id=663393">hard</a> to parse.
<li>On some browsers, <code>&lt;code&gt;</code> elements with newlines in the text
which use CSS to specify <code>white-space:pre</code> will have the newlines
improperly stripped if the element is not attached to the document at the time
the stripping is done. Also, on IE 6, all newlines will be stripped from
<code>&lt;code&gt;</code> elements because of the way IE6 produces
<code>innerHTML</code>. Workaround: use <code>&lt;pre&gt;</code> for code with
newlines.
</ul>
<h1>Change Log</h1>
<h2>29 March 2007</h2>
<ul>
<li>Added <a href="tests/prettify_test.html#PHP">tests</a> for PHP support
to address
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=3"
>issue 3</a>.
<li>Fixed
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=6"
>bug</a>: <code>prettyPrintOne</code> was not halting. This was not
reachable through the normal entry point.
<li>Fixed
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=4"
>bug</a>: recursing into a script block or PHP tag that was not properly
closed would not silently drop the content.
(<a href="tests/prettify_test.html#issue4">test</a>)
<li>Fixed
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=8"
>bug</a>: was eating tabs
(<a href="tests/prettify_test.html#issue8">test</a>)
<li>Fixed entity handling so that the caveat
<blockquote>
<p>Caveats: please properly escape less-thans. <tt>x&amp;lt;y</tt>
instead of <tt>x&lt;y</tt>, and use <tt>&quot;</tt> instead of
<tt>&amp;quot;</tt> for string delimiters.</p>
</blockquote>
is no longer applicable.
<li>Added noisefree's C#
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=4"
>patch</a>
<li>Added a <a href="http://google-code-prettify.googlecode.com/files/prettify-small.zip">distribution</a> that has comments and
whitespace removed to reduce download size from 45.5kB to 12.8kB.
</ul>
<h2>4 Jul 2008</h2>
<ul>
<li>Added <a href="http://code.google.com/p/google-code-prettify/issues/detail?id=17">language specific formatters</a> that are triggered by the presence
of a <code>lang-&lt;language-file-extension&gt;</code></li>
<li>Fixed <a href="http://code.google.com/p/google-code-prettify/issues/detail?id=29">bug</a>: python handling of <code>'''string'''</code>
<li>Fixed bug: <code>/</code> in regex <code>[charsets] should not end regex</code>
</ul>
<h2>5 Jul 2008</h2>
<ul>
<li>Defined language extensions for Lisp and Lua</code>
</ul>
<h2>14 Jul 2008</h2>
<ul>
<li>Language handlers for F#, OCAML, SQL</code>
<li>Support for <code>nocode</code> spans to allow embedding of line
numbers and code annotations which should not be styled or otherwise
affect the tokenization of prettified code.
See the issue 22
<a href="tests/prettify_test.html#issue22">testcase</a>.</code>
</ul>
<h2>6 Jan 2009</h2>
<ul>
<li>Language handlers for Visual Basic, Haskell, CSS, and WikiText</li>
<li>Added <tt>.mxml</tt> extension to the markup style handler for
Flex <a href="http://en.wikipedia.org/wiki/MXML">MXML files</a>. See
<a
href="http://code.google.com/p/google-code-prettify/issues/detail?id=37"
>issue 37</a>.
<li>Added <tt>.m</tt> extension to the C style handler so that Objective
C source files properly highlight. See
<a
href="http://code.google.com/p/google-code-prettify/issues/detail?id=58"
>issue 58</a>.
<li>Changed HTML lexer to use the same embedded source mechanism as the
wiki language handler, and changed to use the registered
CSS handler for STYLE element content.
</ul>
<h2>21 May 2009</h2>
<ul>
<li>Rewrote to improve performance on large files.
See <a href="http://mikesamuel.blogspot.com/2009/05/efficient-parsing-in-javascript.html">benchmarks</a>.</li>
<li>Fixed bugs with highlighting of Haskell line comments, Lisp
number literals, Lua strings, C preprocessor directives,
newlines in Wiki code on Windows, and newlines in IE6.</li>
</ul>
<h2>14 August 2009</h2>
<ul>
<li>Fixed prettifying of <code>&lt;code&gt;</code> blocks with embedded newlines.
</ul>
<h2>3 October 2009</h2>
<ul>
<li>Fixed prettifying of XML/HTML tags that contain uppercase letters.
</ul>
<h2>19 July 2010</h2>
<ul>
<li>Added support for line numbers. Bug
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=22"
>22</a></li>
<li>Added YAML support. Bug
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=123"
>123</a></li>
<li>Added VHDL support courtesy Le Poussin.</li>
<li>IE performance improvements. Bug
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=102"
>102</a> courtesy jacobly.</li>
<li>A variety of markup formatting fixes courtesy smain and thezbyg.</li>
<li>Fixed copy and paste in IE[678].
<li>Changed output to use <code>&amp;#160;</code> instead of
<code>&amp;nbsp;</code> so that the output works when embedded in XML.
Bug
<a href="http://code.google.com/p/google-code-prettify/issues/detail?id=108"
>108</a>.</li>
</ul>
</body>
</html>
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title>Javascript code prettifier</title>
<link href="src/prettify.css" type="text/css" rel="stylesheet" />
<script src="src/prettify.js" type="text/javascript"></script>
<style type="text/css">
body { margin-left: .5in }
h1, h2, h3, h4, .footer { margin-left: -.4in; }
</style>
</head>
<body onload="prettyPrint()" bgcolor="white">
<small style="float: right">Languages : <a href="README-zh-Hans.html">CH</a></small>
<h1>Javascript code prettifier</h1>
<h2>Setup</h2>
<ol>
<li><a href="http://code.google.com/p/google-code-prettify/downloads/list">Download</a> a distribution
<li>Include the script and stylesheets in your document
(you will need to make sure the css and js file are on your server, and
adjust the paths in the <tt>script</tt> and <tt>link</tt> tag)
<pre class="prettyprint">
&lt;link href="prettify.css" type="text/css" rel="stylesheet" />
&lt;script type="text/javascript" src="prettify.js">&lt;/script></pre>
<li>Add <code class="prettyprint lang-html">onload="prettyPrint()"</code> to your
document's body tag.
<li>Modify the stylesheet to get the coloring you prefer</li>
</ol>
<h2>Usage</h2>
<p>Put code snippets in
<tt>&lt;pre class="prettyprint"&gt;...&lt;/pre&gt;</tt>
or <tt>&lt;code class="prettyprint"&gt;...&lt;/code&gt;</tt>
and it will automatically be pretty printed.
<table summary="code examples">
<tr>
<th>The original
<th>Prettier
<tr>
<td><pre style="border: 1px solid #888;padding: 2px"
><a name="voila1"></a>class Voila {
public:
// Voila
static const string VOILA = "Voila";
// will not interfere with embedded <a href="#voila1">tags</a>.
}</pre>
<td><pre class="prettyprint"><a name="voila2"></a>class Voila {
public:
// Voila
static const string VOILA = "Voila";
// will not interfere with embedded <a href="#voila2">tags</a>.
}</pre>
</table>
<h2>FAQ</h2>
<h3 id="langs">Which languages does it work for?</h3>
<p>The comments in <tt>prettify.js</tt> are authoritative but the lexer
should work on a number of languages including C and friends,
Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles.
It works passably on Ruby, PHP, VB, and Awk and a decent subset of Perl
and Ruby, but, because of commenting conventions, doesn't work on
Smalltalk, or CAML-like languages.</p>
<p>LISPy languages are supported via an extension:
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-lisp.js"
><code>lang-lisp.js</code></a>.</p>
<p>And similarly for
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-css.js"
><code>CSS</code></a>,
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-hs.js"
><code>Haskell</code></a>,
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-lua.js"
><code>Lua</code></a>,
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-ml.js"
><code>OCAML, SML, F#</code></a>,
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-vb.js"
><code>Visual Basic</code></a>,
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-sql.js"
><code>SQL</code></a>,
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-proto.js"
><code>Protocol Buffers</code></a>, and
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-wiki.js"
><code>WikiText</code></a>..
<p>If you'd like to add an extension for your favorite language, please
look at <tt>src/lang-lisp.js</tt> and file an
<a href="http://code.google.com/p/google-code-prettify/issues/list"
>issue</a> including your language extension, and a testcase.</p>
<h3>How do I specify which language my code is in?</h3>
<p>You don't need to specify the language since <code>prettyprint()</code>
will guess. You can specify a language by specifying the language extension
along with the <code>prettyprint</code> class like so:</p>
<pre class="prettyprint lang-html"
>&lt;pre class=&quot;prettyprint <b>lang-html</b>&quot;&gt;
The lang-* class specifies the language file extensions.
File extensions supported by default include
"bsh", "c", "cc", "cpp", "cs", "csh", "cyc", "cv", "htm", "html",
"java", "js", "m", "mxml", "perl", "pl", "pm", "py", "rb", "sh",
"xhtml", "xml", "xsl".
&lt;/pre&gt;</pre>
<h3>It doesn't work on <tt>&lt;obfuscated code sample&gt;</tt>?</h3>
<p>Yes. Prettifying obfuscated code is like putting lipstick on a pig
&mdash; i.e. outside the scope of this tool.</p>
<h3>Which browsers does it work with?</h3>
<p>It's been tested with IE 6, Firefox 1.5 &amp; 2, and Safari 2.0.4.
Look at <a href="tests/prettify_test.html">the test page</a> to see if it
works in your browser.</p>
<h3>What's changed?</h3>
<p>See the <a href="CHANGES.html">change log</a></p>
<h3>Why doesn't Prettyprinting of strings work on WordPress?</h3>
<p>Apparently wordpress does "smart quoting" which changes close quotes.
This causes end quotes to not match up with open quotes.
<p>This breaks prettifying as well as copying and pasting of code samples.
See
<a href="http://wordpress.org/support/topic/125038"
>WordPress's help center</a> for info on how to stop smart quoting of code
snippets.</p>
<h3 id="linenums">How do I put line numbers in my code?</h3>
<p>You can use the <code>linenums</code> class to turn on line
numbering. If your code doesn't start at line number 1, you can
add a colon and a line number to the end of that class as in
<code>linenums:52</code>.
<p>For example
<pre class="prettyprint">&lt;pre class="prettyprint linenums:<b>4</b>"
&gt;// This is line 4.
foo();
bar();
baz();
boo();
far();
faz();
&lt;pre&gt;</pre>
produces
<pre class="prettyprint linenums:4"
>// This is line 4.
foo();
bar();
baz();
boo();
far();
faz();
</pre>
<h3>How do I prevent a portion of markup from being marked as code?</h3>
<p>You can use the <code>nocode</code> class to identify a span of markup
that is not code.
<pre class="prettyprint">&lt;pre class=prettyprint&gt;
int x = foo(); /* This is a comment &lt;span class="nocode"&gt;This is not code&lt;/span&gt;
Continuation of comment */
int y = bar();
&lt;/pre&gt;</pre>
produces
<pre class="prettyprint">
int x = foo(); /* This is a comment <span class="nocode">This is not code</span>
Continuation of comment */
int y = bar();
</pre>
<p>For a more complete example see the issue22
<a href="tests/prettify_test.html#issue22">testcase</a>.</p>
<h3>I get an error message "a is not a function" or "opt_whenDone is not a function"</h3>
<p>If you are calling <code>prettyPrint</code> via an event handler, wrap it in a function.
Instead of doing
<blockquote>
<code class="prettyprint lang-js"
>addEventListener('load', prettyPrint, false);</code>
</blockquote>
wrap it in a closure like
<blockquote>
<code class="prettyprint lang-js"
>addEventListener('load', function (event) { prettyPrint() }, false);</code>
</blockquote>
so that the browser does not pass an event object to <code>prettyPrint</code> which
will confuse it.
<br><br><br>
<div class="footer">
<!-- Created: Tue Oct 3 17:51:56 PDT 2006 -->
<!-- hhmts start -->
Last modified: Wed Jul 19 13:56:00 PST 2010
<!-- hhmts end -->
</div>
</body>
</html>
.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee}
\ No newline at end of file
window.PR_SHOULD_USE_CONTINUATION=true;var prettyPrintOne;var prettyPrint;(function(){var O=window;var j=["break,continue,do,else,for,if,return,while"];var v=[j,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var q=[v,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var m=[q,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var y=[q,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var T=[y,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"];var s="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes";var x=[q,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var t="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var J=[j,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var g=[j,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var I=[j,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var B=[m,T,x,t+J,g,I];var f=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;var D="str";var A="kwd";var k="com";var Q="typ";var H="lit";var M="pun";var G="pln";var n="tag";var F="dec";var K="src";var R="atn";var o="atv";var P="nocode";var N="(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function l(ab){var af=0;var U=false;var ae=false;for(var X=0,W=ab.length;X<W;++X){var ag=ab[X];if(ag.ignoreCase){ae=true}else{if(/[a-z]/i.test(ag.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,""))){U=true;ae=false;break}}}var aa={b:8,t:9,n:10,v:11,f:12,r:13};function ad(aj){var ai=aj.charCodeAt(0);if(ai!==92){return ai}var ah=aj.charAt(1);ai=aa[ah];if(ai){return ai}else{if("0"<=ah&&ah<="7"){return parseInt(aj.substring(1),8)}else{if(ah==="u"||ah==="x"){return parseInt(aj.substring(2),16)}else{return aj.charCodeAt(1)}}}}function V(ah){if(ah<32){return(ah<16?"\\x0":"\\x")+ah.toString(16)}var ai=String.fromCharCode(ah);return(ai==="\\"||ai==="-"||ai==="]"||ai==="^")?"\\"+ai:ai}function Z(an){var ar=an.substring(1,an.length-1).match(new RegExp("\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]","g"));var ah=[];var ap=ar[0]==="^";var ao=["["];if(ap){ao.push("^")}for(var at=ap?1:0,al=ar.length;at<al;++at){var aj=ar[at];if(/\\[bdsw]/i.test(aj)){ao.push(aj)}else{var ai=ad(aj);var am;if(at+2<al&&"-"===ar[at+1]){am=ad(ar[at+2]);at+=2}else{am=ai}ah.push([ai,am]);if(!(am<65||ai>122)){if(!(am<65||ai>90)){ah.push([Math.max(65,ai)|32,Math.min(am,90)|32])}if(!(am<97||ai>122)){ah.push([Math.max(97,ai)&~32,Math.min(am,122)&~32])}}}}ah.sort(function(aw,av){return(aw[0]-av[0])||(av[1]-aw[1])});var ak=[];var aq=[];for(var at=0;at<ah.length;++at){var au=ah[at];if(au[0]<=aq[1]+1){aq[1]=Math.max(aq[1],au[1])}else{ak.push(aq=au)}}for(var at=0;at<ak.length;++at){var au=ak[at];ao.push(V(au[0]));if(au[1]>au[0]){if(au[1]+1>au[0]){ao.push("-")}ao.push(V(au[1]))}}ao.push("]");return ao.join("")}function Y(an){var al=an.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var aj=al.length;var ap=[];for(var am=0,ao=0;am<aj;++am){var ai=al[am];if(ai==="("){++ao}else{if("\\"===ai.charAt(0)){var ah=+ai.substring(1);if(ah){if(ah<=ao){ap[ah]=-1}else{al[am]=V(ah)}}}}}for(var am=1;am<ap.length;++am){if(-1===ap[am]){ap[am]=++af}}for(var am=0,ao=0;am<aj;++am){var ai=al[am];if(ai==="("){++ao;if(!ap[ao]){al[am]="(?:"}}else{if("\\"===ai.charAt(0)){var ah=+ai.substring(1);if(ah&&ah<=ao){al[am]="\\"+ap[ah]}}}}for(var am=0;am<aj;++am){if("^"===al[am]&&"^"!==al[am+1]){al[am]=""}}if(an.ignoreCase&&U){for(var am=0;am<aj;++am){var ai=al[am];var ak=ai.charAt(0);if(ai.length>=2&&ak==="["){al[am]=Z(ai)}else{if(ak!=="\\"){al[am]=ai.replace(/[a-zA-Z]/g,function(aq){var ar=aq.charCodeAt(0);return"["+String.fromCharCode(ar&~32,ar|32)+"]"})}}}}return al.join("")}var ac=[];for(var X=0,W=ab.length;X<W;++X){var ag=ab[X];if(ag.global||ag.multiline){throw new Error(""+ag)}ac.push("(?:"+Y(ag)+")")}return new RegExp(ac.join("|"),ae?"gi":"g")}function b(aa,Y){var W=/(?:^|\s)nocode(?:\s|$)/;var ab=[];var Z=0;var X=[];var V=0;function U(ac){switch(ac.nodeType){case 1:if(W.test(ac.className)){return}for(var af=ac.firstChild;af;af=af.nextSibling){U(af)}var ae=ac.nodeName.toLowerCase();if("br"===ae||"li"===ae){ab[V]="\n";X[V<<1]=Z++;X[(V++<<1)|1]=ac}break;case 3:case 4:var ad=ac.nodeValue;if(ad.length){if(!Y){ad=ad.replace(/[ \t\r\n]+/g," ")}else{ad=ad.replace(/\r\n?/g,"\n")}ab[V]=ad;X[V<<1]=Z;Z+=ad.length;X[(V++<<1)|1]=ac}break}}U(aa);return{sourceCode:ab.join("").replace(/\n$/,""),spans:X}}function C(U,W,Y,V){if(!W){return}var X={sourceCode:W,basePos:U};Y(X);V.push.apply(V,X.decorations)}var w=/\S/;function p(U){var X=undefined;for(var W=U.firstChild;W;W=W.nextSibling){var V=W.nodeType;X=(V===1)?(X?U:W):(V===3)?(w.test(W.nodeValue)?U:X):X}return X===U?undefined:X}function h(W,V){var U={};var X;(function(){var af=W.concat(V);var aj=[];var ai={};for(var ad=0,ab=af.length;ad<ab;++ad){var aa=af[ad];var ae=aa[3];if(ae){for(var ag=ae.length;--ag>=0;){U[ae.charAt(ag)]=aa}}var ah=aa[1];var ac=""+ah;if(!ai.hasOwnProperty(ac)){aj.push(ah);ai[ac]=null}}aj.push(/[\0-\uffff]/);X=l(aj)})();var Z=V.length;var Y=function(aj){var ab=aj.sourceCode,aa=aj.basePos;var af=[aa,G];var ah=0;var ap=ab.match(X)||[];var al={};for(var ag=0,at=ap.length;ag<at;++ag){var ai=ap[ag];var ar=al[ai];var ak=void 0;var ao;if(typeof ar==="string"){ao=false}else{var ac=U[ai.charAt(0)];if(ac){ak=ai.match(ac[1]);ar=ac[0]}else{for(var aq=0;aq<Z;++aq){ac=V[aq];ak=ai.match(ac[1]);if(ak){ar=ac[0];break}}if(!ak){ar=G}}ao=ar.length>=5&&"lang-"===ar.substring(0,5);if(ao&&!(ak&&typeof ak[1]==="string")){ao=false;ar=K}if(!ao){al[ai]=ar}}var ad=ah;ah+=ai.length;if(!ao){af.push(aa+ad,ar)}else{var an=ak[1];var am=ai.indexOf(an);var ae=am+an.length;if(ak[2]){ae=ai.length-ak[2].length;am=ae-an.length}var au=ar.substring(5);C(aa+ad,ai.substring(0,am),Y,af);C(aa+ad+am,an,r(au,an),af);C(aa+ad+ae,ai.substring(ae),Y,af)}}aj.decorations=af};return Y}function i(V){var Y=[],U=[];if(V.tripleQuotedStrings){Y.push([D,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(V.multiLineStrings){Y.push([D,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{Y.push([D,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(V.verbatimStrings){U.push([D,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var ab=V.hashComments;if(ab){if(V.cStyleComments){if(ab>1){Y.push([k,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{Y.push([k,/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}U.push([D,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,null])}else{Y.push([k,/^#[^\r\n]*/,null,"#"])}}if(V.cStyleComments){U.push([k,/^\/\/[^\r\n]*/,null]);U.push([k,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(V.regexLiterals){var aa=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");U.push(["lang-regex",new RegExp("^"+N+"("+aa+")")])}var X=V.types;if(X){U.push([Q,X])}var W=(""+V.keywords).replace(/^ | $/g,"");if(W.length){U.push([A,new RegExp("^(?:"+W.replace(/[\s,]+/g,"|")+")\\b"),null])}Y.push([G,/^\s+/,null," \r\n\t\xA0"]);var Z=/^.[^\s\w\.$@\'\"\`\/\\]*/;U.push([H,/^@[a-z_$][a-z_$@0-9]*/i,null],[Q,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[G,/^[a-z_$][a-z_$@0-9]*/i,null],[H,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[G,/^\\[\s\S]?/,null],[M,Z,null]);return h(Y,U)}var L=i({keywords:B,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function S(W,ah,aa){var V=/(?:^|\s)nocode(?:\s|$)/;var ac=/\r\n?|\n/;var ad=W.ownerDocument;var ag=ad.createElement("li");while(W.firstChild){ag.appendChild(W.firstChild)}var X=[ag];function af(am){switch(am.nodeType){case 1:if(V.test(am.className)){break}if("br"===am.nodeName){ae(am);if(am.parentNode){am.parentNode.removeChild(am)}}else{for(var ao=am.firstChild;ao;ao=ao.nextSibling){af(ao)}}break;case 3:case 4:if(aa){var an=am.nodeValue;var ak=an.match(ac);if(ak){var aj=an.substring(0,ak.index);am.nodeValue=aj;var ai=an.substring(ak.index+ak[0].length);if(ai){var al=am.parentNode;al.insertBefore(ad.createTextNode(ai),am.nextSibling)}ae(am);if(!aj){am.parentNode.removeChild(am)}}}break}}function ae(al){while(!al.nextSibling){al=al.parentNode;if(!al){return}}function aj(am,at){var ar=at?am.cloneNode(false):am;var ap=am.parentNode;if(ap){var aq=aj(ap,1);var ao=am.nextSibling;aq.appendChild(ar);for(var an=ao;an;an=ao){ao=an.nextSibling;aq.appendChild(an)}}return ar}var ai=aj(al.nextSibling,0);for(var ak;(ak=ai.parentNode)&&ak.nodeType===1;){ai=ak}X.push(ai)}for(var Z=0;Z<X.length;++Z){af(X[Z])}if(ah===(ah|0)){X[0].setAttribute("value",ah)}var ab=ad.createElement("ol");ab.className="linenums";var Y=Math.max(0,((ah-1))|0)||0;for(var Z=0,U=X.length;Z<U;++Z){ag=X[Z];ag.className="L"+((Z+Y)%10);if(!ag.firstChild){ag.appendChild(ad.createTextNode("\xA0"))}ab.appendChild(ag)}W.appendChild(ab)}function E(af){var X=/\bMSIE\s(\d+)/.exec(navigator.userAgent);X=X&&+X[1]<=8;var ao=/\n/g;var an=af.sourceCode;var ap=an.length;var Y=0;var ad=af.spans;var V=ad.length;var aj=0;var aa=af.decorations;var ab=aa.length;var ac=0;aa[ab]=ap;var av,at;for(at=av=0;at<ab;){if(aa[at]!==aa[at+2]){aa[av++]=aa[at++];aa[av++]=aa[at++]}else{at+=2}}ab=av;for(at=av=0;at<ab;){var aw=aa[at];var ae=aa[at+1];var Z=at+2;while(Z+2<=ab&&aa[Z+1]===ae){Z+=2}aa[av++]=aw;aa[av++]=ae;at=Z}ab=aa.length=av;var au=af.sourceNode;var ak;if(au){ak=au.style.display;au.style.display="none"}try{var ah=null;while(aj<V){var ai=ad[aj];var U=ad[aj+2]||ap;var ar=aa[ac+2]||ap;var Z=Math.min(U,ar);var am=ad[aj+1];var W;if(am.nodeType!==1&&(W=an.substring(Y,Z))){if(X){W=W.replace(ao,"\r")}am.nodeValue=W;var al=am.ownerDocument;var aq=al.createElement("span");aq.className=aa[ac+1];var ag=am.parentNode;ag.replaceChild(aq,am);aq.appendChild(am);if(Y<U){ad[aj+1]=am=al.createTextNode(an.substring(Z,U));ag.insertBefore(am,aq.nextSibling)}}Y=Z;if(Y>=U){aj+=2}if(Y>=ar){ac+=2}}}finally{if(au){au.style.display=ak}}}var u={};function d(W,X){for(var U=X.length;--U>=0;){var V=X[U];if(!u.hasOwnProperty(V)){u[V]=W}else{if(O.console){console.warn("cannot override language handler %s",V)}}}}function r(V,U){if(!(V&&u.hasOwnProperty(V))){V=/^\s*</.test(U)?"default-markup":"default-code"}return u[V]}d(L,["default-code"]);d(h([],[[G,/^[^<?]+/],[F,/^<!\w[^>]*(?:>|$)/],[k,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[M,/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);d(h([[G,/^[\s]+/,null," \t\r\n"],[o,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[n,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[R,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[M,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);d(h([],[[o,/^[\s\S]+/]]),["uq.val"]);d(i({keywords:m,hashComments:true,cStyleComments:true,types:f}),["c","cc","cpp","cxx","cyc","m"]);d(i({keywords:"null,true,false"}),["json"]);d(i({keywords:T,hashComments:true,cStyleComments:true,verbatimStrings:true,types:f}),["cs"]);d(i({keywords:y,cStyleComments:true}),["java"]);d(i({keywords:I,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);d(i({keywords:J,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);d(i({keywords:t,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);d(i({keywords:g,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);d(i({keywords:x,cStyleComments:true,regexLiterals:true}),["js"]);d(i({keywords:s,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);d(h([],[[D,/^[\s\S]+/]]),["regex"]);function e(X){var W=X.langExtension;try{var U=b(X.sourceNode,X.pre);var V=U.sourceCode;X.sourceCode=V;X.spans=U.spans;X.basePos=0;r(W,V)(X);E(X)}catch(Y){if(O.console){console.log(Y&&Y.stack?Y.stack:Y)}}}function z(Y,X,W){var U=document.createElement("pre");U.innerHTML=Y;if(W){S(U,W,true)}var V={langExtension:X,numberLines:W,sourceNode:U,pre:1};e(V);return U.innerHTML}function c(aj){function ab(al){return document.getElementsByTagName(al)}var ah=[ab("pre"),ab("code"),ab("xmp")];var V=[];for(var ae=0;ae<ah.length;++ae){for(var ac=0,Y=ah[ae].length;ac<Y;++ac){V.push(ah[ae][ac])}}ah=null;var Z=Date;if(!Z.now){Z={now:function(){return +(new Date)}}}var aa=0;var U;var af=/\blang(?:uage)?-([\w.]+)(?!\S)/;var ak=/\bprettyprint\b/;var W=/\bprettyprinted\b/;var ag=/pre|xmp/i;var ai=/^code$/i;var ad=/^(?:pre|code|xmp)$/i;function X(){var ar=(O.PR_SHOULD_USE_CONTINUATION?Z.now()+250:Infinity);for(;aa<V.length&&Z.now()<ar;aa++){var at=V[aa];var au=at.className;if(ak.test(au)&&!W.test(au)){var aw=false;for(var ao=at.parentNode;ao;ao=ao.parentNode){var ax=ao.tagName;if(ad.test(ax)&&ao.className&&ak.test(ao.className)){aw=true;break}}if(!aw){at.className+=" prettyprinted";var aq=au.match(af);var am;if(!aq&&(am=p(at))&&ai.test(am.tagName)){aq=am.className.match(af)}if(aq){aq=aq[1]}var ap;if(ag.test(at.tagName)){ap=1}else{var an=at.currentStyle;var al=(an?an.whiteSpace:(document.defaultView&&document.defaultView.getComputedStyle)?document.defaultView.getComputedStyle(at,null).getPropertyValue("white-space"):0);ap=al&&"pre"===al.substring(0,3)}var av=at.className.match(/\blinenums\b(?::(\d+))?/);av=av?av[1]&&av[1].length?+av[1]:true:false;if(av){S(at,av,ap)}U={langExtension:aq,sourceNode:at,numberLines:av,pre:ap};e(U)}}}if(aa<V.length){setTimeout(X,250)}else{if(aj){aj()}}}X()}var a=O.PR={createSimpleLexer:h,registerLangHandler:d,sourceDecorator:i,PR_ATTRIB_NAME:R,PR_ATTRIB_VALUE:o,PR_COMMENT:k,PR_DECLARATION:F,PR_KEYWORD:A,PR_LITERAL:H,PR_NOCODE:P,PR_PLAIN:G,PR_PUNCTUATION:M,PR_SOURCE:K,PR_STRING:D,PR_TAG:n,PR_TYPE:Q,prettyPrintOne:O.prettyPrintOne=z,prettyPrint:O.prettyPrint=c};if(typeof define==="function"&&define.amd){define("google-code-prettify",[],function(){return a})}})();PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_DECLARATION,/^<!\w[^>]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^<script\b[^>]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:<!--|-->)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]);
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>QueryInterface</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1>QueryInterface Class</h1>
<div class="box meta">
<div class="foundat">
Defined in: <a href="..&#x2F;files&#x2F;lib_dialects_sqlite_query-interface.js.html#l3"><code>lib&#x2F;dialects&#x2F;sqlite&#x2F;query-interface.js:3</code></a>
</div>
Module: <a href="../modules/Sequelize.html">Sequelize</a>
</div>
<div class="box intro">
<p>Returns an object that treats SQLite's inabilities to do certain queries.</p>
</div>
<div id="classdocs" class="tabview">
<ul class="api-class-tabs">
<li class="api-class-tab index"><a href="#index">Index</a></li>
<li class="api-class-tab methods"><a href="#methods">Methods</a></li>
</ul>
<div>
<div id="index" class="api-class-tabpanel index">
<h2 class="off-left">Item Index</h2>
<div class="index-section methods">
<h3>Methods</h3>
<ul class="index-list methods">
<li class="index-item method">
<a href="#method_changeColumn">changeColumn</a>
</li>
<li class="index-item method">
<a href="#method_removeColumn">removeColumn</a>
</li>
<li class="index-item method">
<a href="#method_renameColumn">renameColumn</a>
</li>
</ul>
</div>
</div>
<div id="methods" class="api-class-tabpanel">
<h2 class="off-left">Methods</h2>
<div id="method_changeColumn" class="method item">
<h3 class="name"><code>changeColumn</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code>tableName</code>
</li>
<li class="arg">
<code>attributes</code>
</li>
<li class="arg">
<code>emitter</code>
</li>
<li class="arg">
<code>queryAndEmit</code>
</li>
</ul><span class="paren">)</span>
</div>
<div class="meta">
<p>
Defined in
<a href="..&#x2F;files&#x2F;lib_dialects_sqlite_query-interface.js.html#l40"><code>lib&#x2F;dialects&#x2F;sqlite&#x2F;query-interface.js:40</code></a>
</p>
<p>Available since 1.6.0</p>
</div>
<div class="description">
<p>A wrapper that fixes SQLite's inability to change columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a
new table with the same name but with a modified version of the respective column.</p>
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name">tableName</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the table.</p>
</div>
</li>
<li class="param">
<code class="param-name">attributes</code>
<span class="type">Object</span>
<div class="param-description">
<p>An object with the attribute's name as key and it's options as value object.</p>
</div>
</li>
<li class="param">
<code class="param-name">emitter</code>
<span class="type">CustomEventEmitter</span>
<div class="param-description">
<p>The EventEmitter from outside.</p>
</div>
</li>
<li class="param">
<code class="param-name">queryAndEmit</code>
<span class="type">Function</span>
<div class="param-description">
<p>The function from outside that triggers some events to get triggered.</p>
</div>
</li>
</ul>
</div>
</div>
<div id="method_removeColumn" class="method item">
<h3 class="name"><code>removeColumn</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code>tableName</code>
</li>
<li class="arg">
<code>attributeName</code>
</li>
<li class="arg">
<code>emitter</code>
</li>
<li class="arg">
<code>queryAndEmit</code>
</li>
</ul><span class="paren">)</span>
</div>
<div class="meta">
<p>
Defined in
<a href="..&#x2F;files&#x2F;lib_dialects_sqlite_query-interface.js.html#l10"><code>lib&#x2F;dialects&#x2F;sqlite&#x2F;query-interface.js:10</code></a>
</p>
<p>Available since 1.6.0</p>
</div>
<div class="description">
<p>A wrapper that fixes SQLite's inability to remove columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a
new table with the same name but without the obsolete column.</p>
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name">tableName</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the table.</p>
</div>
</li>
<li class="param">
<code class="param-name">attributeName</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the attribute that we want to remove.</p>
</div>
</li>
<li class="param">
<code class="param-name">emitter</code>
<span class="type">CustomEventEmitter</span>
<div class="param-description">
<p>The EventEmitter from outside.</p>
</div>
</li>
<li class="param">
<code class="param-name">queryAndEmit</code>
<span class="type">Function</span>
<div class="param-description">
<p>The function from outside that triggers some events to get triggered.</p>
</div>
</li>
</ul>
</div>
</div>
<div id="method_renameColumn" class="method item">
<h3 class="name"><code>renameColumn</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code>tableName</code>
</li>
<li class="arg">
<code>attrNameBefore</code>
</li>
<li class="arg">
<code>attrNameAfter</code>
</li>
<li class="arg">
<code>emitter</code>
</li>
<li class="arg">
<code>queryAndEmit</code>
</li>
</ul><span class="paren">)</span>
</div>
<div class="meta">
<p>
Defined in
<a href="..&#x2F;files&#x2F;lib_dialects_sqlite_query-interface.js.html#l72"><code>lib&#x2F;dialects&#x2F;sqlite&#x2F;query-interface.js:72</code></a>
</p>
<p>Available since 1.6.0</p>
</div>
<div class="description">
<p>A wrapper that fixes SQLite's inability to rename columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a
new table with the same name but with a renamed version of the respective column.</p>
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name">tableName</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the table.</p>
</div>
</li>
<li class="param">
<code class="param-name">attrNameBefore</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the attribute before it was renamed.</p>
</div>
</li>
<li class="param">
<code class="param-name">attrNameAfter</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the attribute after it was renamed.</p>
</div>
</li>
<li class="param">
<code class="param-name">emitter</code>
<span class="type">CustomEventEmitter</span>
<div class="param-description">
<p>The EventEmitter from outside.</p>
</div>
</li>
<li class="param">
<code class="param-name">queryAndEmit</code>
<span class="type">Function</span>
<div class="param-description">
<p>The function from outside that triggers some events to get triggered.</p>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sequelize</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1>Sequelize Class</h1>
<div class="box meta">
<div class="foundat">
Defined in: <a href="..&#x2F;files&#x2F;lib_sequelize.js.html#l12"><code>lib&#x2F;sequelize.js:12</code></a>
</div>
Module: <a href="../modules/Sequelize.html">Sequelize</a>
</div>
<div class="box intro">
<p>Main class of the project.</p>
</div>
<div class="constructor">
<h2>Constructor</h2>
<div id="method_Sequelize" class="method item">
<h3 class="name"><code>Sequelize</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code>database</code>
</li>
<li class="arg">
<code>username</code>
</li>
<li class="arg">
<code class="optional">[password=null]</code>
</li>
<li class="arg">
<code class="optional">[options={}]</code>
</li>
</ul><span class="paren">)</span>
</div>
<div class="meta">
<p>
Defined in
<a href="..&#x2F;files&#x2F;lib_sequelize.js.html#l12"><code>lib&#x2F;sequelize.js:12</code></a>
</p>
</div>
<div class="description">
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name">database</code>
<span class="type">String</span>
<div class="param-description">
<p>The name of the database.</p>
</div>
</li>
<li class="param">
<code class="param-name">username</code>
<span class="type">String</span>
<div class="param-description">
<p>The username which is used to authenticate against the database.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[password=null]</code>
<span class="type">String</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>The password which is used to authenticate against the database.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[options={}]</code>
<span class="type">Object</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>An object with options.</p>
</div>
<ul class="params-list">
<li class="param">
<code class="param-name optional">[dialect=&#x27;mysql&#x27;]</code>
<span class="type">String</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>The dialect of the relational database.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[host=&#x27;localhost&#x27;]</code>
<span class="type">String</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>The host of the relational database.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[port=3306]</code>
<span class="type">Integer</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>The port of the relational database.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[protocol=&#x27;tcp&#x27;]</code>
<span class="type">String</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>The protocol of the relational database.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[define={}]</code>
<span class="type">Object</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>Options, which shall be default for every model definition.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[query={}]</code>
<span class="type">Object</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>I have absolutely no idea.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[sync={}]</code>
<span class="type">Object</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>Options, which shall be default for every <code>sync</code> call.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[logging=console.log]</code>
<span class="type">Function</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>A function that gets executed everytime Sequelize would log something.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[omitNull=false]</code>
<span class="type">Boolean</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>A flag that defines if null values should be passed to SQL queries or not.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[queue=true]</code>
<span class="type">Boolean</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>I have absolutely no idea.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[native=false]</code>
<span class="type">Boolean</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>A flag that defines if native library shall be used or not.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[replication=false]</code>
<span class="type">Boolean</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>I have absolutely no idea.</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[pool={}]</code>
<span class="type">Object</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>Something.</p>
</div>
</li>
</ul>
</li>
</ul>
</div>
<div class="example">
<h4>Example:</h4>
<div class="example-content">
<pre class="code prettyprint"><code>// without password and options
var sequelize = new Sequelize('database', 'username')
// without options
var sequelize = new Sequelize('database', 'username', 'password')
// without password / with blank password
var sequelize = new Sequelize('database', 'username', null, {})
// with password and options
var sequelize = new Sequelize('my_database', 'john', 'doe', {})
</code></pre>
</div>
</div>
</div>
</div>
<div id="classdocs" class="tabview">
<ul class="api-class-tabs">
<li class="api-class-tab index"><a href="#index">Index</a></li>
<li class="api-class-tab methods"><a href="#methods">Methods</a></li>
</ul>
<div>
<div id="index" class="api-class-tabpanel index">
<h2 class="off-left">Item Index</h2>
<div class="index-section methods">
<h3>Methods</h3>
<ul class="index-list methods">
<li class="index-item method">
<a href="#method_getMigrator">getMigrator</a>
</li>
<li class="index-item method">
<a href="#method_getQueryInterface">getQueryInterface</a>
</li>
</ul>
</div>
</div>
<div id="methods" class="api-class-tabpanel">
<h2 class="off-left">Methods</h2>
<div id="method_getMigrator" class="method item">
<h3 class="name"><code>getMigrator</code></h3>
<div class="args">
<span class="paren">(</span><ul class="args-list inline commas">
<li class="arg">
<code class="optional">[options={}]</code>
</li>
<li class="arg">
<code class="optional">[force=false]</code>
</li>
</ul><span class="paren">)</span>
</div>
<span class="returns-inline">
<span class="type">Migrator</span>
</span>
<div class="meta">
<p>
Defined in
<a href="..&#x2F;files&#x2F;lib_sequelize.js.html#l113"><code>lib&#x2F;sequelize.js:113</code></a>
</p>
</div>
<div class="description">
<p>Returns an instance (singleton) of Migrator.</p>
</div>
<div class="params">
<h4>Parameters:</h4>
<ul class="params-list">
<li class="param">
<code class="param-name optional">[options={}]</code>
<span class="type">Object</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>Some options</p>
</div>
</li>
<li class="param">
<code class="param-name optional">[force=false]</code>
<span class="type">Boolean</span>
<span class="flag optional" title="This parameter is optional.">optional</span>
<div class="param-description">
<p>A flag that defines if the migrator should get instantiated or not.</p>
</div>
</li>
</ul>
</div>
<div class="returns">
<h4>Returns:</h4>
<div class="returns-description">
<span class="type">Migrator</span>:
An instance of Migrator.
</div>
</div>
</div>
<div id="method_getQueryInterface" class="method item">
<h3 class="name"><code>getQueryInterface</code></h3>
<span class="paren">()</span>
<span class="returns-inline">
<span class="type"><a href="../classes/QueryInterface.html" class="crosslink">QueryInterface</a></span>
</span>
<div class="meta">
<p>
Defined in
<a href="..&#x2F;files&#x2F;lib_sequelize.js.html#l102"><code>lib&#x2F;sequelize.js:102</code></a>
</p>
</div>
<div class="description">
<p>Returns an instance of QueryInterface.</p>
</div>
<div class="returns">
<h4>Returns:</h4>
<div class="returns-description">
<span class="type"><a href="../classes/QueryInterface.html" class="crosslink">QueryInterface</a></span>:
An instance (singleton) of QueryInterface.
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Redirector</title>
<meta http-equiv="refresh" content="0;url=../">
</head>
<body>
<a href="../">Click here to redirect</a>
</body>
</html>
{
"project": {},
"files": {
"lib/dialects/abstract/query.js": {
"name": "lib/dialects/abstract/query.js",
"modules": {},
"classes": {},
"fors": {},
"namespaces": {}
},
"lib/dialects/sqlite/query-interface.js": {
"name": "lib/dialects/sqlite/query-interface.js",
"modules": {},
"classes": {
"QueryInterface": 1
},
"fors": {
"QueryInterface": 1
},
"namespaces": {}
},
"lib/dao-factory.js": {
"name": "lib/dao-factory.js",
"modules": {},
"classes": {},
"fors": {},
"namespaces": {}
},
"lib/sequelize.js": {
"name": "lib/sequelize.js",
"modules": {},
"classes": {
"Sequelize": 1
},
"fors": {},
"namespaces": {}
},
"index.js": {
"name": "index.js",
"modules": {
"Sequelize": 1
},
"classes": {},
"fors": {},
"namespaces": {}
}
},
"modules": {
"Sequelize": {
"name": "Sequelize",
"submodules": {},
"classes": {
"QueryInterface": 1,
"Sequelize": 1
},
"fors": {},
"namespaces": {},
"tag": "module",
"file": "lib/sequelize.js",
"line": 12,
"description": "The entry point."
}
},
"classes": {
"QueryInterface": {
"name": "QueryInterface",
"shortname": "QueryInterface",
"classitems": [],
"plugins": [],
"extensions": [],
"plugin_for": [],
"extension_for": [],
"module": "Sequelize",
"file": "lib/dialects/sqlite/query-interface.js",
"line": 3,
"description": "Returns an object that treats SQLite's inabilities to do certain queries.",
"static": 1
},
"Sequelize": {
"name": "Sequelize",
"shortname": "Sequelize",
"classitems": [],
"plugins": [],
"extensions": [],
"plugin_for": [],
"extension_for": [],
"module": "Sequelize",
"file": "lib/sequelize.js",
"line": 12,
"description": "Main class of the project.",
"params": [
{
"name": "database",
"description": "The name of the database.",
"type": "String"
},
{
"name": "username",
"description": "The username which is used to authenticate against the database.",
"type": "String"
},
{
"name": "password",
"description": "The password which is used to authenticate against the database.",
"type": "String",
"optional": true,
"optdefault": "null"
},
{
"name": "options",
"description": "An object with options.",
"type": "Object",
"optional": true,
"optdefault": "{}",
"props": [
{
"name": "dialect",
"description": "The dialect of the relational database.",
"type": "String",
"optional": true,
"optdefault": "'mysql'"
},
{
"name": "host",
"description": "The host of the relational database.",
"type": "String",
"optional": true,
"optdefault": "'localhost'"
},
{
"name": "port",
"description": "The port of the relational database.",
"type": "Integer",
"optional": true,
"optdefault": "3306"
},
{
"name": "protocol",
"description": "The protocol of the relational database.",
"type": "String",
"optional": true,
"optdefault": "'tcp'"
},
{
"name": "define",
"description": "Options, which shall be default for every model definition.",
"type": "Object",
"optional": true,
"optdefault": "{}"
},
{
"name": "query",
"description": "I have absolutely no idea.",
"type": "Object",
"optional": true,
"optdefault": "{}"
},
{
"name": "sync",
"description": "Options, which shall be default for every `sync` call.",
"type": "Object",
"optional": true,
"optdefault": "{}"
},
{
"name": "logging",
"description": "A function that gets executed everytime Sequelize would log something.",
"type": "Function",
"optional": true,
"optdefault": "console.log"
},
{
"name": "omitNull",
"description": "A flag that defines if null values should be passed to SQL queries or not.",
"type": "Boolean",
"optional": true,
"optdefault": "false"
},
{
"name": "queue",
"description": "I have absolutely no idea.",
"type": "Boolean",
"optional": true,
"optdefault": "true"
},
{
"name": "native",
"description": "A flag that defines if native library shall be used or not.",
"type": "Boolean",
"optional": true,
"optdefault": "false"
},
{
"name": "replication",
"description": "I have absolutely no idea.",
"type": "Boolean",
"optional": true,
"optdefault": "false"
},
{
"name": "pool",
"description": "Something.",
"type": "Object",
"optional": true,
"optdefault": "{}"
}
]
}
],
"example": [
"\n // without password and options\n var sequelize = new Sequelize('database', 'username')\n\n // without options\n var sequelize = new Sequelize('database', 'username', 'password')\n\n // without password / with blank password\n var sequelize = new Sequelize('database', 'username', null, {})\n\n // with password and options\n var sequelize = new Sequelize('my_database', 'john', 'doe', {})"
],
"is_constructor": 1
}
},
"classitems": [
{
"file": "lib/dialects/abstract/query.js",
"line": 8,
"description": "Inherit from CustomEventEmitter",
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 13,
"description": "Execute the passed sql query.\n\nExamples:\n\n query.run('SELECT 1')",
"params": [
{
"name": "sql",
"description": "- The SQL query which should be executed.",
"type": "String"
}
],
"api": "public",
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 27,
"description": "Check the logging option of the instance and print deprecation warnings.",
"return": {
"description": "",
"type": "Void"
},
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 44,
"description": "High level function that handles the results of a query execution.\n\n\nExample:\n query.formatResults([\n {\n id: 1, // this is from the main table\n attr2: 'snafu', // this is from the main table\n Tasks.id: 1, // this is from the associated table\n Tasks.title: 'task' // this is from the associated table\n }\n ])",
"params": [
{
"name": "data",
"description": "- The result of the query execution.",
"type": "Array"
}
],
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 102,
"description": "Shortcut methods (success, ok) for listening for success events.\n\nParams:\n - fct: A function that gets executed once the *success* event was triggered.\n\nResult:\n The function returns the instance of the query.",
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 118,
"description": "Shortcut methods (failure, fail, error) for listening for error events.\n\nParams:\n - fct: A function that gets executed once the *error* event was triggered.\n\nResult:\n The function returns the instance of the query.",
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 135,
"description": "This function is a wrapper for private methods.",
"params": [
{
"name": "fctName",
"description": "The name of the private method.",
"type": "String"
}
],
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 146,
"description": "Get the attributes of an insert query, which contains the just inserted id.",
"return": {
"description": "The field name.",
"type": "String"
},
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 159,
"description": "Iterate over all known tables and search their names inside the sql query.\nThis method will also check association aliases ('as' option).",
"params": [
{
"name": "attribute",
"description": "An attribute of a SQL query. (?)",
"type": "String"
}
],
"return": {
"description": "The found tableName / alias.",
"type": "String"
},
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 350,
"description": "The function takes the result of the query execution and groups\nthe associated data by the callee.\n\nExample:\n groupDataByCalleeFactory([\n {\n callee: { some: 'data', id: 1 },\n association: { foo: 'bar', id: 1 }\n }, {\n callee: { some: 'data', id: 1 },\n association: { foo: 'bar', id: 2 }\n }, {\n callee: { some: 'data', id: 1 },\n association: { foo: 'bar', id: 3 }\n }\n ])\n\nResult:\n Something like this:\n\n [\n {\n callee: { some: 'data', id: 1 },\n association: [\n { foo: 'bar', id: 1 },\n { foo: 'bar', id: 2 },\n { foo: 'bar', id: 3 }\n ]\n }\n ]",
"class": "QueryInterface"
},
{
"file": "lib/dialects/abstract/query.js",
"line": 410,
"description": "This function will prepare the result of select queries with joins.",
"params": [
{
"name": "data",
"description": "This array contains objects.",
"type": "Array"
}
],
"return": {
"description": "The array will have the needed format for groupDataByCalleeFactory.",
"type": "Array"
},
"class": "QueryInterface"
},
{
"file": "lib/dialects/sqlite/query-interface.js",
"line": 10,
"description": "A wrapper that fixes SQLite's inability to remove columns from existing tables.\nIt will create a backup of the table, drop the table afterwards and create a\nnew table with the same name but without the obsolete column.",
"itemtype": "method",
"name": "removeColumn",
"params": [
{
"name": "tableName",
"description": "The name of the table.",
"type": "String"
},
{
"name": "attributeName",
"description": "The name of the attribute that we want to remove.",
"type": "String"
},
{
"name": "emitter",
"description": "The EventEmitter from outside.",
"type": "CustomEventEmitter"
},
{
"name": "queryAndEmit",
"description": "The function from outside that triggers some events to get triggered.",
"type": "Function"
}
],
"since": "1.6.0",
"class": "QueryInterface"
},
{
"file": "lib/dialects/sqlite/query-interface.js",
"line": 40,
"description": "A wrapper that fixes SQLite's inability to change columns from existing tables.\nIt will create a backup of the table, drop the table afterwards and create a\nnew table with the same name but with a modified version of the respective column.",
"itemtype": "method",
"name": "changeColumn",
"params": [
{
"name": "tableName",
"description": "The name of the table.",
"type": "String"
},
{
"name": "attributes",
"description": "An object with the attribute's name as key and it's options as value object.",
"type": "Object"
},
{
"name": "emitter",
"description": "The EventEmitter from outside.",
"type": "CustomEventEmitter"
},
{
"name": "queryAndEmit",
"description": "The function from outside that triggers some events to get triggered.",
"type": "Function"
}
],
"since": "1.6.0",
"class": "QueryInterface"
},
{
"file": "lib/dialects/sqlite/query-interface.js",
"line": 72,
"description": "A wrapper that fixes SQLite's inability to rename columns from existing tables.\nIt will create a backup of the table, drop the table afterwards and create a\nnew table with the same name but with a renamed version of the respective column.",
"itemtype": "method",
"name": "renameColumn",
"params": [
{
"name": "tableName",
"description": "The name of the table.",
"type": "String"
},
{
"name": "attrNameBefore",
"description": "The name of the attribute before it was renamed.",
"type": "String"
},
{
"name": "attrNameAfter",
"description": "The name of the attribute after it was renamed.",
"type": "String"
},
{
"name": "emitter",
"description": "The EventEmitter from outside.",
"type": "CustomEventEmitter"
},
{
"name": "queryAndEmit",
"description": "The function from outside that triggers some events to get triggered.",
"type": "Function"
}
],
"since": "1.6.0",
"class": "QueryInterface"
},
{
"file": "lib/dao-factory.js",
"line": 178,
"description": "Search for an instance.",
"params": [
{
"name": "options",
"description": "Options to describe the scope of the search.",
"type": "Object"
},
{
"name": "include",
"description": "A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.",
"type": "Array"
}
],
"return": {
"description": "A promise which fires `success`, `error`, `complete` and `sql`.",
"type": "Object"
},
"class": "Sequelize"
},
{
"file": "lib/sequelize.js",
"line": 93,
"description": "Reference to Utils",
"class": "Sequelize"
},
{
"file": "lib/sequelize.js",
"line": 102,
"description": "Returns an instance of QueryInterface.",
"itemtype": "method",
"name": "getQueryInterface",
"return": {
"description": "An instance (singleton) of QueryInterface.",
"type": "QueryInterface"
},
"class": "Sequelize"
},
{
"file": "lib/sequelize.js",
"line": 113,
"description": "Returns an instance (singleton) of Migrator.",
"itemtype": "method",
"name": "getMigrator",
"params": [
{
"name": "options",
"description": "Some options",
"type": "Object",
"optional": true,
"optdefault": "{}"
},
{
"name": "force",
"description": "A flag that defines if the migrator should get instantiated or not.",
"type": "Boolean",
"optional": true,
"optdefault": "false"
}
],
"return": {
"description": "An instance of Migrator.",
"type": "Migrator"
},
"class": "Sequelize"
}
],
"warnings": [
{
"message": "unknown tag: api",
"line": " lib/dialects/abstract/query.js:13"
},
{
"message": "Missing item type\nInherit from CustomEventEmitter",
"line": " lib/dialects/abstract/query.js:8"
},
{
"message": "Missing item type\nExecute the passed sql query.\n\nExamples:\n\n query.run('SELECT 1')",
"line": " lib/dialects/abstract/query.js:13"
},
{
"message": "Missing item type\nCheck the logging option of the instance and print deprecation warnings.",
"line": " lib/dialects/abstract/query.js:27"
},
{
"message": "Missing item type\nHigh level function that handles the results of a query execution.\n\n\nExample:\n query.formatResults([\n {\n id: 1, // this is from the main table\n attr2: 'snafu', // this is from the main table\n Tasks.id: 1, // this is from the associated table\n Tasks.title: 'task' // this is from the associated table\n }\n ])",
"line": " lib/dialects/abstract/query.js:44"
},
{
"message": "Missing item type\nShortcut methods (success, ok) for listening for success events.\n\nParams:\n - fct: A function that gets executed once the *success* event was triggered.\n\nResult:\n The function returns the instance of the query.",
"line": " lib/dialects/abstract/query.js:102"
},
{
"message": "Missing item type\nShortcut methods (failure, fail, error) for listening for error events.\n\nParams:\n - fct: A function that gets executed once the *error* event was triggered.\n\nResult:\n The function returns the instance of the query.",
"line": " lib/dialects/abstract/query.js:118"
},
{
"message": "Missing item type\nThis function is a wrapper for private methods.",
"line": " lib/dialects/abstract/query.js:135"
},
{
"message": "Missing item type\nGet the attributes of an insert query, which contains the just inserted id.",
"line": " lib/dialects/abstract/query.js:146"
},
{
"message": "Missing item type\nIterate over all known tables and search their names inside the sql query.\nThis method will also check association aliases ('as' option).",
"line": " lib/dialects/abstract/query.js:159"
},
{
"message": "Missing item type\nThe function takes the result of the query execution and groups\nthe associated data by the callee.\n\nExample:\n groupDataByCalleeFactory([\n {\n callee: { some: 'data', id: 1 },\n association: { foo: 'bar', id: 1 }\n }, {\n callee: { some: 'data', id: 1 },\n association: { foo: 'bar', id: 2 }\n }, {\n callee: { some: 'data', id: 1 },\n association: { foo: 'bar', id: 3 }\n }\n ])\n\nResult:\n Something like this:\n\n [\n {\n callee: { some: 'data', id: 1 },\n association: [\n { foo: 'bar', id: 1 },\n { foo: 'bar', id: 2 },\n { foo: 'bar', id: 3 }\n ]\n }\n ]",
"line": " lib/dialects/abstract/query.js:350"
},
{
"message": "Missing item type\nThis function will prepare the result of select queries with joins.",
"line": " lib/dialects/abstract/query.js:410"
},
{
"message": "Missing item type\nSearch for an instance.",
"line": " lib/dao-factory.js:178"
},
{
"message": "Missing item type\nReference to Utils",
"line": " lib/sequelize.js:93"
}
]
}
\ No newline at end of file
<!doctype html>
<html>
<head>
<title>Redirector</title>
<meta http-equiv="refresh" content="0;url=../">
</head>
<body>
<a href="../">Click here to redirect</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>index.js</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1 class="file-heading">File: index.js</h1>
<div class="file">
<pre class="code prettyprint linenums">
&#x2F;**
The entry point.
@module Sequelize
**&#x2F;
module.exports = require(&quot;.&#x2F;lib&#x2F;sequelize&quot;)
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>lib&#x2F;dao-factory.js</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1 class="file-heading">File: lib&#x2F;dao-factory.js</h1>
<div class="file">
<pre class="code prettyprint linenums">
var Utils = require(&quot;.&#x2F;utils&quot;)
, DAO = require(&quot;.&#x2F;dao&quot;)
, DataTypes = require(&quot;.&#x2F;data-types&quot;)
, Util = require(&#x27;util&#x27;)
module.exports = (function() {
var DAOFactory = function(name, attributes, options) {
var self = this
this.options = Utils._.extend({
timestamps: true,
instanceMethods: {},
classMethods: {},
validate: {},
freezeTableName: false,
underscored: false,
syncOnAssociation: true,
paranoid: false,
whereCollection: null
}, options || {})
this.name = name
if (!this.options.tableName) {
this.tableName = this.options.freezeTableName ? name : Utils.pluralize(name)
} else {
this.tableName = this.options.tableName
}
this.rawAttributes = attributes
this.daoFactoryManager = null &#x2F;&#x2F; defined in init function
this.associations = {}
&#x2F;&#x2F; extract validation
this.validate = this.options.validate || {}
}
Object.defineProperty(DAOFactory.prototype, &#x27;attributes&#x27;, {
get: function() {
return this.QueryGenerator.attributesToSQL(this.rawAttributes)
}
})
Object.defineProperty(DAOFactory.prototype, &#x27;QueryInterface&#x27;, {
get: function() { return this.daoFactoryManager.sequelize.getQueryInterface() }
})
Object.defineProperty(DAOFactory.prototype, &#x27;QueryGenerator&#x27;, {
get: function() { return this.QueryInterface.QueryGenerator }
})
DAOFactory.prototype.init = function(daoFactoryManager) {
var self = this;
this.daoFactoryManager = daoFactoryManager
this.primaryKeys = {};
Utils._.each(this.attributes, function(dataTypeString, attributeName) {
&#x2F;&#x2F; If you don&#x27;t specify a valid data type lets help you debug it
if (dataTypeString === undefined) {
throw new Error(&quot;Unrecognized data type for field &quot; + attributeName );
}
if ((attributeName !== &#x27;id&#x27;) &amp;&amp; (dataTypeString.indexOf(&#x27;PRIMARY KEY&#x27;) !== -1)) {
self.primaryKeys[attributeName] = dataTypeString
}
})
this.primaryKeyCount = Object.keys(this.primaryKeys).length;
this.options.hasPrimaryKeys = this.hasPrimaryKeys = this.primaryKeyCount &gt; 0;
addDefaultAttributes.call(this)
addOptionalClassMethods.call(this)
findAutoIncrementField.call(this)
&#x2F;&#x2F; DAO prototype
this.DAO = function() {
DAO.apply(this, arguments);
};
Util.inherits(this.DAO, DAO);
this.DAO.prototype.rawAttributes = this.rawAttributes;
if (this.options.instanceMethods) {
Utils._.each(this.options.instanceMethods, function(fct, name) {
self.DAO.prototype[name] = fct
})
}
this.DAO.prototype.attributes = Object.keys(this.DAO.prototype.rawAttributes);
this.DAO.prototype.booleanValues = [];
this.DAO.prototype.defaultValues = {};
this.DAO.prototype.validators = {};
Utils._.each(this.rawAttributes, function (definition, name) {
if (((definition === DataTypes.BOOLEAN) || (definition.type === DataTypes.BOOLEAN))) {
self.DAO.prototype.booleanValues.push(name);
}
if (definition.hasOwnProperty(&#x27;defaultValue&#x27;)) {
self.DAO.prototype.defaultValues[name] = function() {
return Utils.toDefaultValue(definition.defaultValue);
}
}
if (definition.hasOwnProperty(&#x27;validate&#x27;)) {
self.DAO.prototype.validators[name] = definition.validate;
}
});
this.DAO.prototype.__factory = this;
this.DAO.prototype.hasDefaultValues = !Utils._.isEmpty(this.DAO.prototype.defaultValues);
return this
}
DAOFactory.prototype.sync = function(options) {
options = Utils._.extend({}, this.options, options || {})
var self = this
return new Utils.CustomEventEmitter(function(emitter) {
var doQuery = function() {
self.QueryInterface
.createTable(self.tableName, self.attributes, options)
.success(function() { emitter.emit(&#x27;success&#x27;, self) })
.error(function(err) { emitter.emit(&#x27;error&#x27;, err) })
.on(&#x27;sql&#x27;, function(sql) { emitter.emit(&#x27;sql&#x27;, sql) })
}
if (options.force) {
self.drop().success(doQuery).error(function(err) { emitter.emit(&#x27;error&#x27;, err) })
} else {
doQuery()
}
}).run()
}
DAOFactory.prototype.drop = function() {
return this.QueryInterface.dropTable(this.tableName)
}
&#x2F;&#x2F; alias for findAll
DAOFactory.prototype.all = function(options) {
return this.findAll(options)
}
DAOFactory.prototype.findAll = function(options) {
var hasJoin = false
var options = Utils._.clone(options)
if (typeof options === &#x27;object&#x27;) {
hasJoin = true
if (options.hasOwnProperty(&#x27;include&#x27;)) {
hasJoin = true
options.include = options.include.map(function(include) {
return validateIncludedElement.call(this, include)
}.bind(this))
}
&#x2F;&#x2F; whereCollection is used for non-primary key updates
this.options.whereCollection = options.where || null
}
return this.QueryInterface.select(this, this.tableName, options, {
type: &#x27;SELECT&#x27;,
hasJoin: hasJoin
})
}
&#x2F;&#x2F;right now, the caller (has-many-double-linked) is in charge of the where clause
DAOFactory.prototype.findAllJoin = function(joinTableName, options) {
var optcpy = Utils._.clone(options)
optcpy.attributes = optcpy.attributes || [Utils.addTicks(this.tableName)+&quot;.*&quot;]
&#x2F;&#x2F; whereCollection is used for non-primary key updates
this.options.whereCollection = optcpy.where || null;
return this.QueryInterface.select(this, [this.tableName, joinTableName], optcpy, { type: &#x27;SELECT&#x27; })
}
&#x2F;**
* Search for an instance.
*
* @param {Object} options Options to describe the scope of the search.
* @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: &#x27;Alias&#x27; } ] }.
* @return {Object} A promise which fires &#x60;success&#x60;, &#x60;error&#x60;, &#x60;complete&#x60; and &#x60;sql&#x60;.
*&#x2F;
DAOFactory.prototype.find = function(options) {
var hasJoin = false
&#x2F;&#x2F; no options defined?
&#x2F;&#x2F; return an emitter which emits null
if ([null, undefined].indexOf(options) !== -1) {
return new Utils.CustomEventEmitter(function(emitter) {
setTimeout(function() { emitter.emit(&#x27;success&#x27;, null) }, 10)
}).run()
}
var primaryKeys = this.primaryKeys
&#x2F;&#x2F; options is not a hash but an id
if (typeof options === &#x27;number&#x27;) {
options = { where: options }
} else if (Utils._.size(primaryKeys) &amp;&amp; Utils.argsArePrimaryKeys(arguments, primaryKeys)) {
var where = {}
, self = this
, keys = Object.keys(primaryKeys)
Utils._.each(arguments, function(arg, i) {
var key = keys[i]
where[key] = arg
})
options = { where: where }
} else if (typeof options === &#x27;string&#x27; &amp;&amp; parseInt(options, 10).toString() === options) {
var parsedId = parseInt(options, 10)
if (!Utils._.isFinite(parsedId)) {
throw new Error(&#x27;Invalid argument to find(). Must be an id or an options object.&#x27;)
}
options = { where: parsedId }
} else if (typeof options === &#x27;object&#x27;) {
options = Utils._.clone(options)
if (options.hasOwnProperty(&#x27;include&#x27;)) {
hasJoin = true
options.include = options.include.map(function(include) {
return validateIncludedElement.call(this, include)
}.bind(this))
}
&#x2F;&#x2F; whereCollection is used for non-primary key updates
this.options.whereCollection = options.where || null
}
options.limit = 1
return this.QueryInterface.select(this, this.tableName, options, {
plain: true,
type: &#x27;SELECT&#x27;,
hasJoin: hasJoin
})
}
DAOFactory.prototype.count = function(options) {
options = Utils._.extend({ attributes: [] }, options || {})
options.attributes.push([&#x27;count(*)&#x27;, &#x27;count&#x27;])
options.parseInt = true
return this.QueryInterface.rawSelect(this.tableName, options, &#x27;count&#x27;)
}
DAOFactory.prototype.max = function(field, options) {
options = Utils._.extend({ attributes: [] }, options || {})
options.attributes.push([&#x27;max(&#x27; + field + &#x27;)&#x27;, &#x27;max&#x27;])
options.parseInt = true
return this.QueryInterface.rawSelect(this.tableName, options, &#x27;max&#x27;)
}
DAOFactory.prototype.min = function(field, options) {
options = Utils._.extend({ attributes: [] }, options || {})
options.attributes.push([&#x27;min(&#x27; + field + &#x27;)&#x27;, &#x27;min&#x27;])
options.parseInt = true
return this.QueryInterface.rawSelect(this.tableName, options, &#x27;min&#x27;)
}
DAOFactory.prototype.build = function(values, options) {
options = options || { isNewRecord: true }
var self = this
, instance = new this.DAO(values, this.options, options.isNewRecord)
instance.isNewRecord = options.isNewRecord
instance.daoFactoryName = this.name
instance.daoFactory = this
return instance
}
DAOFactory.prototype.create = function(values, fields) {
return this.build(values).save(fields)
}
DAOFactory.prototype.findOrCreate = function (params, defaults) {
var self = this;
return new Utils.CustomEventEmitter(function (emitter) {
self.find({
where: params
}).success(function (instance) {
if (instance === null) {
for (var attrname in defaults) {
params[attrname] = defaults[attrname]
}
self.create(params)
.success(function (instance) {
emitter.emit(&#x27;success&#x27;, instance)
})
.error( function (error) {
emitter.emit(&#x27;error&#x27;, error)
})
} else {
emitter.emit(&#x27;success&#x27;, instance)
}
}).error(function (error) {
emitter.emit(&#x27;error&#x27;, error)
});
}).run()
}
&#x2F;&#x2F; private
var query = function() {
var args = Utils._.map(arguments, function(arg, _) { return arg })
, sequelize = this.daoFactoryManager.sequelize
&#x2F;&#x2F; add this as the second argument
if (arguments.length === 1) {
args.push(this)
}
&#x2F;&#x2F; add {} as options
if (args.length === 2) {
args.push({})
}
return sequelize.query.apply(sequelize, args)
}
var addOptionalClassMethods = function() {
var self = this
Utils._.each(this.options.classMethods || {}, function(fct, name) { self[name] = fct })
}
var addDefaultAttributes = function() {
var self = this
, defaultAttributes = {
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true
}
}
if (this.hasPrimaryKeys) {
defaultAttributes = {}
}
if (this.options.timestamps) {
defaultAttributes[Utils._.underscoredIf(&#x27;createdAt&#x27;, this.options.underscored)] = {type: DataTypes.DATE, allowNull: false}
defaultAttributes[Utils._.underscoredIf(&#x27;updatedAt&#x27;, this.options.underscored)] = {type: DataTypes.DATE, allowNull: false}
if (this.options.paranoid)
defaultAttributes[Utils._.underscoredIf(&#x27;deletedAt&#x27;, this.options.underscored)] = {type: DataTypes.DATE}
}
Utils._.each(defaultAttributes, function(value, attr) {
self.rawAttributes[attr] = value
})
}
var findAutoIncrementField = function() {
var fields = this.QueryGenerator.findAutoIncrementField(this)
this.autoIncrementField = null
fields.forEach(function(field) {
if (this.autoIncrementField) {
throw new Error(&#x27;Invalid DAO definition. Only one autoincrement field allowed.&#x27;)
} else {
this.autoIncrementField = field
}
}.bind(this))
}
var validateIncludedElement = function(include) {
if (include instanceof DAOFactory) {
include = { daoFactory: include, as: include.tableName }
}
if (typeof include === &#x27;object&#x27;) {
if (include.hasOwnProperty(&#x27;model&#x27;)) {
include.daoFactory = include.model
delete include.model
}
if (include.hasOwnProperty(&#x27;daoFactory&#x27;) &amp;&amp; (include.hasOwnProperty(&#x27;as&#x27;))) {
var usesAlias = (include.as !== include.daoFactory.tableName)
, association = (usesAlias ? this.getAssociationByAlias(include.as) : this.getAssociation(include.daoFactory))
&#x2F;&#x2F; check if the current daoFactory is actually associated with the passed daoFactory
if (!!association &amp;&amp; (!association.options.as || (association.options.as === include.as))) {
include.association = association
return include
} else {
var msg = include.daoFactory.name
if (usesAlias) {
msg += &quot; (&quot; + include.as + &quot;)&quot;
}
msg += &quot; is not associated to &quot; + this.name + &quot;!&quot;
throw new Error(msg)
}
} else {
throw new Error(&#x27;Include malformed. Expected attributes: daoFactory, as!&#x27;)
}
} else {
throw new Error(&#x27;Include unexpected. Element has to be either an instance of DAOFactory or an object.&#x27;)
}
}
Utils._.extend(DAOFactory.prototype, require(&quot;.&#x2F;associations&#x2F;mixin&quot;))
return DAOFactory
})()
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>lib&#x2F;dialects&#x2F;abstract&#x2F;query.js</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1 class="file-heading">File: lib&#x2F;dialects&#x2F;abstract&#x2F;query.js</h1>
<div class="file">
<pre class="code prettyprint linenums">
var Utils = require(&#x27;..&#x2F;..&#x2F;utils&#x27;)
, CustomEventEmitter = require(&quot;..&#x2F;..&#x2F;emitters&#x2F;custom-event-emitter&quot;)
, Dot = require(&#x27;dottie&#x27;)
module.exports = (function() {
var AbstractQuery = function(database, sequelize, callee, options) {}
&#x2F;**
Inherit from CustomEventEmitter
*&#x2F;
Utils.inherit(AbstractQuery, CustomEventEmitter)
&#x2F;**
* Execute the passed sql query.
*
* Examples:
*
* query.run(&#x27;SELECT 1&#x27;)
*
* @param {String} sql - The SQL query which should be executed.
* @api public
*&#x2F;
AbstractQuery.prototype.run = function(sql) {
throw new Error(&quot;The run method wasn&#x27;t overwritten!&quot;)
}
&#x2F;**
* Check the logging option of the instance and print deprecation warnings.
*
* @return {void}
*&#x2F;
AbstractQuery.prototype.checkLoggingOption = function() {
if (this.options.logging === true) {
console.log(&#x27;DEPRECATION WARNING: The logging-option should be either a function or false. Default: console.log&#x27;)
this.options.logging = console.log
}
if (this.options.logging === console.log) {
&#x2F;&#x2F; using just console.log will break in node &lt; 0.6
this.options.logging = function(s) { console.log(s) }
}
}
&#x2F;**
* High level function that handles the results of a query execution.
*
*
* Example:
* query.formatResults([
* {
* id: 1, &#x2F;&#x2F; this is from the main table
* attr2: &#x27;snafu&#x27;, &#x2F;&#x2F; this is from the main table
* Tasks.id: 1, &#x2F;&#x2F; this is from the associated table
* Tasks.title: &#x27;task&#x27; &#x2F;&#x2F; this is from the associated table
* }
* ])
*
* @param {Array} data - The result of the query execution.
*&#x2F;
AbstractQuery.prototype.formatResults = function(data) {
var result = this.callee
if (isInsertQuery.call(this, data)) {
handleInsertQuery.call(this, data)
}
if (isSelectQuery.call(this)) {
result = handleSelectQuery.call(this, data)
} else if (isShowTableQuery.call(this)) {
result = handleShowTableQuery.call(this, data)
} else if (isShowOrDescribeQuery.call(this)) {
result = data
if (this.sql.toLowerCase().indexOf(&#x27;describe&#x27;) === 0) {
result = {}
data.forEach(function(_result) {
result[_result.Field] = {
type: _result.Type.toUpperCase(),
allowNull: (_result.Null === &#x27;YES&#x27;),
defaultValue: _result.Default
}
})
} else if (this.sql.toLowerCase().indexOf(&#x27;show index from&#x27;) === 0) {
result = Utils._.uniq(result.map(function(result) {
return {
name: result.Key_name,
tableName: result.Table,
unique: (result.Non_unique !== 1)
}
}), false, function(row) {
return row.name
})
}
} else if (isCallQuery.call(this)) {
result = data[0]
}
return result
}
&#x2F;**
Shortcut methods (success, ok) for listening for success events.
Params:
- fct: A function that gets executed once the *success* event was triggered.
Result:
The function returns the instance of the query.
*&#x2F;
AbstractQuery.prototype.success =
AbstractQuery.prototype.ok =
function(fct) {
this.on(&#x27;success&#x27;, fct)
return this
}
&#x2F;**
Shortcut methods (failure, fail, error) for listening for error events.
Params:
- fct: A function that gets executed once the *error* event was triggered.
Result:
The function returns the instance of the query.
*&#x2F;
AbstractQuery.prototype.failure =
AbstractQuery.prototype.fail =
AbstractQuery.prototype.error =
function(fct) {
this.on(&#x27;error&#x27;, fct)
return this
}
&#x2F;**
* This function is a wrapper for private methods.
*
* @param {String} fctName The name of the private method.
*
*&#x2F;
AbstractQuery.prototype.send = function(fctName&#x2F;*, arg1, arg2, arg3, ...*&#x2F;) {
var args = Array.prototype.slice.call(arguments).slice(1)
return eval(fctName).apply(this, args)
}
&#x2F;**
* Get the attributes of an insert query, which contains the just inserted id.
*
* @return {String} The field name.
*&#x2F;
AbstractQuery.prototype.getInsertIdField = function() {
return &#x27;insertId&#x27;
}
&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;
&#x2F;&#x2F; private &#x2F;&#x2F;
&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;&#x2F;
&#x2F;**
* Iterate over all known tables and search their names inside the sql query.
* This method will also check association aliases (&#x27;as&#x27; option).
*
* @param {String} attribute An attribute of a SQL query. (?)
* @return {String} The found tableName &#x2F; alias.
*&#x2F;
var findTableNameInAttribute = function(attribute) {
if (!this.options.include) {
return null
}
var tableNames = this.options.include.map(function(include) {
return include.as
}).filter(function(include) {
return attribute.indexOf(include + &#x27;.&#x27;) === 0
})
if (tableNames.length === 1) {
return tableNames[0]
} else {
return null
}
}
var queryResultHasJoin = function(results) {
if (!!results[0]) {
var keys = Object.keys(results[0])
for (var i = 0; i &lt; keys.length; i++) {
if (!!findTableNameInAttribute.call(this, keys[i])) {
return true
}
}
}
return false
}
var isInsertQuery = function(results, metaData) {
var result = true
&#x2F;&#x2F; is insert query if sql contains insert into
result = result &amp;&amp; (this.sql.toLowerCase().indexOf(&#x27;insert into&#x27;) === 0)
&#x2F;&#x2F; is insert query if no results are passed or if the result has the inserted id
result = result &amp;&amp; (!results || results.hasOwnProperty(this.getInsertIdField()))
&#x2F;&#x2F; is insert query if no metadata are passed or if the metadata has the inserted id
result = result &amp;&amp; (!metaData || metaData.hasOwnProperty(this.getInsertIdField()))
return result
}
var handleInsertQuery = function(results, metaData) {
if (this.callee) {
&#x2F;&#x2F; add the inserted row id to the instance
var autoIncrementField = this.callee.__factory.autoIncrementField
, id = null
id = id || (results &amp;&amp; results[this.getInsertIdField()])
id = id || (metaData &amp;&amp; metaData[this.getInsertIdField()])
this.callee[autoIncrementField] = id
}
}
var isShowTableQuery = function() {
return (this.sql.toLowerCase().indexOf(&#x27;show tables&#x27;) === 0)
}
var handleShowTableQuery = function(results) {
return Utils._.flatten(results.map(function(resultSet) {
return Utils._.values(resultSet)
}))
}
var isSelectQuery = function() {
return this.options.type === &#x27;SELECT&#x27;;
}
var isUpdateQuery = function() {
return (this.sql.toLowerCase().indexOf(&#x27;update&#x27;) === 0)
}
var handleSelectQuery = function(results) {
var result = null
if (this.options.raw) {
result = results.map(function(result) {
var o = {}
for (var key in result) {
if (result.hasOwnProperty(key)) {
o[key] = result[key]
}
}
return o
})
result = result.map(Dot.transform)
} else if (this.options.hasJoin === true) {
result = prepareJoinData.call(this, results)
result = groupDataByCalleeFactory.call(this, result).map(function(result) {
&#x2F;&#x2F; let&#x27;s build the actual dao instance first...
var dao = this.callee.build(result[this.callee.tableName], { isNewRecord: false })
&#x2F;&#x2F; ... and afterwards the prefetched associations
for (var tableName in result) {
if (result.hasOwnProperty(tableName) &amp;&amp; (tableName !== this.callee.tableName)) {
buildAssociatedDaoInstances.call(this, tableName, result[tableName], dao)
}
}
return dao
}.bind(this))
} else {
result = results.map(function(result) {
return this.callee.build(result, { isNewRecord: false })
}.bind(this))
}
&#x2F;&#x2F; return the first real model instance if options.plain is set (e.g. Model.find)
if (this.options.plain) {
result = (result.length === 0) ? null : result[0]
}
return result
}
var buildAssociatedDaoInstances = function(tableName, associationData, dao) {
var associatedDaoFactory = this.sequelize.daoFactoryManager.getDAO(tableName, { attribute: &#x27;tableName&#x27; })
, association = null
if (!!associatedDaoFactory) {
association = this.callee.getAssociation(associatedDaoFactory)
} else {
associatedDaoFactory = this.sequelize.daoFactoryManager.getDAO(Utils.pluralize(tableName), { attribute: &#x27;tableName&#x27; })
if (!!associatedDaoFactory) {
association = this.callee.getAssociation(associatedDaoFactory)
} else {
association = this.callee.getAssociationByAlias(tableName)
associatedDaoFactory = association.target
}
}
var accessor = Utils._.camelize(tableName)
&#x2F;&#x2F; downcase the first char
accessor = accessor.slice(0,1).toLowerCase() + accessor.slice(1)
associationData.forEach(function(data) {
var daoInstance = associatedDaoFactory.build(data, { isNewRecord: false })
, isEmpty = ! Utils.firstValueOfHash(daoInstance.identifiers)
if ([&#x27;BelongsTo&#x27;, &#x27;HasOne&#x27;].indexOf(association.associationType) &gt; -1) {
accessor = Utils.singularize(accessor)
dao[accessor] = isEmpty ? null : daoInstance
} else {
dao[accessor] = dao[accessor] || []
if (!isEmpty) {
dao[accessor].push(daoInstance)
}
}
&#x2F;&#x2F; add the accessor to the eagerly loaded associations array
dao.__eagerlyLoadedAssociations = Utils._.uniq(dao.__eagerlyLoadedAssociations.concat([accessor]))
})
}
var isShowOrDescribeQuery = function() {
var result = false
result = result || (this.sql.toLowerCase().indexOf(&#x27;show&#x27;) === 0)
result = result || (this.sql.toLowerCase().indexOf(&#x27;describe&#x27;) === 0)
return result
}
var isCallQuery = function() {
var result = false
result = result || (this.sql.toLowerCase().indexOf(&#x27;call&#x27;) === 0)
return result
}
&#x2F;**
The function takes the result of the query execution and groups
the associated data by the callee.
Example:
groupDataByCalleeFactory([
{
callee: { some: &#x27;data&#x27;, id: 1 },
association: { foo: &#x27;bar&#x27;, id: 1 }
}, {
callee: { some: &#x27;data&#x27;, id: 1 },
association: { foo: &#x27;bar&#x27;, id: 2 }
}, {
callee: { some: &#x27;data&#x27;, id: 1 },
association: { foo: &#x27;bar&#x27;, id: 3 }
}
])
Result:
Something like this:
[
{
callee: { some: &#x27;data&#x27;, id: 1 },
association: [
{ foo: &#x27;bar&#x27;, id: 1 },
{ foo: &#x27;bar&#x27;, id: 2 },
{ foo: &#x27;bar&#x27;, id: 3 }
]
}
]
*&#x2F;
var groupDataByCalleeFactory = function(data) {
var result = []
, calleeTableName = this.callee.tableName
data.forEach(function(row) {
var calleeData = row[calleeTableName]
, existingEntry = result.filter(function(groupedRow) {
return Utils._.isEqual(groupedRow[calleeTableName], calleeData)
})[0]
if (!existingEntry) {
existingEntry = {}
result.push(existingEntry)
existingEntry[calleeTableName] = calleeData
}
for (var attrName in row) {
if (row.hasOwnProperty(attrName) &amp;&amp; (attrName !== calleeTableName)) {
existingEntry[attrName] = existingEntry[attrName] || []
existingEntry[attrName].push(row[attrName])
}
}
})
return result
}
&#x2F;**
* This function will prepare the result of select queries with joins.
*
* @param {Array} data This array contains objects.
* @return {Array} The array will have the needed format for groupDataByCalleeFactory.
*&#x2F;
var prepareJoinData = function(data) {
var result = data.map(function(row) {
var nestedRow = {}
for (var key in row) {
if (row.hasOwnProperty(key)) {
var tableName = findTableNameInAttribute.call(this, key)
if (!!tableName) {
nestedRow[tableName] = nestedRow[tableName] || {}
nestedRow[tableName][key.replace(tableName + &#x27;.&#x27;, &#x27;&#x27;)] = row[key]
} else {
nestedRow[this.callee.tableName] = nestedRow[this.callee.tableName] || {}
nestedRow[this.callee.tableName][key] = row[key]
}
}
}
return nestedRow
}.bind(this))
return result
}
return AbstractQuery
})()
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>lib&#x2F;dialects&#x2F;sqlite&#x2F;query-interface.js</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1 class="file-heading">File: lib&#x2F;dialects&#x2F;sqlite&#x2F;query-interface.js</h1>
<div class="file">
<pre class="code prettyprint linenums">
var Utils = require(&quot;..&#x2F;..&#x2F;utils&quot;)
&#x2F;**
Returns an object that treats SQLite&#x27;s inabilities to do certain queries.
@class QueryInterface
@static
*&#x2F;
var QueryInterface = module.exports = {
&#x2F;**
A wrapper that fixes SQLite&#x27;s inability to remove columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a
new table with the same name but without the obsolete column.
@method removeColumn
@for QueryInterface
@param {String} tableName The name of the table.
@param {String} attributeName The name of the attribute that we want to remove.
@param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0
*&#x2F;
removeColumn: function(tableName, attributeName, emitter, queryAndEmit) {
this.describeTable(tableName).complete(function(err, fields) {
if (err) {
emitter.emit(&#x27;error&#x27;, err)
} else {
delete fields[attributeName]
var sql = this.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(&#x27;;&#x27;).filter(function(q) { return q !== &#x27;&#x27; })
QueryInterface.execMultiQuery.call(this, subQueries, &#x27;removeColumn&#x27;, emitter, queryAndEmit)
}
}.bind(this))
},
&#x2F;**
A wrapper that fixes SQLite&#x27;s inability to change columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a
new table with the same name but with a modified version of the respective column.
@method changeColumn
@for QueryInterface
@param {String} tableName The name of the table.
@param {Object} attributes An object with the attribute&#x27;s name as key and it&#x27;s options as value object.
@param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0
*&#x2F;
changeColumn: function(tableName, attributes, emitter, queryAndEmit) {
var attributeName = Utils._.keys(attributes)[0]
this.describeTable(tableName).complete(function(err, fields) {
if (err) {
emitter.emit(&#x27;error&#x27;, err)
} else {
fields[attributeName] = attributes[attributeName]
var sql = this.QueryGenerator.removeColumnQuery(tableName, fields)
, subQueries = sql.split(&#x27;;&#x27;).filter(function(q) { return q !== &#x27;&#x27; })
QueryInterface.execMultiQuery.call(this, subQueries, &#x27;changeColumn&#x27;, emitter, queryAndEmit)
}
}.bind(this))
},
&#x2F;**
A wrapper that fixes SQLite&#x27;s inability to rename columns from existing tables.
It will create a backup of the table, drop the table afterwards and create a
new table with the same name but with a renamed version of the respective column.
@method renameColumn
@for QueryInterface
@param {String} tableName The name of the table.
@param {String} attrNameBefore The name of the attribute before it was renamed.
@param {String} attrNameAfter The name of the attribute after it was renamed.
@param {CustomEventEmitter} emitter The EventEmitter from outside.
@param {Function} queryAndEmit The function from outside that triggers some events to get triggered.
@since 1.6.0
*&#x2F;
renameColumn: function(tableName, attrNameBefore, attrNameAfter, emitter, queryAndEmit) {
this.describeTable(tableName).complete(function(err, fields) {
if (err) {
emitter.emit(&#x27;error&#x27;, err)
} else {
fields[attrNameAfter] = Utils._.clone(fields[attrNameBefore])
delete fields[attrNameBefore]
var sql = this.QueryGenerator.renameColumnQuery(tableName, attrNameBefore, attrNameAfter, fields)
, subQueries = sql.split(&#x27;;&#x27;).filter(function(q) { return q !== &#x27;&#x27; })
QueryInterface.execMultiQuery.call(this, subQueries, &#x27;renameColumn&#x27;, emitter, queryAndEmit)
}
}.bind(this))
},
execMultiQuery: function(queries, methodName, emitter, queryAndEmit) {
var chainer = new Utils.QueryChainer()
queries.splice(0, queries.length - 1).forEach(function(query) {
chainer.add(this.sequelize, &#x27;query&#x27;, [query + &quot;;&quot;, null, { raw: true }])
}.bind(this))
chainer
.runSerially()
.complete(function(err) {
if (err) {
emitter.emit(methodName, err)
emitter.emit(&#x27;error&#x27;, err)
} else {
queryAndEmit.call(this, queries.splice(queries.length - 1)[0], methodName, {}, emitter)
}
}.bind(this))
}
}
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>lib&#x2F;sequelize.js</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1 class="file-heading">File: lib&#x2F;sequelize.js</h1>
<div class="file">
<pre class="code prettyprint linenums">
var Utils = require(&quot;.&#x2F;utils&quot;)
, DAOFactory = require(&quot;.&#x2F;dao-factory&quot;)
, DataTypes = require(&#x27;.&#x2F;data-types&#x27;)
, DAOFactoryManager = require(&quot;.&#x2F;dao-factory-manager&quot;)
, QueryInterface = require(&quot;.&#x2F;query-interface&quot;)
if (typeof process != &#x27;undefined&#x27; &amp;&amp; parseFloat(process.version.replace(&#x27;v&#x27;, &#x27;&#x27;)) &lt; 0.6) {
console.log(&quot;DEPRECATION WARNING: Support for Node.JS &lt; v0.6 will be canceled in the next minor release.&quot;)
}
module.exports = (function() {
&#x2F;**
Main class of the project.
@param {String} database The name of the database.
@param {String} username The username which is used to authenticate against the database.
@param {String} [password=null] The password which is used to authenticate against the database.
@param {Object} [options={}] An object with options.
@param {String} [options.dialect=&#x27;mysql&#x27;] The dialect of the relational database.
@param {String} [options.host=&#x27;localhost&#x27;] The host of the relational database.
@param {Integer} [options.port=3306] The port of the relational database.
@param {String} [options.protocol=&#x27;tcp&#x27;] The protocol of the relational database.
@param {Object} [options.define={}] Options, which shall be default for every model definition.
@param {Object} [options.query={}] I have absolutely no idea.
@param {Object} [options.sync={}] Options, which shall be default for every &#x60;sync&#x60; call.
@param {Function} [options.logging=console.log] A function that gets executed everytime Sequelize would log something.
@param {Boolean} [options.omitNull=false] A flag that defines if null values should be passed to SQL queries or not.
@param {Boolean} [options.queue=true] I have absolutely no idea.
@param {Boolean} [options.native=false] A flag that defines if native library shall be used or not.
@param {Boolean} [options.replication=false] I have absolutely no idea.
@param {Object} [options.pool={}] Something.
@example
&#x2F;&#x2F; without password and options
var sequelize = new Sequelize(&#x27;database&#x27;, &#x27;username&#x27;)
&#x2F;&#x2F; without options
var sequelize = new Sequelize(&#x27;database&#x27;, &#x27;username&#x27;, &#x27;password&#x27;)
&#x2F;&#x2F; without password &#x2F; with blank password
var sequelize = new Sequelize(&#x27;database&#x27;, &#x27;username&#x27;, null, {})
&#x2F;&#x2F; with password and options
var sequelize = new Sequelize(&#x27;my_database&#x27;, &#x27;john&#x27;, &#x27;doe&#x27;, {})
@class Sequelize
@constructor
*&#x2F;
var Sequelize = function(database, username, password, options) {
this.options = Utils._.extend({
dialect: &#x27;mysql&#x27;,
host: &#x27;localhost&#x27;,
port: 3306,
protocol: &#x27;tcp&#x27;,
define: {},
query: {},
sync: {},
logging: console.log,
omitNull: false,
queue: true,
native: false,
replication: false,
pool: {}
}, options || {})
if (this.options.logging === true) {
console.log(&#x27;DEPRECATION WARNING: The logging-option should be either a function or false. Default: console.log&#x27;)
this.options.logging = console.log
}
this.config = {
database: database,
username: username,
password: (( ([&quot;&quot;, null, false].indexOf(password) &gt; -1) || (typeof password == &#x27;undefined&#x27;)) ? null : password),
host : this.options.host,
port : this.options.port,
pool : this.options.pool,
protocol: this.options.protocol,
queue : this.options.queue,
native : this.options.native,
replication: this.options.replication,
maxConcurrentQueries: this.options.maxConcurrentQueries
}
var ConnectorManager = require(&quot;.&#x2F;dialects&#x2F;&quot; + this.options.dialect + &quot;&#x2F;connector-manager&quot;)
this.daoFactoryManager = new DAOFactoryManager(this)
this.connectorManager = new ConnectorManager(this, this.config)
this.importCache = {}
}
&#x2F;**
Reference to Utils
*&#x2F;
Sequelize.Utils = Utils
for (var dataType in DataTypes) {
Sequelize[dataType] = DataTypes[dataType]
}
&#x2F;**
Returns an instance of QueryInterface.
@method getQueryInterface
@return {QueryInterface} An instance (singleton) of QueryInterface.
*&#x2F;
Sequelize.prototype.getQueryInterface = function() {
this.queryInterface = this.queryInterface || new QueryInterface(this)
return this.queryInterface
}
&#x2F;**
Returns an instance (singleton) of Migrator.
@method getMigrator
@param {Object} [options={}] Some options
@param {Boolean} [force=false] A flag that defines if the migrator should get instantiated or not.
@return {Migrator} An instance of Migrator.
*&#x2F;
Sequelize.prototype.getMigrator = function(options, force) {
var Migrator = require(&quot;.&#x2F;migrator&quot;)
if (force) {
this.migrator = new Migrator(this, options)
} else {
this.migrator = this.migrator || new Migrator(this, options)
}
return this.migrator
}
Sequelize.prototype.define = function(daoName, attributes, options) {
options = options || {}
var globalOptions = this.options
if (globalOptions.define) {
options = Utils._.extend({}, globalOptions.define, options)
Utils._([&#x27;classMethods&#x27;, &#x27;instanceMethods&#x27;]).each(function(key) {
if (globalOptions.define[key]) {
options[key] = options[key] || {}
Utils._.extend(options[key], globalOptions.define[key])
}
})
}
options.omitNull = globalOptions.omitNull
var factory = new DAOFactory(daoName, attributes, options)
this.daoFactoryManager.addDAO(factory.init(this.daoFactoryManager))
return factory
}
Sequelize.prototype.isDefined = function(daoName) {
var daos = this.daoFactoryManager.daos
return (daos.filter(function(dao) { return dao.name === daoName }).length !== 0)
}
Sequelize.prototype.import = function(path) {
if (!this.importCache[path]) {
var defineCall = require(path)
this.importCache[path] = defineCall(this, DataTypes)
}
return this.importCache[path]
}
Sequelize.prototype.migrate = function(options) {
this.getMigrator().migrate(options)
}
Sequelize.prototype.query = function(sql, callee, options, replacements) {
if (arguments.length === 4) {
sql = Utils.format([sql].concat(replacements))
} else if (arguments.length === 3) {
options = options
} else if (arguments.length === 2) {
options = {}
} else {
options = { raw: true }
}
options = Utils._.extend(Utils._.clone(this.options.query), options)
options = Utils._.defaults(options, {
logging: this.options.hasOwnProperty(&#x27;logging&#x27;) ? this.options.logging : console.log,
type: (sql.toLowerCase().indexOf(&#x27;select&#x27;) === 0) ? &#x27;SELECT&#x27; : false
})
return this.connectorManager.query(sql, callee, options)
}
Sequelize.prototype.sync = function(options) {
options = options || {}
if (this.options.sync) {
options = Utils._.extend({}, this.options.sync, options)
}
var chainer = new Utils.QueryChainer()
this.daoFactoryManager.daos.forEach(function(dao) {
chainer.add(dao.sync(options))
})
return chainer.run()
}
Sequelize.prototype.drop = function() {
var self = this
return new Utils.CustomEventEmitter(function(emitter) {
var chainer = new Utils.QueryChainer
self.daoFactoryManager.daos.forEach(function(dao) { chainer.add(dao.drop()) })
chainer
.run()
.success(function() { emitter.emit(&#x27;success&#x27;, null) })
.error(function(err) { emitter.emit(&#x27;error&#x27;, err) })
}).run()
}
return Sequelize
})()
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href=".&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href=".&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href=".&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src=".&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href=".&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href=".&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href=".&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<div class="apidocs">
<div id="docs-main" class="content">
<p>
Browse to a module or class using the sidebar to view its API documentation.
</p>
<h2>Keyboard Shortcuts</h2>
<ul>
<li><p>Press <kbd>s</kbd> to focus the API search box.</p></li>
<li><p>Use <kbd>Up</kbd> and <kbd>Down</kbd> to select classes, modules, and search results.</p></li>
<li class="mac-only"><p>With the API search box or sidebar focused, use <kbd><span class="cmd">&#x2318;</span>-Left</kbd> or <kbd><span class="cmd">&#x2318;</span>-Right</kbd> to switch sidebar tabs.</p></li>
<li class="pc-only"><p>With the API search box or sidebar focused, use <kbd>Ctrl+Left</kbd> and <kbd>Ctrl+Right</kbd> to switch sidebar tabs.</p></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src=".&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src=".&#x2F;assets/js/yui-prettify.js"></script>
<script src=".&#x2F;assets/../api.js"></script>
<script src=".&#x2F;assets/js/api-filter.js"></script>
<script src=".&#x2F;assets/js/api-list.js"></script>
<script src=".&#x2F;assets/js/api-search.js"></script>
<script src=".&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
var markdox = require('markdox')
, program = require('commander')
, fs = require('fs')
, _ = require('lodash');
program
.version('0.0.1')
.option('-f, --file [file]', 'Process a single file', '')
.option('-a, --all', 'Process all files, generate index etc. (default if no options are specified')
.option('-c, --clean', 'Remove all generated markdown and HTML files')
.option('--html', 'Generate html files from the markdown ones (requires manual installation of the github-flavored-markdown package')
.parse(process.argv)
if (program.clean) {
fs.readdirSync('docs/').forEach(function (file) {
if (file.indexOf('.ejs') === -1 && file.indexOf('.js') === -1) {
fs.unlinkSync ('docs/' + file);
}
})
return
}
if (program.html) {
var ghm = require('github-flavored-markdown')
}
var getTag = function(tags, tagName) {
return _.find(tags, function (tag) {
return tag.type === tagName;
});
};
var getTags = function(tags, tagName) {
return _.where(tags, function (tag) {
return tag.type === tagName;
});
}
var options = {
formatter: function (docfile) {
docfile = markdox.defaultFormatter(docfile);
docfile.members = [];
docfile.javadoc.forEach(function(javadoc){
// Find constructor tags
javadoc.isConstructor = getTag(javadoc.raw.tags, 'constructor') !== undefined;
javadoc.isMixin = getTag(javadoc.raw.tags, 'mixin') !== undefined;
javadoc.isProperty = getTag(javadoc.raw.tags, 'property') !== undefined
javadoc.private = getTag(javadoc.raw.tags, 'private') !== undefined
// Only show params without a dot in them (dots means attributes of object, so no need to clutter the signature too much)
var params = []
javadoc.paramTags.forEach(function (paramTag) {
if (paramTag.name.indexOf('.') === -1) {
params.push(paramTag.name);
}
});
javadoc.paramStr = (javadoc.isMethod || javadoc.isFunction) ? '(' + params.join(', ') + ')' : '';
// Convert | to &#124; to be able to use github flavored md tables
if (javadoc.paramTags) {
javadoc.paramTags.forEach(function (paramTag) {
paramTag.joinedTypes = paramTag.joinedTypes.replace(/\|/g, '&#124;')
});
}
// Handle aliases
javadoc.aliases = getTags(javadoc.raw.tags, 'alias').map(function (a) {
return a.string
}).join(', ')
// Handle deprecation text
if (javadoc.deprecated) {
var deprecation = getTag(javadoc.raw.tags, 'deprecated')
javadoc.deprecated = deprecation.string
}
// Handle linking in comments
javadoc.see = getTags(javadoc.raw.tags, 'see');
javadoc.see.forEach(function (see, i, collection) {
collection[i] = {}
if (see.local) {
collection[i].external = false
if (see.local.indexOf('{') === 0){
var _see = see.local.split('}')
_see[0] = _see[0].substring(1)
collection[i].url = 'API-Reference-' + _see[0]
collection[i].text = see.local.replace(/{|}/g, '')
} else {
collection[i].url = false
collection[i].text = see.local
}
} else {
see.external = true
see.text = see.url
collection[i] = see
}
})
// Set a name for properties
if (!javadoc.name) {
var property = getTag(javadoc.raw.tags, 'property')
if (property) {
javadoc.name = property.string
}
}
if (javadoc.isMixin) {
javadoc.name = getTag(javadoc.raw.tags, 'mixin').string;
}
javadoc.mixes = getTags(javadoc.raw.tags, 'mixes').map(function (mix) {
return {
text: mix.string,
link: (mix.string.indexOf('www') !== -1 || mix.string.indexOf('http') !== -1) ? mix.string: 'API-Reference-' + mix.string
}
})
if (!javadoc.isClass) {
if (!javadoc.isProperty) {
docfile.members.push({
text: javadoc.name + javadoc.paramStr,
link: '#' + javadoc.name
})
} else {
docfile.members.push({
text: javadoc.name,
link: '#' + javadoc.name
})
}
}
});
return docfile;
},
template: 'docs/output.md.ejs'
};
var files;
if (program.file) {
files = [{file: program.file, output: 'tmp'}]
} else {
files = [
{file:'lib/sequelize.js', output: 'API-Reference-Sequelize'},
{file:'lib/dao.js', output: 'API-Reference-DAO'},
{file:'lib/dao-factory.js', output: 'API-Reference-DAOFactory'},
{file:'lib/query-chainer.js', output: 'API-Reference-QueryChainer'},
{file:'lib/emitters/custom-event-emitter.js', output: 'API-Reference-EventEmitter'},
{file:'lib/hooks.js', output: 'API-Reference-Hooks'},
{file:'lib/associations/mixin.js', output: 'API-Reference-Associations'}
];
}
files.forEach(function (file) {
var opts = _.clone(options)
, output = 'docs/' + file.output + '.md'
opts.output = output
markdox.process(file.file, opts, function(){
if (program.html) {
var md = fs.readFileSync(output).toString();
fs.writeFileSync(output.replace('md', 'html'), ghm.parse(md))
}
});
})
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sequelize</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.8.0&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.8.0&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<h1><img src="..&#x2F;assets/css/logo.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/QueryInterface.html">QueryInterface</a></li>
<li><a href="..&#x2F;classes/Sequelize.html">Sequelize</a></li>
</ul>
<ul id="api-modules" class="apis modules">
<li><a href="..&#x2F;modules/Sequelize.html">Sequelize</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1>Sequelize Module</h1>
<div class="box clearfix meta">
<div class="foundat">
Defined in: <a href="..&#x2F;files&#x2F;lib_sequelize.js.html#l12"><code>lib&#x2F;sequelize.js:12</code></a>
</div>
</div>
<div class="box intro">
<p>The entry point.</p>
</div>
<div class="yui3-g">
<div class="yui3-u-1-2">
<p>This module provides the following classes:</p>
<ul class="module-classes">
<li class="module-class">
<a href="..&#x2F;classes/QueryInterface.html">
QueryInterface
</a>
</li>
<li class="module-class">
<a href="..&#x2F;classes/Sequelize.html">
Sequelize
</a>
</li>
</ul>
</div>
<div class="yui3-u-1-2">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>
<!doctype html>
<html>
<head>
<title>Redirector</title>
<meta http-equiv="refresh" content="0;url=../">
</head>
<body>
<a href="../">Click here to redirect</a>
</body>
</html>
<? docfiles.forEach(function(doc) { ?>
<? doc.javadoc.forEach(function(comment) { ?>
<? if (comment.name && comment.private !== true) { -?>
<? if (!comment.ignore) { ?>
<a name="<?= comment.name ?>" />
<? if (comment.isConstructor) { ?>
### `new <?= comment.name ?><?= comment.paramStr ?>`
<? } else if (comment.isMixin) { ?>
### Mixin <?= comment.name ?>
<? } else if (comment.isClass) { ?>
### Class <?= comment.name ?>
<? } else { ?>
#### `<?= comment.name ?><?= comment.paramStr ?>` <? if (comment.returnTags.length > 0) { ?> -> `<?= comment.returnTags[0].joinedTypes ?>` <? } ?>
<? } ?>
<? } ?>
<?= comment.description ?>
<? if (comment.mixes.length) { ?>
### Mixes:
<? comment.mixes.forEach(function (mix) { -?>
* [<?=mix.text ?>](<?=mix.link ?>)
<? }) ?>
<? } ?>
<? if (comment.isClass) { ?>
### Members:
<? doc.members.forEach(function (member) { -?>
* [<?= member.text ?>](<?= member.link ?>)
<? }) -?>
<? } ?>
<? if (comment.deprecated) { ?>
**Deprecated** <?- comment.deprecated ?>
<? } ?>
<? if (comment.version) { ?>
Version: <?= comment.version ?>
<? } ?>
<? if (comment.see.length) { ?>See:<? } ?>
<? comment.see.forEach(function (see) { -?>
<? if (see.url !== false) { -?>
* [<?= see.text ?>](<?= see.url ?>)
<? } else { -?>
* <?= see.text ?>
<? } -?>
<? }) -?>
<? if (comment.paramTags.length > 0) { ?>
##### Params:
| Name | Type | Description |
| ---- | ---- | ----------- |
<? comment.paramTags.forEach(function(paramTag) { -?>
| <?= paramTag.name ?> | <?= paramTag.joinedTypes ?> | <?= paramTag.description ?> |
<? }) ?>
<? } ?>
<? if (comment.returnTags.length > 0 && comment.returnTags[0].description.length > 0) { ?>
__Returns:__ <?= comment.returnTags[0].description ?>
<? } ?>
<? if (comment.aliases) { ?>
__Aliases:__ *<?= comment.aliases ?>*
<? } ?>
======
<? } ?>
<? }) ?>
_This document is automatically generated based on source code comments. Please do not edit it directly, as your changes will be ignored. Please write on <a href="irc://irc.freenode.net/#sequelizejs">IRC</a>, open an issue or a create a pull request if you feel something can be improved. For help on how to write source code documentation see [JSDoc](http://usejsdoc.org) and [markdox](https://github.com/cbou/markdox)_
_This documentation was automagically created on <?= new Date().toString() ?>_
<? }) ?>
\ No newline at end of file
......@@ -32,7 +32,8 @@ module.exports = (function() {
self.instance[instancePrimaryKey]
),
new Utils.where(
through.rawAttributes[self.association.foreignIdentifier], {
through.rawAttributes[self.association.foreignIdentifier],
{
join: new Utils.literal([
self.QueryInterface.quoteTable(self.association.target.name),
self.QueryInterface.quoteIdentifier(foreignPrimaryKey)
......
......@@ -3,9 +3,83 @@ var Utils = require("./../utils")
, HasMany = require("./has-many")
, BelongsTo = require("./belongs-to")
/* Defines Mixin for all models. */
/**
* Creating assocations in sequelize is done by calling one of the belongsTo / hasOne / hasMany functions
* on a model (the source), and prodiving another model as the first argument to the function (the target).
*
* * hasOne - adds a foreign key to target
* * belongsTo - add a foreign key to source
* * hasMany - adds a foreign key to target, unless you also specifiy that target hasMany source, in which case a junction table is created with sourceId and targetId
*
* Creating an association will add a foreign key constraint to the attributes. All associations use `CASCADE` on update and `SET NULL` on delete, except for n:m, which also uses `CASCADE` on delete.
*
* When creating associations, you can provide an alias, via the `as` option. This is usefull if the same model
* is associated twice, or you want your association to be called something other than the name of the target model.
* As an example, consider the case where users have many pictures, one of which is their profile picture. All pictures
* have a `userId`, but in addition the user model also has a `profilePictureId`, to be able to easily load the user's profile
* picture.
*
* ```js
* User.hasMany(Picture)
* User.belongsTo(Picture, { as: 'ProfilePicture', constraints: false })
*
* user.getPictures() // gets you all pictures
* user.getProfilePicture() // gets you only the profile picture
*
* User.findAll({
* where: ...,
* include: [
* { model: Picture }, // load all pictures
* { model: Picture, as: 'ProfilePicture' }, // load the profile picture. Notice that the spelling must be the exact same as the one in the association
* ]
* })
* ```
*
* When getting associated models, you can limit your query to only load some models. These queries are written in the same way as queries to `find`/`findAll`. To only get pictures in JPG, you can do:
*
* ```js
* user.getPictures({
* where: {
* format: 'jpg'
* }
* })
* ```
*
* In the above we specify that a user belongs to his profile picture. Conceptually, this might not make sense,
* but since we want to add the foreign key to the user model this is the way to do it.
* Note how we also specified `constraints: false` for profile picture. This is because we add a foreign key from
* user to picture (profilePictureId), and from picture to user (userId). If we were to add foreign keys to both, it would
* create a cyclic dependency, and sequelize would not know which table to create first, since user depends on picture, and picture
* depends on user. These kinds of problems are detected by sequelize before the models are synced to the database, and you will
* get an error along the lines of `Error: Cyclic dependency found. 'users' is dependent of itself`. If you encounter this,
* you should either disable some constraints, or rethink your associations completely.
*
* @mixin Associations
*/
var Mixin = module.exports = function(){}
/**
* Creates an association between this (the source) and the provided target. The foreign key is added on the target.
*
* Example: `User.hasOne(Profile)`. This will add userId to the profile table.
*
* The following methods are injected on the source:
*
* * get[AS] - for example getProfile()
* * set[AS] - for example setProfile(instance, options). Options are passed to `target.save`
* * create[AS] - for example createProfile(value, options). Builds and saves a new instance of the associated model. Values and options are passed on to `target.create`
*
* All methods return an event emitter.
*
* @param {DAOFactory} target
* @param {object} [options]
* @param {boolean} [options.hooks=false] Set to true to run before-/afterDestroy hooks when an associated model is deleted because of a cascade. For example if `User.hasOne(Profile, {onDelete: 'cascade', hooks:true})`, the before-/afterDestroy hooks for profile will be called when a user is deleted. Otherwise the profile will be deleted without invoking any hooks
* @param {string} [options.as] The alias of this model. If you create multiple associations between the same tables, you should provide an alias to be able to distinguish between them. If you provide an alias when creating the assocition, you should provide the same alias when eager loading and when getting assocated models. Defaults to the singularized version of target.name
* @param {string} [options.foreignKey] The name of the foreign key in the target table. Defaults to the name of source + primary key of source
* @param {string} [options.onDelete='SET&nbsp;NULL']
* @param {string} [options.onUpdate='CASCADE']
* @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key.
*/
Mixin.hasOne = function(associatedDAOFactory, options) {
// Since this is a mixin, we'll need a unique variable name for hooks (since DAOFactory will override our hooks option)
options = options || {}
......@@ -23,6 +97,28 @@ Mixin.hasOne = function(associatedDAOFactory, options) {
return this
}
/**
* Creates an association between this (the source) and the provided target. The foreign key is added on the source.
*
* Example: `Profile.belongsTo(User)`. This will add userId to the profile table.
*
* The following methods are injected on the source:
*
* * get[AS] - for example getUser()
* * set[AS] - for example setUser(instance, options). Options are passed to this.save
* * create[AS] - for example createUser(value, options). Builds and saves a new instance of the associated model. Values and options are passed on to target.create
*
* All methods return an event emitter.
*
* @param {DAOFactory} target
* @param {object} [options]
* @param {boolean} [options.hooks=false] Set to true to run before-/afterDestroy hooks when an associated model is deleted because of a cascade. For example if `User.hasOne(Profile, {onDelete: 'cascade', hooks:true})`, the before-/afterDestroy hooks for profile will be called when a user is deleted. Otherwise the profile will be deleted without invoking any hooks
* @param {string} [options.as] The alias of this model. If you create multiple associations between the same tables, you should provide an alias to be able to distinguish between them. If you provide an alias when creating the assocition, you should provide the same alias when eager loading and when getting assocated models. Defaults to the singularized version of target.name
* @param {string} [options.foreignKey] The name of the foreign key in the source table. Defaults to the name of target + primary key of target
* @param {string} [options.onDelete='SET&nbsp;NULL']
* @param {string} [options.onUpdate='CASCADE']
* @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key.
*/
Mixin.belongsTo = function(associatedDAOFactory, options) {
// Since this is a mixin, we'll need a unique variable name for hooks (since DAOFactory will override our hooks option)
options = options || {}
......@@ -40,6 +136,73 @@ Mixin.belongsTo = function(associatedDAOFactory, options) {
return this
}
/**
* Create an association that is either 1:m or n:m.
*
* ```js
* // Create a 1:m association between user and project
* User.hasMany(Project)
* ```
* ```js
* // Create a n:m association between user and project
* User.hasMany(Project)
* Project.hasMany(User)
* ```
* By default, the name of the join table will be source+target, so in this case projectsusers. This can be overridden by providing either a string or a DAOFactory as `through` in the options.
* The following methods are injected on the source:
*
* * get[AS] - for example getPictures().
* * set[AS] - for example setPictures(instances, defaultAttributes|options). Update the associations. All currently associated models that are not in instances will be removed.
* * add[AS] - for example addPicture(instance, defaultAttributes|options). Add another association.
* * create[AS] - for example createPicture(values, options). Build and save a new association.
* * remove[AS] - for example removePicture(instance). Remove a single association
* * has[AS] - for example hasPicture(instance). Is source associated to this target?
* * has[AS] [plural] - for example hasPictures(instances). Is source associated to all these targets?
*
* All methods return an event emitter.
*
* If you use a through model with custom attributes, these attributes can be set when adding / setting new associations in two ways. Consider users and projects from before
* with a join table that stores whether the project has been started yet:
* ```js
* var UserProjects = sequelize.define('userprojects', {
* started: Sequelize.BOOLEAN
* })
* User.hasMany(Project, { through: UserProjects })
* Project.hasMany(User, { through: UserProjects })
* ```
* ```js
* jan.addProject(homework, { started: false }) // The homework project is not started yet
* jan.setProjects([makedinner, doshopping], { started: true}) // Both shopping and dinner has been started
* ```
*
* If you want to set several target instances, but with different attributes you have to set the attributes on the instance, using a property with the name of the through model:
*
* ```js
* p1.userprojects {
* started: true
* }
* user.setProjects([p1, p2], {started: false}) // The default value is false, but p1 overrides that.
* ```
*
* Similarily, when fetching through a join table with custom attributes, these attributes will be available as an object with the name of the through model.
* ```js
* user.getProjects().success(function (projects) {
* var p1 = projects[0]
* p1.userprojects.started // Is this project started yet?
* })
* ```
*
* @param {DAOFactory} target
* @param {object} [options]
* @param {boolean} [options.hooks=false] Set to true to run before-/afterDestroy hooks when an associated model is deleted because of a cascade. For example if `User.hasOne(Profile, {onDelete: 'cascade', hooks:true})`, the before-/afterDestroy hooks for profile will be called when a user is deleted. Otherwise the profile will be deleted without invoking any hooks
* @param {DAOFactory|string} [options.through] The name of the table that is used to join source and target in n:m associations. Can also be a sequelize model if you want to define the junction table yourself and add extra attributes to it.
* @param {string} [options.as] The alias of this model. If you create multiple associations between the same tables, you should provide an alias to be able to distinguish between them. If you provide an alias when creating the assocition, you should provide the same alias when eager loading and when getting assocated models. Defaults to the singularized version of target.name
* @param {string} [options.foreignKey] The name of the foreign key in the source table. Defaults to the name of target + primary key of target
* @param {string} [options.onDelete='SET&nbsp;NULL|CASCADE'] Cascade if this is a n:m, and set null if it is a 1:m
* @param {string} [options.onUpdate='CASCADE']
* @param {boolean} [options.constraints=true] Should on update and on delete constraints be enabled on the foreign key.
*/
Mixin.hasMany = function(associatedDAOFactory, options) {
// Since this is a mixin, we'll need a unique variable name for hooks (since DAOFactory will override our hooks option)
options = options || {}
......
......@@ -8,6 +8,13 @@ var Utils = require("./utils")
, QueryTypes = require('./query-types')
module.exports = (function() {
/**
* A DAOFactory represents a table in the database. Sometimes you might also see it refererred to as model, or simply as factory. This class should _not_ be instantiated directly, it is created using `sequelize.define`, and already created models can be loaded using `sequelize.import`
*
* @class DAOFactory
* @mixes Hooks
* @mixes Associations
*/
var DAOFactory = function(name, attributes, options) {
this.options = Utils._.extend({
timestamps: true,
......@@ -60,12 +67,22 @@ module.exports = (function() {
this.scopeObj = {}
}
/**
* Return a hash of the columns defined for this table. Keys are attributes, values are the SQL representation of their type
* @property attributes
* @return {Object}
*/
Object.defineProperty(DAOFactory.prototype, 'attributes', {
get: function() {
return this.QueryGenerator.attributesToSQL(this.rawAttributes)
}
})
/**
* A reference to the sequelize instance
* @property sequelize
* @return {Sequelize}
*/
Object.defineProperty(DAOFactory.prototype, 'sequelize', {
get: function() { return this.daoFactoryManager.sequelize }
})
......@@ -310,6 +327,11 @@ module.exports = (function() {
})
}
/**
* Sync this DAOFactory to the DB, that is create the table. Upon success, the callback will be called with the model instance (this)
* @see {Sequelize#sync} for options
* @return {EventEmitter}
*/
DAOFactory.prototype.sync = function(options) {
options = Utils._.extend({}, this.options, options || {})
......@@ -335,6 +357,12 @@ module.exports = (function() {
}).run()
}
/**
* Drop the table represented by this Model
* @param {Object} [options]
* @param {Boolean} [options.cascade=false] Also drop all objects depending on this table, such as views. Only works in postgres
* @return {EventEmitter}
*/
DAOFactory.prototype.drop = function(options) {
return this.QueryInterface.dropTable(this.getTableName(), options)
}
......@@ -343,6 +371,15 @@ module.exports = (function() {
return this.QueryInterface.dropSchema(schema)
}
/**
* Apply a schema to this model. For postgres, this will actually place the schema in front of the table name - `"schema"."tableName"`,
* while the schema will be prepended to the table name for mysql and sqlite - `'schema.tablename'`.
*
* @param {String} schema The name of the schema
* @param {Object} [options]
* @param {String} [options.schemaDelimiter='.'] The character(s) that separates the schema name from the table name
* @return this
*/
DAOFactory.prototype.schema = function(schema, options) {
this.options.schema = schema
......@@ -359,10 +396,55 @@ module.exports = (function() {
return this
}
/**
* Get the tablename of the model, taking schema into account. The method will return The name as a string if the model has no schema,
* or an object with `tableName`, `schema` and `delimiter` properties.
*
* @return {String|Object}
*/
DAOFactory.prototype.getTableName = function() {
return this.QueryGenerator.addSchema(this)
}
/**
* Apply a scope created in `define` to the model. First let's look at how to create scopes:
* ```js
* var Model = sequelize.define('model', attributes, {
* defaultScope: {
* where: {
* username: 'dan'
* },
* limit: 12
* },
* scopes: {
* isALie: {
* where: {
* stuff: 'cake'
* }
* },
* complexFunction: function(email, accessLevel) {
* return {
* where: ['email like ? AND access_level >= ?', email + '%', accessLevel]
* }
* },
* }
* })
* ```
* Now, since you defined a default scope, every time you do Model.find, the default scope is appended to your query. Here's a couple of examples:
* ```js
* Model.findAll() // WHERE username = 'dan'
* Model.findAll({ where: { age: { gt: 12 } } }) // WHERE age > 12 AND username = 'dan'
* ```
*
* To invoke scope functions you can do:
* ```js
* Model.scope({ method: ['complexFunction' 'dan@sequelize.com', 42]}).findAll()
* // WHERE email like 'dan@sequelize.com%' AND access_level >= 42
* ```
*
* @param {Array|Object|String|null} options* The scope(s) to apply. Scopes can either be passed as consecutive arguments, or as an array of arguments. To apply simple scopes, pass them as strings. For scope function, pass an object, with a `method` property. The value can either be a string, if the method does not take any arguments, or an array, where the first element is the name of the method, and consecutive elements are arguments to that method. Pass null to remove all scopes, including the default.
* @return {DAOFactory} A reference to the model, with the scope(s) applied. Calling scope again on the returned model will clear the previous scope.
*/
DAOFactory.prototype.scope = function(option) {
var self = Object.create(this)
, type
......@@ -445,11 +527,83 @@ module.exports = (function() {
return self
}
// alias for findAll
DAOFactory.prototype.all = function(options, queryOptions) {
return this.findAll(options, queryOptions)
}
/**
* Search for multiple instances.
*
* __Simple search using AND and =__
* ```js
* Model.find({
* where: {
* attr1: 42,
* attr2: 'cake'
* }
* })
* ```
* ```sql
* WHERE attr1 = 42 AND attr2 = 'cake'
*```
*
* __Using greater than, less than etc.__
* ```js
*
* Model.find({
* where: {
* attr1: {
* gt: 50
* },
* attr2: {
* lte: 45
* },
* attr3: {
* in: [1,2,3]
* },
* attr4: {
* ne: 5
* }
* }
* })
* ```
* ```sql
* WHERE attr1 > 50 AND attr2 <= 45 AND attr3 IN (1,2,3) AND attr4 != 5
* ```
* Possible options are: `gt, gte, lt, lte, ne, between/.., nbetween/notbetween/!.., in, not, like, nlike/notlike`
*
* __Queries using OR__
* ```js
* Model.find({
* where: Sequelize.and(
* { name: 'a project' },
* Sequelize.or(
* { id: [1,2,3] },
* { id: { gt: 10 } }
* )
* )
* })
* ```
* ```sql
* WHERE name = 'a project' AND (id` IN (1,2,3) OR id > 10)
* ```
*
* The success listener is called with an array of instances if the query succeeds.
*
* @param {Object} [options] A hash of options to describe the scope of the search
* @param {Object} [options.where] A hash of attributes to describe your search. See above for examples.
* @param {Array<String>} [options.attributes] A list of the attributes that you want to select
* @param {Array<Object|DAOFactory>} [options.include] A list of associations to eagerly load. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { model: DaoFactory1, as: 'Alias' } ] }. If your association are set up with an `as` (eg. `X.hasMany(Y, { as: 'Z }`, you need to specify Z in the as attribute when eager loading Y). When using the object form, you can also specify `attributes` to specify what columns to load, `where` to limit the relations, and `include` to load further nested relations
* @param {String|Array|Sequelize.fn} [options.order] Specifies an ordering. If a string is provided, it will be esacped. Using an array, you can provide several columns / functions to order by. Each element can be further wrapped in a two-element array. The first element is the column / function to order by, the second is the direction. For example: `order: [['name', 'DESC']]`. In this way the column will be escaped, but the direction will not.
* @param {Number} [options.limit]
* @param {Number} [options.offset]
* @param {Object} [queryOptions] Set the query options, e.g. raw, specifying that you want raw data instead of built DAOs. See sequelize.query for options
* @param {Transaction} [queryOptions.transaction]
*
* @see {Sequelize#query}
* @return {EventEmitter}
* @alias all
*/
DAOFactory.prototype.findAll = function(options, queryOptions) {
var hasJoin = false
, tableNames = { }
......@@ -497,12 +651,13 @@ module.exports = (function() {
}
/**
* Search for an instance.
* Search for a single instance. This applies LIMIT 1, so the listener will always be called with a single instance.
*
* @param {Object} options Options to describe the scope of the search.
* @param {Array} include A list of associations which shall get eagerly loaded. Supported is either { include: [ DaoFactory1, DaoFactory2, ...] } or { include: [ { daoFactory: DaoFactory1, as: 'Alias' } ] }.
* @param {Object} set the query options, e.g. raw, specifying that you want raw data instead of built DAOs
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object|Number} [options] A hash of options to describe the scope of the search, or a number to search by id.
* @param {Object} [queryOptions]
*
* @see {DAOFactory#findAll} for an explanation of options and queryOptions
* @return {EventEmitter}
*/
DAOFactory.prototype.find = function(options, queryOptions) {
var hasJoin = false
......@@ -587,6 +742,16 @@ module.exports = (function() {
}, queryOptions, { transaction: (options || {}).transaction }))
}
/**
* Run an aggregation method on the specified field
*
* @param {String} field The field to aggregate over. Can be a field name or *
* @param {String} aggregateFunction The function to use for aggregation, e.g. sum, max etc.
* @param {Object} [options] Query options. See sequelize.query for full options
* @param {DataType|String} [options.dataType] The type of the result. If field is a field in the DAO, the default will be the type of that field, otherwise defaults to float.
*
* @return {EventEmitter}
*/
DAOFactory.prototype.aggregate = function(field, aggregateFunction, options) {
var tableField;
......@@ -635,6 +800,25 @@ module.exports = (function() {
}.bind(this)).run()
}
/**
* Find all the rows matching your query, within a specified offset / limit, and get the total number of rows matching your query. This is very usefull for paging
*
* ```js
* Model.findAndCountAll({
* where: ...,
* limit: 12,
* offset: 12
* }).success(function (result) {
* })
* ```
* In the above example, `result.rows` will contain rows 13 through 24, while `result.count` will return the total number of rows that matched your query.
*
* @param {Object} [findOptions] See findAll
* @param {Object} [queryOptions] See Sequelize.query
*
* @see {DAOFactory#findAll} for a specification of find and query options
* @return {EventEmitter}
*/
DAOFactory.prototype.findAndCountAll = function(findOptions, queryOptions) {
var self = this
// no limit, offset, order, attributes for the options given to count()
......@@ -667,18 +851,57 @@ module.exports = (function() {
}).run()
}
/**
* Find the maximum value of field
*
* @param {String} field
* @param {Object} [options] See aggregate
* @see {DAOFactory#aggregate} for options
*
* @return {EventEmitter}
*/
DAOFactory.prototype.max = function(field, options) {
return this.aggregate(field, 'max', options)
}
/**
* Find the minimum value of field
*
* @param {String} field
* @param {Object} [options] See aggregate
* @see {DAOFactory#aggregate} for options
*
* @return {EventEmitter}
*/
DAOFactory.prototype.min = function(field, options) {
return this.aggregate(field, 'min', options)
}
/**
* Find the sum of field
*
* @param {String} field
* @param {Object} [options] See aggregate
* @see {DAOFactory#aggregate} for options
*
* @return {EventEmitter}
*/
DAOFactory.prototype.sum = function(field, options) {
return this.aggregate(field, 'sum', options)
}
/**
* Builds a new model instance. Values is an object of key value pairs, must be defined but can be empty.
* @param {Object} values
* @param {Object} [options]
* @param {Boolean} [options.raw=false] If set to true, values will ignore field and virtual setters.
* @param {Boolean} [options.isNewRecord=true]
* @param {Boolean} [options.isDirty=true]
* @param {Array} [options.include] an array of include options - Used to build prefetched/included model instances. See `set`
*
* @return {DAO}
*/
DAOFactory.prototype.build = function(values, options) {
if (Array.isArray(values)) {
return this.bulkBuild(values, options)
......@@ -698,6 +921,7 @@ module.exports = (function() {
return new this.DAO(values, options)
}
DAOFactory.prototype.bulkBuild = function(valueSets, options) {
options = options || { isNewRecord: true, isDirty: true }
......@@ -716,6 +940,23 @@ module.exports = (function() {
}.bind(this))
}
/**
* Builds a new model instance and calls save on it.
* @see {DAO#build}
* @see {DAO#save}
*
* @param {Object} values
* @param {Object} [options]
* @param {Boolean} [options.raw=false] If set to true, values will ignore field and virtual setters.
* @param {Boolean} [options.isNewRecord=true]
* @param {Boolean} [options.isDirty=true]
* @param {Array} [options.fields] If set, only columns matching those in fields will be saved
* @param {Array} [options.include] an array of include options - Used to build prefetched/included model instances
* @param {Transaction} [options.transaction]
*
* @return {EventEmitter}
*/
DAOFactory.prototype.create = function(values, options) {
Utils.validateParameter(values, Object, { optional: true })
Utils.validateParameter(options, Object, { deprecated: Array, optional: true, index: 2, method: 'DAOFactory#create' })
......@@ -734,6 +975,17 @@ module.exports = (function() {
}).save(options)
}
/**
* Find a row that matches the query, or build (but don't save) the row if none is found.
*
* @param {Object} where A hash of search attributes. Note that this method differs from finders, in that the syntax is `{ attr1: 42 }` and NOT `{ where: { attr1: 42}}`. This may be subject to change in 2.0
* @param {Object} [defaults] Default values to use if building a new instance
* @param {Object} [options] Options passed to the find call
* @deprecated The syntax is due for change, in order to make `where` more consistent with the rest of the API
*
* @return {EventEmitter}
* @alias findOrBuild
*/
DAOFactory.prototype.findOrInitialize = DAOFactory.prototype.findOrBuild = function (params, defaults, options) {
defaults = defaults || {}
options = options || {}
......@@ -775,6 +1027,16 @@ module.exports = (function() {
}).run()
}
/**
* Find a row that matches the query, or build and save the row if none is found
*
* @param {Object} where A hash of search attributes. Note that this method differs from finders, in that the syntax is `{ attr1: 42 }` and NOT `{ where: { attr1: 42}}`. This is subject to change in 2.0
* @param {Object} [defaults] Default values to use if creating a new instance
* @param {Object} [options] Options passed to the find and create calls
* @deprecated The syntax is due for change, in order to make `where` more consistent with the rest of the API
*
* @return {EventEmitter}
*/
DAOFactory.prototype.findOrCreate = function (where, defaults, options) {
var self = this
, values = {}
......@@ -818,19 +1080,20 @@ module.exports = (function() {
}
/**
* Create and insert multiple instances
* Create and insert multiple instances in bulk.
*
* The success handler is not passed any arguments. To obtain DAOs for the newly created values, you will need to query for them again.
* This is because MySQL and SQLite do not make it easy to obtain back automatically generated IDs and other default values in a way that can be mapped to multiple records.
*
* @param {Array} records List of objects (key/value pairs) to create instances from
* @param {Array} fields Fields to insert (defaults to all fields)
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object} [options]
* @param {Array} [options.fields] Fields to insert (defaults to all fields)
* @param {Boolean} [options.validate=false] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation
* @param {Boolean} [options.hooks=false] Run before / after bulkCreate hooks?
* @param {Boolean} [options.ignoreDuplicates=false] Ignore duplicate values for primary keys? (not supported by postgres)
*
* Note: the `success` handler is not passed any arguments. To obtain DAOs for
* the newly created values, you will need to query for them again. This is
* because MySQL and SQLite do not make it easy to obtain back automatically
* generated IDs and other default values in a way that can be mapped to
* multiple records
* @return {EventEmitter}
*/
DAOFactory.prototype.bulkCreate = function(records, fieldsOrOptions, options) {
Utils.validateParameter(fieldsOrOptions, Object, { deprecated: Array, optional: true, index: 2, method: 'DAOFactory#bulkCreate' })
Utils.validateParameter(options, 'undefined', { deprecated: Object, optional: true, index: 3, method: 'DAOFactory#bulkCreate' })
......@@ -1009,12 +1272,13 @@ module.exports = (function() {
/**
* Delete multiple instances
*
* @param {Object} where Options to describe the scope of the search.
* @param {Object} options Possible options are:
- hooks: If set to true, destroy will find all records within the where parameter and will execute before/afterDestroy hooks on each row
- limit: How many rows to delete
- truncate: If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is truncated the where and limit options are ignored
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object} [where] Options to describe the scope of the search.
* @param {Object} [options]
* @param {Boolean} [options.hooks] If set to true, destroy will find all records within the where parameter and will execute before-/ after bulkDestroy hooks on each row
* @param {Number} [options.limit] How many rows to delete
* @param {Boolean} [options.truncate] If set to true, dialects that support it will use TRUNCATE instead of DELETE FROM. If a table is truncated the where and limit options are ignored
*
* @return {EventEmitter}
*/
DAOFactory.prototype.destroy = function(where, options) {
options = options || {}
......@@ -1128,11 +1392,16 @@ module.exports = (function() {
}
/**
* Update multiple instances
* Update multiple instances that match the where options.
*
* @param {Object} attrValueHash A hash of fields to change and their new values
* @param {Object} where Options to describe the scope of the search.
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @param {Object where Options to describe the scope of the search. Note that these options are not wrapped in a { where: ... } is in find / findAll calls etc. This is probably due to change in 2.0
* @param {Object} [options]
* @param {Boolean} [options.validate=true] Should each row be subject to validation before it is inserted. The whole insert will fail if one row fails validation
* @param {Boolean} [options.hooks=false] Run before / after bulkUpdate hooks?
* @deprecated The syntax is due for change, in order to make `where` more consistent with the rest of the API
*
* @return {EventEmitter}
*/
DAOFactory.prototype.update = function(attrValueHash, where, options) {
var self = this
......@@ -1265,10 +1534,22 @@ module.exports = (function() {
}).run()
}
/**
* Run a describe query on the table. The result will be return to the listener as a hash of attributes and their types.
*
* @return {EventEmitter}
*/
DAOFactory.prototype.describe = function(schema) {
return this.QueryInterface.describeTable(this.tableName, schema || this.options.schema || undefined)
}
/**
* A proxy to the node-sql query builder, which allows you to build your query through a chain of method calls.
* The returned instance already has all the fields property populated with the field of the model.
*
* @see https://github.com/brianc/node-sql
* @return {node-sql} A node-sql instance
*/
DAOFactory.prototype.dataset = function() {
if (!this.__sql) {
this.__setSqlDialect()
......
......@@ -90,8 +90,8 @@ function extendModelValidations(modelInstance){
/**
* The Main DAO Validator.
*
* @param {sequelize.Model} modelInstance The model instance.
* @param {Object=} options A dict with options.
* @param {DAO} modelInstance The model instance.
* @param {Object} options A dict with options.
* @constructor
*/
var DaoValidator = module.exports = function(modelInstance, options) {
......@@ -106,7 +106,7 @@ var DaoValidator = module.exports = function(modelInstance, options) {
this.chainer = new Utils.QueryChainer()
/**
* Expose validator.js to allow users to extend
* Exposes a reference to validator.js. This allows you to add custom validations using `Validator.extend`
* @name Validator
*/
this.Validator = Validator
......@@ -131,7 +131,7 @@ DaoValidator.RAW_KEY_NAME = '__raw'
/**
* The main entry point for the Validation module, invoke to start the dance.
*
* @return {sequelize.Utils.CustomEventEmitter} That thing...
* @return {EventEmitter}
*/
DaoValidator.prototype.validate = function() {
if (this.inProgress) {
......@@ -161,7 +161,7 @@ DaoValidator.prototype.validate = function() {
* - Validation
* - After Validation Model Hooks
*
* @return {sequelize.Utils.CustomEventEmitter} An eventemitter.
* @return {EventEmitter}
*/
DaoValidator.prototype.hookValidate = function() {
var self = this
......
......@@ -7,18 +7,57 @@ var Utils = require("./utils")
module.exports = (function() {
/**
* This class represents an single instance, a database row. You might see it referred to as both DAO and instance. You should not
* instantiate the DAO class directly, instead you access it using the finder and creation methods on the model.
*
* DAO instances operate with the concept of a `dataValues` property, which stores the actual values represented by the instance.
* By default, the values from dataValues can also be accessed directly from the DAO, that is:
* ```js
* instance.field
* // is the same as
* instance.get('field')
* // is the same as
* instance.getDataValue('field')
* ```
* However, if getters and/or setters are defined for `field` they will be invoked, instead of returning the value from `dataValues`.
* Accessing properties directly or using `get` is preferred for regular use, `getDataValue` should only be used for custom getters.
*
* @see {Sequelize#define} for more information about getters and setters
* @class DAO
*/
var DAO = function(values, options) {
this.dataValues = {}
this._previousDataValues = {}
this.__options = this.Model.options
this.options = options
this.hasPrimaryKeys = this.Model.options.hasPrimaryKeys
this.__eagerlyLoadedAssociations = []
/**
* Returns true if this instance has not yet been persisted to the database
* @property isNewRecord
* @return {Boolean}
*/
this.isNewRecord = options.isNewRecord
/**
* Returns the Model the instance was created from.
* @see {DAOFactory}
* @property Model
* @return DAOFactory
*/
initValues.call(this, values, options);
}
Utils._.extend(DAO.prototype, Mixin.prototype)
/**
* A reference to the sequelize instance
* @see {Sequelize}
* @property sequelize
* @return {Sequelize}
*/
Object.defineProperty(DAO.prototype, 'sequelize', {
get: function(){ return this.Model.daoFactoryManager.sequelize }
})
......@@ -27,24 +66,48 @@ module.exports = (function() {
get: function(){ return this.sequelize.getQueryInterface() }
})
/**
* If timestamps and paranoid are enabled, returns whether the deletedAt timestamp of this instance is set. Otherwise, always returns false.
* @property isDeleted
* @return {Boolean}
*/
Object.defineProperty(DAO.prototype, 'isDeleted', {
get: function() {
return this.Model._timestampAttributes.deletedAt && this.dataValues[this.Model._timestampAttributes.deletedAt] !== null
}
})
/**
* Get the values of this DAO. Proxies to `this.get`
* @see {DAO#get}
* @property values
* @return {Object}
*/
Object.defineProperty(DAO.prototype, 'values', {
get: function() {
return this.get()
}
})
/**
* A getter for `this.changed()`. Returns true if any keys have changed.
*
* @see {DAO#changed}
* @property isDirty
* @return {Boolean}
*/
Object.defineProperty(DAO.prototype, 'isDirty', {
get: function() {
return !!this.changed()
}
})
/**
* Get the values of the primary keys of this instance.
*
* @property primaryKeyValues
* @return {Object}
*/
Object.defineProperty(DAO.prototype, 'primaryKeyValues', {
get: function() {
var result = {}
......@@ -71,13 +134,34 @@ module.exports = (function() {
}
})
/**
* Get the value of the underlying data value
*
* @param {String} key
* @return {any}
*/
DAO.prototype.getDataValue = function(key) {
return this.dataValues[key]
}
/**
* Update the underlying data value
*
* @param {String} key
* @param {any} value
*/
DAO.prototype.setDataValue = function(key, value) {
this.dataValues[key] = value
}
/**
* If no key is given, returns all values of the instance, also invoking virtual getters.
*
* If key is given and a field or virtual getter is present for the key it will call that getter - else it will return the value for key.
*
* @param {String} [key]
* @return {Object|any}
*/
DAO.prototype.get = function (key) {
if (key) {
if (this._customGetters[key]) {
......@@ -105,6 +189,28 @@ module.exports = (function() {
}
return this.dataValues
}
/**
* Set is used to update values on the instance (the sequelize representation of the instance that is, remember that nothing will be persisted before you actually call `save`).
* In its most basic form `set` will update a value stored in the underlying `dataValues` object. However, if a custom setter function is defined for the key, that function
* will be called instead. To bypass the setter, you can pass `raw: true` in the options object.
*
* If set is called with an object, it will loop over the object, and call set recursively for each key, value pair. If you set raw to true, the underlying dataValues will either be
* set directly to the object passed, or used to extend dataValues, if dataValues already contain values.
*
* When set is called, the previous value of the field is stored, so that you can later see which fields changed (see `changed`).
*
* Set can also be used to build instances for associations, if you have values for those. TODO - mick should probably write something here about how includes in set works - perhaps also even some tests?
*
* @see {DAOFactory#find} for more information about includes
* @param {String|Object} key
* @param {any} value
* @param {Object} [options]
* @param {Boolean} [options.raw=false] If set to true, field and virtual setters will be ignored
* @param {Boolean} [options.reset=false] Clear all previously set data values
* @param {Object} [options.include]
* @alias setAttributes
*/
DAO.prototype.set = function (key, value, options) {
var values
, originalValue
......@@ -212,6 +318,14 @@ module.exports = (function() {
return this;
}
/**
* If changed is called with a string it will return a boolean indicating whether the value of that key in `dataValues` is different from the value in `_previousDataValues`.
*
* If changed is called without an argument, it will return an array of keys that have changed.
*
* @param {String} [key]
* @return {Boolean|Array}
*/
DAO.prototype.changed = function(key) {
if (key) {
if (this.Model._isDateAttribute(key) && this._previousDataValues[key] && this.dataValues[key]) {
......@@ -226,6 +340,11 @@ module.exports = (function() {
return changed.length ? changed : false
}
/**
* Returns the previous value for key from `_previousDataValues`.
* @param {String} key
* @return {Boolean}
*/
DAO.prototype.previous = function(key) {
return this._previousDataValues[key]
}
......@@ -270,8 +389,19 @@ module.exports = (function() {
}
};
// if an array with field names is passed to save()
// only those fields will be updated
/**
* Validate this instance, and if the validation passes, persist it to the database.
*
* On success, the callback will be called with this instance. On validation error, the callback will be called with an instance of `Sequelize.ValidationError`.
* This error will have a property for each of the fields for which validation failed, with the error message for that field.
*
* @param {Array} [fields] An optional array of strings, representing database columns. If fields is provided, only those columns will be validation and saved.
* @param {Object} [options]
* @param {Object} [options.fields] An alternative way of setting which fields should be persisted
* @param {Transaction} [options.transaction]
*
* @return {EventEmitter}
*/
DAO.prototype.save = function(fieldsOrOptions, options) {
if (fieldsOrOptions instanceof Array) {
fieldsOrOptions = { fields: fieldsOrOptions }
......@@ -438,10 +568,12 @@ module.exports = (function() {
/*
* Refresh the current instance in-place, i.e. update the object with current data from the DB and return the same object.
* This is different from doing a `find(DAO.id)`, because that would create and return a new object. With this method,
* This is different from doing a `find(DAO.id)`, because that would create and return a new instance. With this method,
* all references to the DAO are updated with the new data and no new objects are created.
*
* @return {Object} A promise which fires `success`, `error`, `complete` and `sql`.
* @see {DAOFactory#find}
* @param {Object} [options] Options that are passed on to `DAOFactory.find`
* @return {EventEmitter}
*/
DAO.prototype.reload = function(options) {
var where = [
......@@ -466,25 +598,36 @@ module.exports = (function() {
}
/*
* Validate this dao's attribute values according to validation rules set in the dao definition.
* Validate the attribute of this instance according to validation rules set in the model definition.
*
* Emits null if and only if validation successful; otherwise an Error instance containing { field name : [error msgs] } entries.
*
* @param {Object} [options] Options that are passed to the validator
* @param {Array} [options.skip] An array of strings. All properties that are in this array will not be validated
* @see {DAOValidator}
*
* @return null if and only if validation successful; otherwise an object containing { field name : [error msgs] } entries.
* @return {EventEmitter}
*/
DAO.prototype.validate = function(options) {
return new DaoValidator(this, options).validate()
}
/*
* Validate this dao's attribute values according to validation rules set in the dao definition.
*
* @return CustomEventEmitter with null if validation successful; otherwise an object containing { field name : [error msgs] } entries.
*/
DAO.prototype.hookValidate = function(object) {
var validator = new DaoValidator(this, object)
return validator.hookValidate()
}
/**
* This is the same as calling `setAttributes`, then calling `save`.
*
* @see {DAO#setAttributes}
* @see {DAO#save}
* @param {Object} updates See `setAttributes`
* @param {Object} options See `save`
*
* @return {EventEmitter}
*/
DAO.prototype.updateAttributes = function(updates, options) {
if (options instanceof Array) {
options = { fields: options }
......@@ -498,6 +641,14 @@ module.exports = (function() {
return this.set(updates)
}
/**
* Destroy the row corresponding to this instance. Depending on your setting for paranoid, the row will either be completely deleted, or have its deletedAt timestamp set to the current time.
*
* @param {Object} [options={}]
* @param {Boolean} [options.force=false] If set to true, paranoid models will actually be deleted
*
* @return {EventEmitter}
*/
DAO.prototype.destroy = function(options) {
options = options || {}
options.force = options.force === undefined ? false : Boolean(options.force)
......@@ -538,6 +689,28 @@ module.exports = (function() {
}).run()
}
/**
* Increment the value of one or more columns. This is done in the database, which means it does not use the values currently stored on the DAO. The increment is done using a
* ```sql
* SET column = column + X
* ```
* query. To get the correct value after an increment into the DAO you should do a reload.
*
*```js
* instance.increment('number') // increment number by 1
* instance.increment(['number', 'count'], { by: 2 }) // increment number and count by 2
* instance.increment({ answer: 42, tries: 1}, { by: 2 }) // increment answer by 42, and tries by 1.
* // `by` is ignored, since each column has its own value
* ```
*
* @see {DAO#reload}
* @param {String|Array|Object} fields If a string is provided, that column is incremented by the value of `by` given in options. If an array is provided, the same is true for each column. If and object is provided, each column is incremented by the value given
* @param {Object} [options]
* @param {Integer} [options.by=1] The number to increment by
* @param {Transaction} [options.transaction=null]
*
* @return {EventEmitter}
*/
DAO.prototype.increment = function(fields, countOrOptions) {
Utils.validateParameter(countOrOptions, Object, {
optional: true,
......@@ -581,6 +754,28 @@ module.exports = (function() {
return this.QueryInterface.increment(this, this.QueryInterface.QueryGenerator.addSchema(this.Model.tableName, this.Model.options.schema), values, where, countOrOptions)
}
/**
* Decrement the value of one or more columns. This is done in the database, which means it does not use the values currently stored on the DAO. The decrement is done using a
* ```sql
* SET column = column - X
* ```
* query. To get the correct value after an decrement into the DAO you should do a reload.
*
* ```js
* instance.decrement('number') // decrement number by 1
* instance.decrement(['number', 'count'], { by: 2 }) // decrement number and count by 2
* instance.decrement({ answer: 42, tries: 1}, { by: 2 }) // decrement answer by 42, and tries by 1.
* // `by` is ignored, since each column has its own value
* ```
*
* @see {DAO#reload}
* @param {String|Array|Object} fields If a string is provided, that column is decremented by the value of `by` given in options. If an array is provided, the same is true for each column. If and object is provided, each column is decremented by the value given
* @param {Object} [options]
* @param {Integer} [options.by=1] The number to decrement by
* @param {Transaction} [options.transaction=null]
*
* @return {EventEmitter}
*/
DAO.prototype.decrement = function (fields, countOrOptions) {
Utils.validateParameter(countOrOptions, Object, {
optional: true,
......@@ -609,6 +804,12 @@ module.exports = (function() {
return this.increment(fields, countOrOptions)
}
/**
* Check whether all values of this and `other` DAO are the same
*
* @param {DAO} other
* @return {Boolean}
*/
DAO.prototype.equals = function(other) {
var result = true
......@@ -623,19 +824,30 @@ module.exports = (function() {
return result
}
/**
* Check if this is eqaul to one of `others` by calling equals
*
* @param {Array} others
* @return {Boolean}
*/
DAO.prototype.equalsOneOf = function(others) {
var result = false
, self = this
others.forEach(function(other) { result = result || self.equals(other) })
var self = this
return result
return _.any(others, function (other) {
return self.equals(other)
})
}
DAO.prototype.setValidators = function(attribute, validators) {
this.validators[attribute] = validators
}
/**
* Convert the instance to a JSON representation. Proxies to calling `get` with no keys. This means get all values gotten from the DB, and apply all custom getters.
*
* @see {DAO#get}
* @return {object}
*/
DAO.prototype.toJSON = function() {
return this.get();
}
......
......@@ -12,12 +12,53 @@ var bindToProcess = function(fct) {
return fct
}
/**
* The EventEmitter is returned from all asynchronous Sequelize calls - So almost all of them.
* The emitter provides a lovely mix of native node.js `EventEmitter` and promise methods.
*
* There are several different syntaxes for attaching listeners to the emitter:
*
* ```js
* Model.find(...).on('success', function (dao) {
* // Using it as a regular node emitter
* })
*
* Model.find(...).success(function (dao) {
* // Using the shortcut methods
* })
*
* Model.find(...).done(function (err, dao) {
* // Using the done method, which is called both if the operation succeeds,
* // and if it fails. On success, the err argument will be null
* })
*
* Model.find(...).then(function (dao) {
* // Using the emitter as a promise. The first function is the success handler,
* // and the second is the error handler.
* }, function (err) {
*
* })
* ```
*
* @mixes http://nodejs.org/api/events.html#events_class_events_eventemitter
* @class EventEmitter
*/
module.exports = (function() {
/**
* Create a new emitter instance.
*
* @constructor CustomEventEmitter
* @param {function} fct A function that this emitter should run. The function is called with the emitter as first argument and as context
*/
var CustomEventEmitter = function(fct) {
this.fct = bindToProcess(fct)
}
util.inherits(CustomEventEmitter, EventEmitter)
/**
* Run the function that was passed when the emitter was instantiated.
* @return this
*/
CustomEventEmitter.prototype.run = function() {
Utils.tick(function() {
if (this.fct) {
......@@ -28,6 +69,11 @@ module.exports = (function() {
return this
}
/**
* Emit an event from the emitter
* @param {string} type The type of event
* @param {any} value(s)* All other arguments will be passed to the event listeners
*/
CustomEventEmitter.prototype.emit = function(type) {
this._events = this._events || {};
......@@ -62,13 +108,18 @@ module.exports = (function() {
};
/**
Shortcut methods (success, ok) for listening for success events.
Params:
- fct: A function that gets executed once the *success* event was triggered.
Result:
The function returns the instance of the query.
* Listen for success events.
*
* ```js
* emitter.success(function (result) {
* //...
* });
* ```
*
* @param {function} onSuccess
* @method success
* @alias ok
* @return this
*/
CustomEventEmitter.prototype.success =
CustomEventEmitter.prototype.ok =
......@@ -78,13 +129,19 @@ module.exports = (function() {
}
/**
Shortcut methods (failure, fail, error) for listening for error events.
Params:
- fct: A function that gets executed once the *error* event was triggered.
Result:
The function returns the instance of the query.
* Listen for error events
*
* ```js
* emitter.error(function (err) {
* //...
* });
* ```
*
* @param {function} onError
* @metohd error
* @alias fail
* @alias failure
* @return this
*/
CustomEventEmitter.prototype.failure =
CustomEventEmitter.prototype.fail =
......@@ -94,6 +151,20 @@ module.exports = (function() {
return this;
}
/**
* Listen for both success and error events.
*
* ```js
* emitter.done(function (err, result) {
* //...
* });
* ```
*
* @param {function} onDone
* @method done
* @alias complete
* @return this
*/
CustomEventEmitter.prototype.done =
CustomEventEmitter.prototype.complete =
function(fct) {
......@@ -107,16 +178,23 @@ module.exports = (function() {
return this
}
/*
* Attach a function that is called every time the function that created this emitter executes a query.
* @param {function} onSQL
* @return this
*/
CustomEventEmitter.prototype.sql = function(fct) {
this.on('sql', bindToProcess(fct))
return this;
}
/**
* Proxy every event of this custom event emitter to another one.
* Proxy every event of this event emitter to another one.
*
* @param {CustomEventEmitter} emitter The event emitter that should receive the events.
* @return {void}
* @param {EventEmitter} emitter The event emitter that should receive the events.
* @param {Object} [options]
* @param {Array} [options.events] An array of the events to proxy. Defaults to sql, error and success
* @return this
*/
CustomEventEmitter.prototype.proxy = function(emitter, options) {
options = Utils._.extend({
......@@ -136,6 +214,13 @@ module.exports = (function() {
return this
}
/**
* Attach listeners to the emitter, promise style.
*
* @param {Function} onFulfilled The function to call if the promise is fulfilled (if the emitter emits success). Note that this function will always only be called with one argument, as per the promises/A spec. For functions that emit multiple arguments (e.g. findOrCreate) see `spread`
* @param {Function} onRejected
* @return {Bluebird.Promise}
*/
CustomEventEmitter.prototype.then = function(onFulfilled, onRejected) {
var self = this
......@@ -148,6 +233,13 @@ module.exports = (function() {
}).then(onFulfilled, onRejected)
}
/**
* Attach listeners to the emitter, promise style. This listener will recieve all arguments emitted by the emitter, as opposed to `then` which will only recieve the first argument.
*
* @param {Function} onFulfilled The function to call if the promise is fulfilled (if the emitter emits success).
* @param {Function} onRejected
* @return {Bluebird.Promise}
*/
CustomEventEmitter.prototype.spread = function(onFulfilled, onRejected) {
var self = this
......@@ -162,6 +254,12 @@ module.exports = (function() {
}).spread(onFulfilled, onRejected)
}
/**
* Shorthand for `then(null, onRejected)`
*
* @param {Function} onRejected
* @return {Bluebird.Promise}
*/
CustomEventEmitter.prototype.catch = function(onRejected) {
return this.then(null, onRejected)
}
......
var Utils = require("./utils")
/**
* Hooks are function that are called before and after (bulk-) creation/updating/deletion and validation. Hooks can be added to you models in three ways:
*
* 1. By specifying them as options in `sequelize.define`
* 2. By calling `hook()` with a string and your hook handler function
* 3. By calling the function with the same name as the hook you want
* ```js
* // Method 1
* sequelize.define(name, { attributes }, {
* hooks: {
* beforeBulkCreate: function () {
* // can be a single function
* },
* beforeValidate: [
* function () {},
* function() {} // Or an array of several
* ]
* }
* })
*
* // Method 2
* Model.hook('afterDestroy', function () {})
*
* // Method 3
* Model.afterBulkUpdate(function () {})
* ```
*
* @see {Sequelize#define}
* @mixin Hooks
*/
var Hooks = module.exports = function(){}
var hookAliases = {
beforeDelete: "beforeDestroy",
......@@ -65,11 +97,18 @@ Hooks.runHooks = function() {
run(hooks[tick])
}
// Alias for `.addHook`
Hooks.hook = function() {
Hooks.addHook.apply(this, arguments)
}
/**
* Add a hook to the model
*
* @param {String} hooktype
* @param {String} [name] Provide a name for the hook function. This serves no purpose, other than the ability to be able to order hooks based on some sort of priority system in the future.
* @param {Function} fn The hook function
* @alias hook
*/
Hooks.addHook = function(hookType, name, fn) {
if (typeof name === "function") {
fn = name
......@@ -88,26 +127,58 @@ Hooks.addHook = function(hookType, name, fn) {
this.options.hooks[hookType][this.options.hooks[hookType].length] = !!name ? {name: name, fn: method} : method
}
/**
* A hook that is run before validation
* @param {String} name
* @param {Function} fn A callback function that is called with instance, callback(err)
*/
Hooks.beforeValidate = function(name, fn) {
Hooks.addHook.call(this, 'beforeValidate', name, fn)
}
/**
* A hook that is run after validation
* @param {String} name
* @param {Function} fn A callback function that is called with instance, callback(err)
*/
Hooks.afterValidate = function(name, fn) {
Hooks.addHook.call(this, 'afterValidate', name, fn)
}
/**
* A hook that is run before creating a single instance
* @param {String} name
* @param {Function} fn A callback function that is called with attributes, callback(err)
*/
Hooks.beforeCreate = function(name, fn) {
Hooks.addHook.call(this, 'beforeCreate', name, fn)
}
/**
* A hook that is run after creating a single instance
* @param {String} name
* @param {Function} fn A callback function that is called with attributes, callback(err)
*/
Hooks.afterCreate = function(name, fn) {
Hooks.addHook.call(this, 'afterCreate', name, fn)
}
/**
* A hook that is run before destroying a single instance
* @param {String} name
* @param {Function} fn A callback function that is called with instance, callback(err)
* alias beforeDelete
*/
Hooks.beforeDestroy = function(name, fn) {
Hooks.addHook.call(this, 'beforeDestroy', name, fn)
}
/**
* A hook that is run after destroying a single instance
* @param {String} name
* @param {Function} fn A callback function that is called with instance, callback(err)
* @alias afterDelete
*/
Hooks.afterDestroy = function(name, fn) {
Hooks.addHook.call(this, 'afterDestroy', name, fn)
}
......@@ -120,34 +191,74 @@ Hooks.afterDelete = function(name, fn) {
Hooks.addHook.call(this, 'afterDelete', name, fn)
}
/**
* A hook that is run before updating a single instance
* @param {String} name
* @param {Function} fn A callback function that is called with instance, callback(err)
*/
Hooks.beforeUpdate = function(name, fn) {
Hooks.addHook.call(this, 'beforeUpdate', name, fn)
}
/**
* A hook that is run after updating a single instance
* @param {String} name
* @param {Function} fn A callback function that is called with instance, callback(err)
*/
Hooks.afterUpdate = function(name, fn) {
Hooks.addHook.call(this, 'afterUpdate', name, fn)
}
/**
* A hook that is run before creating instances in bulk
* @param {String} name
* @param {Function} fn A callback function that is called with instances, fields, callback(err)
*/
Hooks.beforeBulkCreate = function(name, fn) {
Hooks.addHook.call(this, 'beforeBulkCreate', name, fn)
}
/**
* A hook that is run after creating instances in bulk
* @param {String} name
* @param {Function} fn A callback function that is called with instances, fields, callback(err)
*/
Hooks.afterBulkCreate = function(name, fn) {
Hooks.addHook.call(this, 'afterBulkCreate', name, fn)
}
/**
* A hook that is run before destroing instances in bulk
* @param {String} name
* @param {Function} fn A callback function that is called with where, callback(err)
*/
Hooks.beforeBulkDestroy = function(name, fn) {
Hooks.addHook.call(this, 'beforeBulkDestroy', name, fn)
}
/**
* A hook that is run after destroying instances in bulk
* @param {String} name
* @param {Function} fn A callback function that is called with where, callback(err)
*/
Hooks.afterBulkDestroy = function(name, fn) {
Hooks.addHook.call(this, 'afterBulkDestroy', name, fn)
}
/**
* A hook that is run after updating instances in bulk
* @param {String} name
* @param {Function} fn A callback function that is called with attribute, where, callback(err)
*/
Hooks.beforeBulkUpdate = function(name, fn) {
Hooks.addHook.call(this, 'beforeBulkUpdate', name, fn)
}
/**
* A hook that is run after updating instances in bulk
* @param {String} name
* @param {Function} fn A callback function that is called with attribute, where, callback(err)
*/
Hooks.afterBulkUpdate = function(name, fn) {
Hooks.addHook.call(this, 'afterBulkUpdate', name, fn)
}
var Utils = require(__dirname + "/utils")
module.exports = (function() {
/**
* The sequelize query chainer allows you to run several queries, either in parallel or serially, and attach a callback that is called when all queries are done.
* @class QueryChainer
*/
var QueryChainer = function(emitters) {
var self = this
......@@ -24,6 +28,44 @@ module.exports = (function() {
})
}
/**
* Add an query to the chainer. This can be done in two ways - either by invoking the method like you would normally, and then adding the returned emitter to the chainer, or by passing the
* class that you want to call a method on, the name of the method, and its parameters to the chainer. The second form might sound a bit cumbersome, but it is used when you want to run
* queries in serial.
*
* *Method 1:*
* ```js
* chainer.add(User.findAll({
* where: {
* admin: true
* },
* limit: 3
* }))
* chainer.add(Project.findAll())
* chainer.run().done(function (err, users, project) {
*
* })
* ```
*
* *Method 2:*
* ```js
* chainer.add(User, 'findAll', {
* where: {
* admin: true
* },
* limit: 3
* })
* chainer.add(Project, 'findAll')
* chainer.runSerially().done(function (err, users, project) {
*
* })
* ```
* @param {EventEmitter|Any} emitterOrKlass
* @param {String} [method]
* @param {Object} [params]
* @param {Object} [options]
* @return this
*/
QueryChainer.prototype.add = function(emitterOrKlass, method, params, options) {
if (!!method) {
this.serials.push({ klass: emitterOrKlass, method: method, params: params, options: options })
......@@ -35,6 +77,10 @@ module.exports = (function() {
return this
}
/**
* Run the query chainer. In reality, this means, wait for all the added emtiters to finish, since the queries began executing as soon as you invoked their methods.
* @return {EventEmitter}
*/
QueryChainer.prototype.run = function() {
var self = this
this.eventEmitter = new Utils.CustomEventEmitter(function() {
......@@ -44,6 +90,12 @@ module.exports = (function() {
return this.eventEmitter.run()
}
/**
* Run the chainer serially, so that each query waits for the previous one to finish before it starts.
* @param {Object} [options]
* @param {Object} [options.skipOnError=false] If set to true, all pending emitters will be skipped if a previous emitter failed
* @return {EventEmitter}
*/
QueryChainer.prototype.runSerially = function(options) {
var self = this
, serialCopy = Utils._.clone(this.serials)
......
......@@ -5,6 +5,10 @@ var Utils = require(__dirname + '/utils')
, QueryTypes = require('./query-types')
module.exports = (function() {
/*
* The interface that Sequelize uses to talk to all databases
* @class QueryInterface
**/
var QueryInterface = function(sequelize) {
this.sequelize = sequelize
this.QueryGenerator = require('./dialects/' + this.sequelize.options.dialect + '/query-generator')
......
......@@ -11,45 +11,78 @@ var url = require("url")
, QueryTypes = require('./query-types')
, sequelizeErrors = require('./errors')
/**
* This is the main class, the entry point to sequelize. To use it, you just need to import sequelize:
*
* ```js
* var Sequelize = require('sequelize');
* ```
*
* In addition to sequelize, the connection library for the dialect you want to use should also be installed in your project. You don't need to import it however, as sequelize will take care of that.
*
* @class Sequelize
*/
module.exports = (function() {
/**
* Instantiate sequelize with name of database, username and password
*
* #### Example usage
*
* ```javascript
* // without password and options
* var sequelize = new Sequelize('database', 'username')
*
* // without options
* var sequelize = new Sequelize('database', 'username', 'password')
*
* // without password / with blank password
* var sequelize = new Sequelize('database', 'username', null, {})
*
* // with password and options
* var sequelize = new Sequelize('my_database', 'john', 'doe', {})
*
* // with uri (see below)
* var sequelize = new Sequelize('mysql://localhost:3306/database', {})
* ```
*
* @name Sequelize
* @constructor
*
* @param {String} database The name of the database
* @param {String} [username=null] The username which is used to authenticate against the database.
* @param {String} [password=null] The password which is used to authenticate against the database.
* @param {Object} [options={}] An object with options.
* @param {String} [options.dialect='mysql'] The dialect you of the database you are connecting to. One of mysql, postgres, sqlite and mariadb
* @param {String} [options.dialectModulePath=null] If specified, load the dialect library from this path. For example, if you want to use pg.js instead of pg when connecting to a pg database, you should specify 'pg.js' here
* @param {String} [options.host='localhost'] The host of the relational database.
* @param {Integer} [options.port=] The port of the relational database.
* @param {String} [options.protocol='tcp'] The protocol of the relational database.
* @param {Object} [options.define={}] Default options for model definitions. See sequelize.define for options
* @param {Object} [options.query={}] Default options for sequelize.query
* @param {Object} [options.sync={}] Default options for sequelize.sync
* @param {Function} [options.logging=console.log] A function that gets executed everytime Sequelize would log something.
* @param {Boolean} [options.omitNull=false] A flag that defines if null values should be passed to SQL queries or not.
* @param {Boolean} [options.queue=true] Queue queries, so that only maxConcurrentQueries number of queries are executing at once. If false, all queries will be executed immediately.
* @param {int} [options.maxConcurrentQueries=50] The maximum number of queries that should be executed at once if queue is true.
* @param {Boolean} [options.native=false] A flag that defines if native library shall be used or not. Currently only has an effect for postgres
* @param {Boolean} [options.replication=false] Use read / write replication. To enable replication, pass an object, with two properties, read and write. Write should be an object (a single server for handling writes), and read an array of object (several servers to handle reads). Each read/write server can have the following properties: `host`, `port`, `username`, `password`, `database`
* @param {Object} [options.pool={}] Should sequelize use a connection pool. Default is true
* @param {int} [options.pool.maxConnections]
* @param {int} [options.pool.minConnections]
* @param {int} [options.pool.maxIdleTime] The maximum time, in milliseconds, that a connection can be idle before being released
* @param {function} [options.pool.validateConnection] A function that validates a connection. Called with client. The default function checks that client is an object, and that its state is not disconnected
* @param {Boolean} [options.quoteIdentifiers=true] Set to `false` to make table names and attributes case-insensitive on Postgres and skip double quoting of them.
*/
/**
Main class of the project.
@param {String} database The name of the database.
@param {String} username The username which is used to authenticate against the database.
@param {String} [password=null] The password which is used to authenticate against the database.
@param {Object} [options={}] An object with options.
@param {String} [options.dialect='mysql'] The dialect of the relational database.
@param {String} [options.dialectModulePath=null] If specified, load the dialect library from this path.
@param {String} [options.host='localhost'] The host of the relational database.
@param {Integer} [options.port=] The port of the relational database.
@param {String} [options.protocol='tcp'] The protocol of the relational database.
@param {Object} [options.define={}] Options, which shall be default for every model definition.
@param {Object} [options.query={}] I have absolutely no idea.
@param {Object} [options.sync={}] Options, which shall be default for every `sync` call.
@param {Function} [options.logging=console.log] A function that gets executed everytime Sequelize would log something.
@param {Boolean} [options.omitNull=false] A flag that defines if null values should be passed to SQL queries or not.
@param {Boolean} [options.queue=true] I have absolutely no idea.
@param {Boolean} [options.native=false] A flag that defines if native library shall be used or not.
@param {Boolean} [options.replication=false] I have absolutely no idea.
@param {Object} [options.pool={}] Something.
@param {Boolean} [options.quoteIdentifiers=true] Set to `false` to make table names and attributes case-insensitive on Postgres and skip double quoting of them.
@example
// without password and options
var sequelize = new Sequelize('database', 'username')
// without options
var sequelize = new Sequelize('database', 'username', 'password')
// without password / with blank password
var sequelize = new Sequelize('database', 'username', null, {})
// with password and options
var sequelize = new Sequelize('my_database', 'john', 'doe', {})
@class Sequelize
@constructor
* Instantiate sequlize with an URI
* @name Sequelize
* @constructor
*
* @param {String} uri A full database URI
* @param {object} [options={}] See above for possible options
*/
var Sequelize = function(database, username, password, options) {
var urlParts
......@@ -136,12 +169,19 @@ module.exports = (function() {
}
/**
Reference to Utils
* A reference to sequelize utilities. Most users will not need to use these utils directly. However, you might want to use `Sequelize.Utils._`, which is a reference to the lodash library, if you don't already have it imported in your project.
* @property Utils
* @see {Utils}
*/
Sequelize.Utils = Utils
Sequelize.QueryTypes = QueryTypes
/**
* The class used to validate attributes of an instance before saving. Validations are carried out using validator.js, and you can use `Sequelize.DAOValidator.Validator` to access the validator.js object and extend it with custom validation functions.
* @property DAOValidator
* @see https://github.com/chriso/validator.js
*/
Sequelize.DAOValidator = DAOValidator
Sequelize.DAOFactory = Sequelize.Model = DAOFactory
......@@ -150,9 +190,6 @@ module.exports = (function() {
Sequelize[dataType] = DataTypes[dataType]
}
/**
* Polyfill for the default connector manager.
*/
Object.defineProperty(Sequelize.prototype, 'connectorManager', {
get: function() {
return this.transactionManager.getConnectorManager()
......@@ -160,14 +197,27 @@ module.exports = (function() {
})
/**
* Expose Sequelize Error types
* A reference to the sequelize transaction class. Use this to access isolationLevels when creating a transaction
* @property Transaction
* @see {Transaction}
* @see {Sequelize#transaction}
*/
Sequelize.prototype.Transaction = Transaction
/**
* A general error class
* @property Error
*/
Sequelize.prototype.Error = Sequelize.Error =
sequelizeErrors.BaseError
/**
* Emitted when a validation fails
* @property ValidationError
*/
Sequelize.prototype.ValidationError = Sequelize.ValidationError =
sequelizeErrors.ValidationError
/**
* Returns the specified dialect.
*
......@@ -178,10 +228,12 @@ module.exports = (function() {
}
/**
Returns an instance of QueryInterface.
* Returns an instance of QueryInterface.
@method getQueryInterface
@return {QueryInterface} An instance (singleton) of QueryInterface.
* @method getQueryInterface
* @return {QueryInterface} An instance (singleton) of QueryInterface.
*
* @see {QueryInterface}
*/
Sequelize.prototype.getQueryInterface = function() {
this.queryInterface = this.queryInterface || new QueryInterface(this)
......@@ -189,12 +241,13 @@ module.exports = (function() {
}
/**
Returns an instance (singleton) of Migrator.
@method getMigrator
@param {Object} [options={}] Some options
@param {Boolean} [force=false] A flag that defines if the migrator should get instantiated or not.
@return {Migrator} An instance of Migrator.
* Returns an instance (singleton) of Migrator.
*
* @see {Migrator}
* @function getMigrator
* @param {Object} [options={}] See Migrator for options
* @param {Boolean} [force=false] A flag that defines if the migrator should get instantiated or not.
* @return {Migrator} An instance of Migrator.
*/
Sequelize.prototype.getMigrator = function(options, force) {
var Migrator = require("./migrator")
......@@ -208,6 +261,86 @@ module.exports = (function() {
return this.migrator
}
/**
* Define a new model, representing a table in the DB.
*
* The table columns are define by the hash that is given as the second argument. Each attribute of the hash represents a column. A short table definition might look like this:
*
* ```js
* sequelize.define(..., {
* columnA: {
* type: Sequelize.BOOLEAN,
* validate: {
* is: ["[a-z]",'i'], // will only allow letters
* max: 23, // only allow values <= 23
* isIn: {
* args: [['en', 'zh']],
* msg: "Must be English or Chinese"
* }
* },
* // Other attributes here
* },
* columnB: Sequelize.STRING,
* columnC: 'MY VERY OWN COLUMN TYPE'
* })
* ```
*
* As shown above, column definitions can be either strings, a reference to one of the datatypes that are predefined on the Sequelize constructor, or an object that allows you to specify both the type of the column, and other attributes such as default values, foreign key constraints and custom setters and getters.
*
* For a list of possible data types, see http://sequelizejs.com/docs/latest/models#data-types
*
* For more about getters and setters, see http://sequelizejs.com/docs/latest/models#getters---setters
*
* For more about instance and class methods, see http://sequelizejs.com/docs/latest/models#expansion-of-models
*
* For more about validation, see http://sequelizejs.com/docs/latest/models#validations
*
* @see {DataTypes}
* @see {Hooks}
* @param {String} daoName
* @param {Object} attributes An object, where each attribute is a column of the table. Each column can be either a DataType, a string or a type-description object, with the properties described below:
* @param {String|DataType|Object} attributes.column The description of a database column
* @param {String|DataType} attributes.column.type A string or a data type
* @param {Boolean} [attributes.column.allowNull=true] If false, the column will have a NOT NULL constraint, and a not null validation will be run before an instance is saved.
* @param {Any} [attributes.column.defaultValue=null] A literal default value, a javascript function, or an SQL function (see `sequelize.fn`)
* @param {String|Boolean} [attributes.column.unique=false] If true, the column will get a unique constraint. If a string is provided, the column will be part of a composite unique index. If multiple columns have the same string, they will be part of the same unique index
* @param {Boolean} [attributes.column.primaryKey=false]
* @param {Boolean} [attributes.column.autoIncrement=false]
* @param {String} [attributes.column.comment=null]
* @param {String|DAOFactory} [attributes.column.references] If this column references another table, provide it here as a DAOFactory, or a string
* @param {String} [attributes.column.referencesKey='id'] The column of the foreign table that this column references
* @param {String} [attributes.column.onUpdate] What should happen when the referenced key is updated. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTION
* @param {String} [attributes.column.onDelete] What should happen when the referenced key is deleted. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTION
* @param {Function} [attributes.column.get] Provide a custom getter for this column. Use `this.getDataValue(String)` to manipulate the underlying values.
* @param {Function} [attributes.column.set] Provide a custom setter for this column. Use `this.setDataValue(String, Value)` to manipulate the underlying values.
* @param {Object} [attributes.validate] An object of validations to execute for this column every time the model is saved. Can be either the name of a validation provided by validator.js, a validation function provided by extending validator.js (see the `DAOValidator` property for more details), or a custom validation function. Custom validation functions are called with the value of the field, and can possibly take a second callback argument, to signal that they are asynchronous. If the validator is sync, it should throw in the case of a failed validation, it it is async, the callback should be called with the error text.
* @param {Object} [options] These options are merged with the default define options provided to the Sequelize constructor
* @param {Object} [options.defaultScope] Define the default search scope to use for this model. Scopes have the same form as the options passed to find / findAll
* @param {Object} [options.scopes] More scopes, defined in the same way as defaultScope above. See `DAOFactory.scope` for more information about how scopes are defined, and what you can do with them
* @param {Boolean} [options.omitNull] Don't persits null values. This means that all columns with null values will not be saved
* @param {Boolean} [options.timestamps=true] Adds createdAt and updatedAt timestamps to the model.
* @param {Boolean} [options.paranoid=false] Calling `destroy` will not delete the model, but instead set a `deletedAt` timestamp if this is true. Needs `timestamps=true` to work
* @param {Boolean} [options.underscored=false] Converts all camelCased columns to underscored if true
* @param {Boolean} [options.freezeTableName=false] If freezeTableName is true, sequelize will not try to alter the DAO name to get the table name. Otherwise, the dao name will be pluralized
* @param {String|Boolean} [options.createdAt] Override the name of the createdAt column if a string is provided, or disable it if false. Timestamps must be true
* @param {String|Boolean} [options.updatedAt] Override the name of the updatedAt column if a string is provided, or disable it if false. Timestamps must be true
* @param {String|Boolean} [options.deletedAt] Override the name of the deletedAt column if a string is provided, or disable it if false. Timestamps must be true
* @param {String} [options.tableName] Defaults to pluralized DAO name, unless freezeTableName is true, in which case it uses DAO name verbatim
* @param {Object} [options.getterMethods] Provide getter functions that work like those defined per column. If you provide a getter method with the same name as a column, it will be used to access the value of that column. If you provide a name that does not match a column, this function will act as a virtual getter, that can fetch multiple other values
* @param {Object} [options.setterMethods] Provide setter functions that work like those defined per column. If you provide a setter method with the same name as a column, it will be used to update the value of that column. If you provide a name that does not match a column, this function will act as a virtual setter, that can act on and set other values, but will not be persisted
* @param {Object} [options.instanceMethods] Provide functions that are added to each instance (DAO)
* @param {Object} [options.classMethods] Provide functions that are added to the model (DAOFactory)
* @param {String} [options.schema='public']
* @param {String} [options.engine]
* @param {String} [options.charset]
* @param {String} [options.comment]
* @param {String} [options.collate]
* @param {Object} [options.hooks] An object of hook function that are called before and after certain lifecycle events. The possible hooks are: beforeValidate, afterValidate, beforeBulkCreate, beforeBulkDestroy, beforeBulkUpdate, beforeCreate, beforeDestroy, beforeUpdate, afterCreate, afterDestroy, afterUpdate, afterBulkCreate, afterBulkDestory and afterBulkUpdate. See Hooks for more information about hook functions and their signatures. Each property can either be a function, or an array of functions.
* @param {Object} [options.validate] An object of model wide validations. Validations have access to all model values via `this`. If the validator function takes an argument, it is asumed to be async, and is called with a callback that accepts an optional error.
*
* @return {DaoFactory}
*/
Sequelize.prototype.define = function(daoName, attributes, options) {
options = options || {}
var self = this
......@@ -280,10 +413,11 @@ module.exports = (function() {
}
/**
Fetch a DAO factory
@param {String} daoName The name of a model defined with Sequelize.define
@returns {DAOFactory} The DAOFactory for daoName
* Fetch a DAO factory which is already defined
*
* @param {String} daoName The name of a model defined with Sequelize.define
* @throws Will throw an error if the DAO is not define (that is, if sequelize#isDefined returns false)
* @return {DAOFactory}
*/
Sequelize.prototype.model = function(daoName) {
if(!this.isDefined(daoName)) {
......@@ -293,11 +427,26 @@ module.exports = (function() {
return this.daoFactoryManager.getDAO(daoName)
}
/**
* Checks whether a model with the given name is defined
*
* @param {String} daoName The name of a model defined with Sequelize.define
* @return {Boolean}
*/
Sequelize.prototype.isDefined = function(daoName) {
var daos = this.daoFactoryManager.daos
return (daos.filter(function(dao) { return dao.name === daoName }).length !== 0)
}
/**
* Imports a model defined in another file
*
* Imported models are cached, so multiple calls to import with the same path will not load the file multiple times
*
* See https://github.com/sequelize/sequelize/blob/master/examples/using-multiple-model-files/Task.js for a short example of how to define your models in separate files so that they can be imported by sequelize.import
* @param {String} path The path to the file that holds the model you want to import. If the part is relative, it will be resolved relatively to the calling file
* @return {DAOFactory}
*/
Sequelize.prototype.import = function(path) {
// is it a relative path?
if (Path.normalize(path).indexOf(path.sep) !== 0) {
......@@ -320,6 +469,23 @@ module.exports = (function() {
return this.getMigrator().migrate(options)
}
/**
* Execute a query on the DB, with the posibility to bypass all the sequelize goodness.
*
* If you do not provide other arguments than the SQL, raw will be assumed to the true, and sequelize will not try to do any formatting to the results of the query.
*
* @method query
* @param {String} sql
* @param {DAOFactory} [callee] If callee is provided, the selected data will be used to build an instance of the DAO represented by the factory. Equivalent to calling DAOFactory.build with the values provided by the query.
* @param {Object} [options={}] Query options.
* @param {Boolean} [options.raw] If true, sequelize will not try to format the results of the query, or build an instance of a model from the result
* @param {Transaction} [options.transaction=null] The transaction that the query should be executed under
* @param [String] [options.type='SELECT'] The type of query you are executing. The query type affects how results are formatted before they are passed back. If no type is provided sequelize will try to guess the right type based on the sql, and fall back to SELECT. The type is a string, but `Sequelize.QueryTypes` is provided is convenience shortcuts. Current options are SELECT, BULKUPDATE and BULKDELETE
* @param {Object|Array} [replacements] Either an object of named parameter replacements in the format `:param` or an array of unnamed replacements to replace `?` in your SQL.
* @return {EventEmitter}
*
* @see {DAOFactory#build} for more information about callee.
*/
Sequelize.prototype.query = function(sql, callee, options, replacements) {
if (arguments.length === 4) {
if (Array.isArray(replacements)) {
......@@ -345,6 +511,11 @@ module.exports = (function() {
return this.transactionManager.query(sql, callee, options)
}
/**
* Create a new database schema
* @param {String} schema Name of the schema
* @return {EventEmitter}
*/
Sequelize.prototype.createSchema = function(schema) {
var chainer = new Utils.QueryChainer()
......@@ -353,6 +524,10 @@ module.exports = (function() {
return chainer.run()
}
/**
* Show all defined schemas
* @return {EventEmitter}
*/
Sequelize.prototype.showAllSchemas = function() {
var chainer = new Utils.QueryChainer()
......@@ -361,6 +536,11 @@ module.exports = (function() {
return chainer.run()
}
/**
* Drop a single schema
* @param {String} schema Name of the schema
* @return {EventEmitter}
*/
Sequelize.prototype.dropSchema = function(schema) {
var chainer = new Utils.QueryChainer()
......@@ -369,10 +549,23 @@ module.exports = (function() {
return chainer.run()
}
/**
* Drop all schemas
* @return {EventEmitter}
*/
Sequelize.prototype.dropAllSchemas = function() {
return this.getQueryInterface().dropAllSchemas()
}
/**
* Sync all defined DAOs to the DB.
*
* @param {Object} [options={}]
* @param {Boolean} [options.force=false] If force is true, each DAO will do DROP TABLE IF EXISTS ..., before it tries to create its own table
* @param {Boolean|function} [options.logging=console.log] A function that logs sql queries, or false for no logging
* @param {String} [options.schema='public'] The schema that the tables should be created in. This can be overriden for each table in sequelize.define
* @return {EventEmitter}
*/
Sequelize.prototype.sync = function(options) {
options = options || {}
......@@ -402,6 +595,13 @@ module.exports = (function() {
return chainer.runSerially()
}
/**
* Drop all tables defined through this sequelize instance. This is done by calling Model.drop on each model
* @see {DAO#drop} for options
*
* @param {object} options The options passed to each call to Model.drop
* @return {EventEmitter}
*/
Sequelize.prototype.drop = function(options) {
var self = this
......@@ -421,6 +621,14 @@ module.exports = (function() {
}).run()
}
/**
* Test the connection by trying to authenticate
*
* @fires success If authentication was successfull
* @error 'Invalid credentials' if the authentication failed (even if the database did not respond at all...)
* @alias validate
* @return {EventEmitter}
*/
Sequelize.prototype.authenticate = function() {
var self = this
......@@ -439,18 +647,64 @@ module.exports = (function() {
Sequelize.prototype.validate = Sequelize.prototype.authenticate;
/**
* Creates a object representing a database function. This can be used in search queries, both in where and order parts, and as default values in column definitions.
* If you want to refer to columns in your function, you should use `sequelize.col`, so that the columns are properly interpreted as columns and not a strings.
*
* Convert a user's username to upper case
* ```js
* instance.updateAttributes({
* username: self.sequelize.fn('upper', self.sequelize.col('username'))
* })
* ```
*
* @see {DAOFactory#find}
* @see {DAOFactory#findAll}
* @see {DAOFactory#define}
* @see {Sequelize#col}
*
* @method fn
* @param {String} fn The function you want to call
* @param {any} args All further arguments will be passed as arguments to the function
* @return {Sequelize.fn}
*/
Sequelize.fn = Sequelize.prototype.fn = function (fn) {
return new Utils.fn(fn, Array.prototype.slice.call(arguments, 1))
}
/**
* Creates a object representing a column in the DB. This is often useful in conjunction with `sequelize.fn`, since raw string arguments to fn will be escaped.
* @see {Sequelize#fn}
*
* @method col
* @param {String} col The name of the column
* @return {Sequelize.col}
*/
Sequelize.col = Sequelize.prototype.col = function (col) {
return new Utils.col(col)
}
/**
* Creates a object representing a call to the cast function.
*
* @method cast
* @param {any} val The value to cast
* @param {String} type The type to cast it to
* @return {Sequelize.cast}
*/
Sequelize.cast = Sequelize.prototype.cast = function (val, type) {
return new Utils.cast(val, type)
}
/**
* Creates a object representing a literal, i.e. something that will not be escaped.
*
* @method literal
* @param {any} val
* @alias asIs
* @return {Sequelize.literal}
*/
Sequelize.literal = Sequelize.prototype.literal = function (val) {
return new Utils.literal(val)
}
......@@ -459,14 +713,40 @@ module.exports = (function() {
return new Utils.asIs(val)
}
/**
* An AND query
* @see {DAOFactory#find}
*
* @method and
* @param {String|Object} args Each argument will be joined by AND
* @return {Sequelize.and}
*/
Sequelize.and = Sequelize.prototype.and = function() {
return new Utils.and(Array.prototype.slice.call(arguments))
}
/**
* An OR query
* @see {DAOFactory#find}
*
* @method or
* @param {String|Object} args Each argument will be joined by OR
* @return {Sequelize.or}
*/
Sequelize.or = Sequelize.prototype.or = function() {
return new Utils.or(Array.prototype.slice.call(arguments))
}
/*
* A way of specifying attr = condition. Mostly used internally
* @see {DAOFactory#find}
*
* @param {string} attr The attribute
* @param {String|Object} condition The condition. Can be both a simply type, or a further condition (`.or`, `.and`, `.literal` etc.)
* @method where
* @alias condition
* @return {Sequelize.where}
*/
Sequelize.where = Sequelize.prototype.where = function() {
return new Utils.where(Array.prototype.slice.call(arguments))
}
......@@ -475,12 +755,38 @@ module.exports = (function() {
return new Utils.condition(Array.prototype.slice.call(arguments))
}
/**
* Start a transaction. When using transactions, you should pass the transaction in the options argument in order for the query to happen under that transaction
*
* ```js
* sequelize.transaction(function(t) {
* User.find(..., { transaction: t}).success(function (user) {
* user.updateAttributes(..., { transaction: t}).success(function () {
* t.commit()
* })
* })
*
* // the commit / rollback will emit events which can be observed via:
* t.done(function() {
* })
* })
* ```
*
* @see {Transaction}
* @param {Object} [options={}]
* @param {Boolean} [options.autocommit=true]
* @param {String} [options.isolationLevel='REPEATABLE READ'] See `Sequelize.Transaction.ISOLATION_LEVELS` for possible options
* @param {Function} callback Called when the transaction has been set up and is ready for use. If the callback takes two arguments it will be called with err, transaction, otherwise it will be called with transaction.
* @return {Transaction}
* @fires error If there is an uncaught error during the transaction
* @fires success When the transaction has ended (either comitted or rolled back)
*/
Sequelize.prototype.transaction = function(_options, _callback) {
var options = (typeof _options === 'function') ? {} : _options
, callback = (typeof _options === 'function') ? _options : _callback
, wantsError = (callback.length === 2)
, transaction = new Transaction(this, options)
, self = this
Utils.tick(function() {
if (wantsError) {
......
var Utils = require('./utils')
, util = require('util')
/**
* The transaction object is used to identify a running transaction. It is created by calling `Sequelize.transaction()`.
*
* To run a query under a transaction, you should pass the transaction in the options object.
* @class Transaction
*/
var Transaction = module.exports = function(sequelize, options) {
this.sequelize = sequelize
this.id = Utils.generateUUID()
......@@ -12,6 +18,20 @@ var Transaction = module.exports = function(sequelize, options) {
util.inherits(Transaction, Utils.CustomEventEmitter)
/**
* The possible isolations levels to use when starting a transaction
*
* ```js
* {
* READ_UNCOMMITTED: "READ UNCOMMITTED",
* READ_COMMITTED: "READ COMMITTED",
* REPEATABLE_READ: "REPEATABLE READ",
* SERIALIZABLE: "SERIALIZABLE"
* }
* ```
*
* @property ISOLATION_LEVELS
*/
Transaction.ISOLATION_LEVELS = {
READ_UNCOMMITTED: "READ UNCOMMITTED",
READ_COMMITTED: "READ COMMITTED",
......@@ -19,6 +39,11 @@ Transaction.ISOLATION_LEVELS = {
SERIALIZABLE: "SERIALIZABLE"
}
/**
* Commit the transaction
*
* @return {this}
*/
Transaction.prototype.commit = function() {
return this
.sequelize
......@@ -29,6 +54,11 @@ Transaction.prototype.commit = function() {
}
/**
* Rollback (abort) the transaction
*
* @return {this}
*/
Transaction.prototype.rollback = function() {
return this
.sequelize
......
......@@ -70,6 +70,7 @@
"coveralls": "~2.7.1",
"async": "~0.2.10",
"coffee-script": "~1.7.1",
"markdox": "0.1.4",
"sinon-chai": "~2.5.0"
},
"keywords": [
......
......@@ -27,6 +27,7 @@ if (dialect.match(/^postgres/)) {
done()
})
it('should be able to search within an array', function(done) {
this.User.all({where: {email: ['hello', 'world']}}).on('sql', function(sql) {
expect(sql).to.equal('SELECT * FROM "Users" AS "User" WHERE "User"."email" && ARRAY[\'hello\',\'world\']::TEXT[];')
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!