Skip to content

Commit 009ae90

Browse files
support global configuration.
1 parent c550d09 commit 009ae90

20 files changed

Lines changed: 562 additions & 192 deletions

File tree

docs/components/docs/docs.html

Lines changed: 51 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,65 @@ <h1 class="page-title">Node.js</h1>
1313
</header>
1414

1515
<section class="content">
16-
<article>
17-
<h1>{{module[0].toUpperCase() + module.substr(1)}}</h1>
16+
<h1>{{module[0].toUpperCase() + module.substr(1)}}</h1>
17+
<h3 class="sub-heading">
18+
<div class="toggler" ng-click="showGcloudDocs = !showGcloudDocs">
19+
<span class="toggle" ng-hide="showGcloudDocs"></span>
20+
<span class="toggle" ng-show="showGcloudDocs"></span>
21+
</div>
22+
Getting Started with <code>gcloud</code>
23+
</h3>
24+
<article ng-if="showGcloudDocs">
1825
<p>
1926
First, install <code>gcloud</code> with npm and require it into your project:
2027
</p>
2128
<div hljs>$ npm install --save gcloud</div>
2229
<div hljs>var gcloud = require('gcloud');</div>
30+
<p>
31+
There are a couple of ways to use the <code>gcloud</code> module.
32+
</p>
33+
<p>
34+
If you are running your app on Google App Engine or Google Compute Engine, you won't need to worry about supplying connection configuration options to <code>gcloud</code>&mdash; we figure that out for you.
35+
</p>
36+
<p>
37+
However, if you're running your app elsewhere, you will need to provide this information.
38+
</p>
39+
<div hljs>
40+
// App Engine and Compute Engine
41+
var gcloud = require('gcloud');
2342

24-
<article ng-if="isActiveDoc('datastore')">
25-
<p>
26-
The <code>gcloud.datastore</code> object gives you some convenience methods, as well as exposes a <code>Dataset</code> function. This will allow you to create a <code>Dataset</code>, which is the object from which you will interact with the Google Cloud Datastore.
27-
</p>
28-
<div hljs>
43+
// Elsewhere
44+
var gcloud = require('gcloud')({
45+
keyFilename: '/path/to/keyfile.json'
46+
});</div>
47+
<p>
48+
In any environment, you are free to provide these and other default properties, which eventually will be passed to the <code>gcloud</code> sub-modules (Datastore, Storage, etc.).
49+
</p>
50+
</article>
51+
<hr>
52+
<article ng-if="isActiveDoc('datastore')">
53+
<h2>Overview</h2>
54+
<p>
55+
The <code>gcloud.datastore</code> object gives you some convenience methods, as well as exposes a <code>dataset</code> function. This will allow you to create a <code>dataset</code>, which is the object from which you will interact with the Google Cloud Datastore.
56+
</p>
57+
<div hljs>
2958
var datastore = gcloud.datastore;
30-
var dataset = new datastore.Dataset();</div>
31-
<p ng-if="!isActiveUrl('/docs/datastore/dataset')">
32-
See <a href="#/docs/datastore/dataset">the Dataset documentation</a> for examples of how to query the datastore, save entities, run a transaction, and others.
33-
</p>
34-
</article>
35-
36-
<article ng-if="isActiveDoc('storage')">
37-
<p>
38-
The <code>gcloud.storage</code> object contains a <code>Bucket</code> object, which is how you will interact with your Google Cloud Storage bucket.
39-
</p>
40-
<div hljs>
41-
var storage = gcloud.storage;
42-
var bucket = new storage.Bucket({
43-
bucketName: 'MyBucket'
59+
var dataset = datastore.dataset({
60+
projectId: 'myProject',
61+
keyFilename: '/path/to/keyfile.json'
4462
});</div>
45-
<p>
46-
See examples below for more on how to upload a file, read from your bucket's files, create signed URLs, and more.
47-
</p>
48-
</article>
63+
<p ng-if="!isActiveUrl('/docs/datastore/dataset')">
64+
See <a href="#/docs/datastore/dataset">the Dataset documentation</a> for examples of how to query the datastore, save entities, run a transaction, and others.
65+
</p>
66+
</article>
67+
<article ng-if="isActiveDoc('storage')">
68+
<h2>Overview</h2>
69+
<p>
70+
The <code>gcloud.storage</code> object contains a <code>bucket</code> object, which is how you will interact with your Google Cloud Storage bucket. See the guide on <a href="https://developers.google.com/storage">Google Cloud Storage</a> to create a bucket.
71+
</p>
72+
<p>
73+
See examples below for more on how to access your bucket to upload a file, read its files, create signed URLs, and more.
74+
</p>
4975
</article>
5076

5177
<article

docs/components/docs/docs.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ angular
6767
return {
6868
data: obj,
6969
name: obj.ctx.name,
70+
constructor: obj.tags.some(function(tag) {
71+
return tag.type === 'constructor';
72+
}),
7073
description: $sce.trustAsHtml(
7174
formatHtml(detectLinks(detectModules(obj.description.full)))),
7275
params: obj.tags.filter(function(tag) {
@@ -95,7 +98,7 @@ angular
9598
};
9699
})
97100
.sort(function(a, b) {
98-
return a.name > b.name;
101+
return a.constructor ? -1: a.name > b.name;
99102
});
100103
};
101104
}

docs/css/main.css

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,21 @@ h2, h3 {
625625
display: block;
626626
}
627627

628+
.sub-heading {
629+
color: #5d6061;
630+
margin: 0;
631+
}
632+
633+
.toggler {
634+
float: left;
635+
min-width: 15px;
636+
margin: auto;
637+
}
638+
639+
.toggle {
640+
cursor: pointer;
641+
}
642+
628643
/*
629644
Page Title
630645
*/

lib/common/util.js

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,50 @@
2121
* @module common/util
2222
*/
2323

24+
var extend = require('extend');
2425
var util = require('util');
2526

2627
/**
27-
* Extend a base object with properties from another.
28+
* Extend a global configuration object with user options provided at the time
29+
* of sub-module instantiation.
2830
*
29-
* @param {object} from - The base object.
30-
* @param {object} to - The object to extend with.
31+
* Connection details currently come in two ways: `credentials` or
32+
* `keyFilename`. Because of this, we have a special exception when overriding a
33+
* global configuration object. If a user provides either to the global
34+
* configuration, then provides another at submodule instantiation-time, the
35+
* latter is preferred.
36+
*
37+
* @param {object} globalConfig - The global configuration object.
38+
* @param {object} overrides - The instantiation-time configuration object.
3139
* @return {object}
32-
* ```
40+
*
41+
* @example
42+
* // globalConfig = {
43+
* // credentials: {...}
44+
* // }
45+
* Datastore.prototype.dataset = function(options) {
46+
* // options = {
47+
* // keyFilename: 'keyfile.json'
48+
* // }
49+
* return extendGlobalConfig(this.config, options);
50+
* // returns:
51+
* // {
52+
* // keyFilename: 'keyfile.json'
53+
* // }
54+
* };
3355
*/
34-
function extend(from, to) {
35-
if (from === null || typeof from !== 'object') {
36-
return from;
37-
}
38-
if (from.constructor === Date || from.constructor === Function ||
39-
from.constructor === String || from.constructor === Number ||
40-
from.constructor === Boolean) {
41-
return new from.constructor(from);
42-
}
43-
if (from.constructor !== Object && from.constructor !== Array) {
44-
return from;
45-
}
46-
to = to || new from.constructor();
47-
for (var name in from) {
48-
to[name] = to[name] ? extend(from[name], null) : to[name];
56+
function extendGlobalConfig(globalConfig, overrides) {
57+
var options = extend({}, globalConfig);
58+
var hasGlobalConnection = options.credentials || options.keyFilename;
59+
var isOverridingConnection = overrides.credentials || overrides.keyFilename;
60+
if (hasGlobalConnection && isOverridingConnection) {
61+
delete options.credentials;
62+
delete options.keyFilename;
4963
}
50-
return to;
64+
return extend(true, {}, options, overrides);
5165
}
5266

53-
module.exports.extend = extend;
67+
module.exports.extendGlobalConfig = extendGlobalConfig;
5468

5569
/**
5670
* Wrap an array around a non-Array object. If given an Array, it is returned.

lib/datastore/dataset.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ var SCOPES = [
7474
* @alias module:datastore/dataset
7575
*
7676
* @param {object=} options
77-
* @param {string} options.projectId - Dataset ID. This is your project ID from
77+
* @param {string=} options.projectId - Dataset ID. This is your project ID from
7878
* the Google Developers Console.
7979
* @param {string=} options.keyFilename - Full path to the JSON key downloaded
8080
* from the Google Developers Console. Alternatively, you may provide a
@@ -84,20 +84,24 @@ var SCOPES = [
8484
* @param {string} options.namespace - Namespace to isolate transactions to.
8585
*
8686
* @example
87-
* var dataset = new datastore.Dataset({
87+
* var dataset = datastore.dataset({
8888
* projectId: 'my-project',
8989
* keyFilename: '/path/to/keyfile.json'
9090
* });
9191
*/
9292
function Dataset(options) {
93+
if (!(this instanceof Dataset)) {
94+
return new Dataset(options);
95+
}
96+
9397
options = options || {};
9498

9599
this.connection = new conn.Connection({
96100
credentials: options.credentials,
97101
keyFilename: options.keyFilename,
98102
scopes: SCOPES
99103
});
100-
this.id = options.projectId;
104+
this.projectId = options.projectId;
101105
this.namespace = options.namespace;
102106
this.transaction = this.createTransaction_();
103107
}
@@ -108,13 +112,11 @@ function Dataset(options) {
108112
* You may also specify a configuration object to define a namespace and path.
109113
*
110114
* @example
111-
* var key;
112-
*
113115
* // Create a key from the dataset's namespace.
114-
* key = dataset.key('Company', 123);
116+
* var company123 = dataset.key('Company', 123);
115117
*
116118
* // Create a key from a provided namespace and path.
117-
* key = dataset.key({
119+
* var nsCompany123 = dataset.key({
118120
* namespace: 'My-NS',
119121
* path: ['Company', 123]
120122
* });
@@ -347,7 +349,7 @@ Dataset.prototype.allocateIds = function(incompleteKey, n, callback) {
347349
* @private
348350
*/
349351
Dataset.prototype.createTransaction_ = function() {
350-
return new Transaction(this.connection, this.id);
352+
return new Transaction(this.connection, this.projectId);
351353
};
352354

353355
module.exports = Dataset;

lib/datastore/index.js

Lines changed: 85 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,97 @@
2626
*/
2727
var entity = require('./entity');
2828

29-
/*!
30-
* @alias module:datastore
29+
/**
30+
* @type module:common/util
31+
* @private
32+
*/
33+
var util = require('../common/util.js');
34+
35+
/**
36+
* @type module:datastore/dataset
37+
* @private
3138
*/
32-
var datastore = {};
39+
var Dataset = require('./dataset');
3340

41+
/*! Developer Documentation
42+
*
43+
* Invoking the Datastore class allows you to provide configuration up-front.
44+
* This configuration will be used for future invokations of the returned
45+
* `dataset` method.
46+
*
47+
* @example
48+
* var datastore = require('gcloud/lib/datastore')({
49+
* keyFilename: '/path/to/keyfile.json'
50+
* });
51+
*
52+
* var dataset = datastore.dataset();
53+
* // equal to:
54+
* // datastore.dataset({
55+
* // keyFilename: '/path/to/keyfile.json'
56+
* // });
57+
*/
3458
/**
35-
* @see {module:datastore/dataset}
59+
* The example below will demonstrate the different usage patterns your app may
60+
* need to support to retrieve a datastore object.
61+
*
62+
* @alias module:datastore
63+
* @constructor
3664
*
3765
* @example
3866
* var gcloud = require('gcloud');
39-
* var datastore = gcloud.datastore;
67+
*
68+
* // Providing configuration details up-front.
69+
* var myProject = gcloud({
70+
* keyFilename: '/path/to/keyfile.json',
71+
* projectId: 'my-project'
72+
* });
73+
*
74+
* var dataset = myProject.datastore.dataset();
75+
*
76+
*
77+
* // Overriding default configuration details.
78+
* var anotherDataset = myProject.datastore.dataset({
79+
* keyFilename: '/path/to/another/keyfile.json'
80+
* });
81+
*
82+
*
83+
* // Not using a default configuration.
84+
* var myOtherProject = gcloud.datastore.dataset({
85+
* keyFilename: '/path/to/keyfile.json',
86+
* projectId: 'my-project'
87+
* });
88+
*/
89+
function Datastore(config) {
90+
this.config = config || {};
91+
}
92+
93+
/*! Developer Documentation
94+
*
95+
* Use this static method to create a dataset without any pre-configured
96+
* options.
97+
*
98+
* @example
99+
* var datastore = require('gcloud/lib/datastore');
40100
*
41101
* // Create a Dataset object.
42-
* var dataset = new datastore.Dataset();
102+
* var dataset = datastore.dataset({
103+
* keyFilename: '/path/to/keyfile.json'
104+
* });
43105
*/
44-
datastore.Dataset = require('./dataset');
106+
Datastore.dataset = Dataset;
107+
108+
/*! Developer Documentation
109+
*
110+
* Create a dataset using the instance method when you want to use your
111+
* pre-configured options from the Datastore instance.
112+
*
113+
* @param {object=} options - Configuration object.
114+
* @return {module:datastore/dataset}
115+
*/
116+
Datastore.prototype.dataset = function(options) {
117+
// Mix in global config data to the provided options.
118+
return new Dataset(util.extendGlobalConfig(this.config, options));
119+
};
45120

46121
/**
47122
* Helper function to get a Datastore Integer object.
@@ -55,7 +130,7 @@ datastore.Dataset = require('./dataset');
55130
* // Create an Integer.
56131
* var sevenInteger = gcloud.datastore.int(7);
57132
*/
58-
datastore.int = function(value) {
133+
Datastore.int = function(value) {
59134
return new entity.Int(value);
60135
};
61136

@@ -71,8 +146,8 @@ datastore.int = function(value) {
71146
* // Create a Double.
72147
* var threeDouble = gcloud.datastore.double(3.0);
73148
*/
74-
datastore.double = function(value) {
149+
Datastore.double = function(value) {
75150
return new entity.Double(value);
76151
};
77152

78-
module.exports = datastore;
153+
module.exports = Datastore;

0 commit comments

Comments
 (0)