Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat(angular.info): optionally store and access additional info on mo… #12465

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/.jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
"encodeUriSegment": false,
"encodeUriQuery": false,
"angularInit": false,
"info": false,
"bootstrap": false,
"getTestability": false,
"snake_case": false,
Expand Down
19 changes: 19 additions & 0 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,25 @@ function angularInit(element, bootstrap) {
}
}


/**
* @ngdoc function
* @name angular.info
* @module ng
* @returns { Object }
* An object containing the info about a module or an empty object if
* the module has not been defined.
* @description
* Get the info about a given module.
*/
function info(moduleName) {
try {
return angularModule(moduleName).info();
} catch (e) {
return {};
}
}

/**
* @ngdoc function
* @name angular.bootstrap
Expand Down
3 changes: 2 additions & 1 deletion src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ function publishExternalAPI(angular) {
'getTestability': getTestability,
'$$minErr': minErr,
'$$csp': csp,
'reloadWithDebugInfo': reloadWithDebugInfo
'reloadWithDebugInfo': reloadWithDebugInfo,
'info': info
});

angularModule = setupModuleLoader(window);
Expand Down
34 changes: 34 additions & 0 deletions src/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ function setupModuleLoader(window) {
* @returns {module} new module with the {@link angular.Module} api.
*/
return function module(name, requires, configFn) {

var info = {};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably better to use a createMap() call here


var assertNotHasOwnProperty = function(name, context) {
if (name === 'hasOwnProperty') {
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
Expand Down Expand Up @@ -114,6 +117,37 @@ function setupModuleLoader(window) {
_configBlocks: configBlocks,
_runBlocks: runBlocks,

/**
* @ngdoc method
* @name angular.Module#info
* @module ng
*
* @param {Object=} info Information about the module
* @returns {Object|Module} The current info object for this module if called as a getter,
* or `this` if called as a setter.
*
* @description
* Additional info about this module
* For example you could put the version of the module in here.
*
* ```js
* angular.module('myModule', []).info({ version: '1.0.0' });
* ```
*
* The global method `angular.info()` can be used to retrieve this info:
*
* ```js
* var version = angular.info('myModule').version;
* ```
*/
info: function(value) {
if (isDefined(value)) {
info = value;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do

info = angular.extend(info, angular.isObject(value) ? value : {});

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would mean one could add to the info but never remove anything, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ThomasBurleson - I would rather not use extend here. Can you give a concrete use case?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@petebacondarwin

angular
   .module('ngMaterial',['ngAnimate'])
   .info({ 
      version : "1.0",
      name : "Angular Material"
   });

// Later during runtime
var info = angular.info().ngMaterial;
info.license = "MIT";

The goal of the

info = angular.extend(info, angular.isObject(value) ? value : {});

was to require that a hashamp object was registered not just a simply value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could ensure that value is an object with a check for isObject, rather than using extend().

return this;
}
return info;
},

/**
* @ngdoc property
* @name angular.Module#requires
Expand Down
1 change: 1 addition & 0 deletions test/.jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
"encodeUriSegment": false,
"encodeUriQuery": false,
"angularInit": false,
"info": false,
"bootstrap": false,
"snake_case": false,
"bindJQuery": false,
Expand Down
15 changes: 15 additions & 0 deletions test/AngularSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1614,6 +1614,21 @@ describe('angular', function() {
});
});


describe('info', function() {
it('should return the additional info for the named module', function() {
angular.module('a', []).info({some: 'thing'});
angular.module('b', ['dep'], function configFn() {}).info({other: 'thang'});

expect(info('a')).toEqual({some: 'thing'});

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is the info() defined ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is defined in the closure and on angular so we could make this test more clear.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kk. The definition is in src/Angular.js.

expect(info('b')).toEqual({other: 'thang'});
});

it('should return anh empty object if there is no such module', function() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

expect(info('no-such-module')).toEqual({});
});
});

describe('bootstrap', function() {
it('should bootstrap app', function() {
var element = jqLite('<div>{{1+2}}</div>');
Expand Down
32 changes: 27 additions & 5 deletions test/loaderSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ describe('module loader', function() {


it('should record calls', function() {
function config() {}
function init() {}
function init2() {}

var otherModule = window.angular.module('other', []);
otherModule.config('otherInit');
otherModule.config(init);

var myModule = window.angular.module('my', ['other'], 'config');
var myModule = window.angular.module('my', ['other'], config);

expect(myModule.
decorator('dk', 'dv').
Expand All @@ -40,7 +44,7 @@ describe('module loader', function() {
filter('f', 'ff').
directive('d', 'dd').
controller('ctrl', 'ccc').
config('init2').
config(init2).
constant('abc', 123).
run('runBlock')).toBe(myModule);

Expand All @@ -57,13 +61,31 @@ describe('module loader', function() {
['$controllerProvider', 'register', ['ctrl', 'ccc']]
]);
expect(myModule._configBlocks).toEqual([
['$injector', 'invoke', ['config']],
['$injector', 'invoke', ['init2']]
['$injector', 'invoke', [config]],
['$injector', 'invoke', [init2]]
]);
expect(myModule._runBlocks).toEqual(['runBlock']);
});


it('should store additional module info', function() {
var myModule = angular.module('myModule', ['dep1']).info({version: '1.0'});
var otherModule = angular.module('otherModule', ['dep2'], function someConfig() {}).info({version: '2.0'});
var thirdModule = angular.module('thirdModule', ['dep2', 'dep3'], [function someConfig() {}]).info({version: '3.0'});
var fourthModule = angular.module('fourthModule', [], [function someConfig() {}]);

expect(myModule.info()).toEqual({version: '1.0'});
expect(otherModule.info()).toEqual({version: '2.0'});
expect(thirdModule.info()).toEqual({version: '3.0'});
expect(fourthModule.info()).toEqual({});

expect(angular.info('myModule')).toEqual({version: '1.0'});
expect(angular.info('otherModule')).toEqual({version: '2.0'});
expect(angular.info('thirdModule')).toEqual({version: '3.0'});
expect(angular.info('fourthModule')).toEqual({});
});


it('should allow module redefinition', function() {
expect(window.angular.module('a', [])).not.toBe(window.angular.module('a', []));
});
Expand Down