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

Conversation

petebacondarwin
Copy link
Contributor

…dules

This feature allows the developer to store additional meta data about a
module when it is defined by adding an additional parameter containing
an object to the angular.module(moduleName, deps, info, configFn) call.

Developers can then access this information by calling angular.info(moduleName)

See this angular/material#3842 for more background.

@lgalfaso
Copy link
Contributor

This approach may solve the issue of getting some meta-data out of a module (if a new bootstrap is made). On the other hand, given that it is possible to have modules redefinition, there would be no mechanism to see the metadata of the instance of a module that is used in any given $injector. Is the new functionality going to be used to know before bootstrapping the information of a given module or is the information going to be used after bootstrapping to know the metadata of a module loaded in the current $injector?

@caitp caitp added this to the 1.5.x - migration-facilitation milestone Jul 30, 2015
@petebacondarwin
Copy link
Contributor Author

The primary use case came from Angular Material, where they wanted to publish the version of the module so that when you are debugging some app, you can quickly drop into the browser console and see what versions are loaded.

@petebacondarwin
Copy link
Contributor Author

@lgalfaso is it common to load a module, create an injector, override the module with a new module and then create another injector in a single application?

angular.module('a', [], {some: 'thing'});
angular.module('b', ['dep'], {other: 'thang'}, function configFn() {});

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.

@ThomasBurleson
Copy link

@petebacondarwin - The function signature

return function module(name, requires, configFnOrInfo, configFn) {
};

looks like it will present issues Angular Material using Angular versions <1.4.4; ngMaterial would have to pre-check the registration call using angular.module.length right ?

It appears that an alternative signature would not require an argument count precheck.

return function module(name, requires, configFn, info) {
};

It is late, perhaps I am not thinking clearly here.

@petebacondarwin
Copy link
Contributor Author

The configFn is optional and often left out so we would need to do some wrangling either way.

@lgalfaso
Copy link
Contributor

The configFn is optional and often left out so we would need to do some wrangling either way.

I think that the intention of the comment is that if someone wants to make a module that is 1.4.3 and 1.4.4 compatible, then, to be safe, would need to put the info parameter in the forth position anyhow. So why just not make it the forth position in the first place.

@lgalfaso
Copy link
Contributor

@lgalfaso is it common to load a module, create an injector, override the module with a new module and then create another injector in a single application?

For apps where there are multiple non-trivial angular apps running at the same time and browserify (or any of the similar libraries are used), then the chances of having a module redefinition is quite high (even when in most cases the redefinition is just to a slightly different version of the same module (eg ui-router).

I think that this falls into the less than 5% of the cases. That said, I do not think it would be a more code to make it work as $injector.info(moduleName) (or even both ways and one would be the info on the currently loaded module and the other on the currently running in that injector)

@petebacondarwin
Copy link
Contributor Author

The configFn is optional and often left out so we would need to do some wrangling either way.

I think that the intention of the comment is that if someone wants to make a module that is 1.4.3 and 1.4.4 compatible, then, to be safe, would need to put the info parameter in the forth position anyhow. So why just not make it the forth position in the first place.

@lgalfaso but both the old (configFn) and new (info) parameters are optional so it is backward compatible: you can still do:

angular.module(moduleName, depencencyArray, configFn);

I know that it is the norm to add new parameters to the end of the argument list but when both are optional then it doesn't make much difference. In this case, I believe that it is more pleasant, if you are going to provide both info and a configFn for the configFn to come at the end:

angular.module('someModule`, ['someDependency'], {version: '1.0.2'}, function() {
  ...
});

@lgalfaso
Copy link
Contributor

lgalfaso commented Aug 5, 2015

@petebacondarwin I am just saying that, if people want to be safe, then they will need to put the info parameter in the forth position. The reason being that if they put it in the third position and this module is used with angular 1.4.3, then it would fail.

Note: If people have complete control of the environment their module will run, then this is not an issue, but this is an issue for material design as they should work fine with angular 1.4.3

@petebacondarwin
Copy link
Contributor Author

Oh right! The concern is that people using this feature will cause their modules to be incompatible with previous versions of angular.

This would still be the case if we add it as a fourth parameter but the user chooses not to provide a configFn.

So I think we should move this out of the module function and have it as a method.

@ThomasBurleson
Copy link

@petebacondarwin 👍

…dules

This feature allows the developer to store additional meta data about a
module when it is defined by calling `mod.info(infoObject)` on the module
object.

Developers can then access this information by calling `mod.info()` or
`angular.info(moduleName)`.

See this angular/material#3842 for more background.

Closes angular#12465
*/
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().

@IgorMinar
Copy link
Contributor

What if angular.info() returned a map with all available module names as keys and an object with module specific data (or an empty object if no data is provided).

that way it's easy to see what's available without many angular.info(moduleName) calls.

@ThomasBurleson
Copy link

I think both would be great:

angular.info(<moduleName>) : for specific module info object
angular.info( ) : for hashmap of all modules info objects keyed by moduleName

@IgorMinar - thoughts?

@IgorMinar
Copy link
Contributor

angular.info()[moduleName] is the same as angular.info(moduleName), so why provide both?

@ThomasBurleson
Copy link

@IgorMinar - Agreed: superfluous.

@petebacondarwin petebacondarwin modified the milestones: 1.6.x, 1.5.x - migration-facilitation Nov 10, 2015
@@ -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

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

@petebacondarwin petebacondarwin mentioned this pull request Oct 7, 2016
3 tasks
@petebacondarwin
Copy link
Contributor Author

Closing in favour of #15225

@petebacondarwin petebacondarwin deleted the angular.info branch November 24, 2016 09:04
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants