gobwas / dm.js

Javascript Dependency Injection Manager
MIT License
108 stars 4 forks source link

A way to inject a service which is declared as a part of a complex module. #36

Closed franza closed 9 years ago

franza commented 9 years ago

Hey there, I'd like to use dm.js in my development but I have a question. Assume, you are in NodeJS and you have a class:

// models.js
function Person () { /* ... */ }
// ... here go the declarations of other classes

And it is exported as a property of a module:

// models.js
module.exports = {
  Person: require('./person'),
  // ... here go some other classes
}

How will you register the instance of Person in this case? If config looks like:

var config = {
  "person": {
    "path": "???"
  }

What should be specified in path property? Is there a way to specify a property of module?

gobwas commented 9 years ago

Hello!

Looks like right now it cannot be solved any way.

But this feature looks like really useful.

How do you think it could be declared in config? I can implement it soon.

First thoughts is to write new Loader class, that will be keep this logic.

franza commented 9 years ago

Smth like this maybe:

var config = {
  "person": {
    "path": "path/to/module#property1.property2.property3"
  }
};

or use some kind of JSONPath here:

var config = {
  "person": {
    "path": "path/to/module",
    "jsonPath": "$.property1.property2.property3"
  }
};

Also, need to consider the fact that if no property was passed, then use the old logic (one module - one class). What do you think?

P.S. Is there a way to resolve dependencies synchronously?

gobwas commented 9 years ago

I think the first case is a good one. But I was planned to do this via JSON Pointer. And the second but - is that we need to add ability also require by module names, like:

{
  "emitter": {
    "path": "events#EventEmitter"
  }
}

P.S. Yes, you can use BroodyPromisesAsync adapter. =)

franza commented 9 years ago

I cannot catch your second point. Can you add more details on that?

gobwas commented 9 years ago

I mean CJSLoader class receives options object, with optional base property. When he receives string to load, he try to make some path.resolve(base, needle). So, if you pass just a module name, like events - it could become a path/to/base/events, if base option was set. =)

I think to resolve this by the checking first symbol of path to equality with ..

franza commented 9 years ago

Just to notice - the case with NODE_PATH var is set should be handled too, but I guess it is handled automatically then.

gobwas commented 9 years ago

Hey @franza, just released RC version now.

You could install it via:

npm install dm@0.3.1-rc

Use with this RFC.

Will release 0.3.1 soon if there is no errors.

Thanks!

franza commented 9 years ago

That's great! Btw, what's the syntax to use?

gobwas commented 9 years ago

Smth like:

// path/to/my/module.js
module.exports = {
  field: function Ctor() {...}
}

{
  path: "path/to/my/module.js#/field"
}
gobwas commented 9 years ago

Is it OK? )

franza commented 9 years ago

Nope, npm install dm@0.3.1-rc doesn't work for me. It shows:

npm ERR! Error: version not found: dm@0.3.1-rc
npm ERR!     at /home/ubuntu/.nvm/v0.10.35/lib/node_modules/npm/lib/cache/add-named.js:125:12
npm ERR!     at saved (/home/ubuntu/.nvm/v0.10.35/lib/node_modules/npm/node_modules/npm-registry-client/lib/get.js:167:7)
npm ERR!     at Object.oncomplete (fs.js:108:15)
npm ERR! If you need help, you may report this *entire* log,
npm ERR! including the npm and node versions, at:
npm ERR!     <http://github.com/npm/npm/issues>
gobwas commented 9 years ago

0.3.1-rc is a npm tag, you could use it instead of npm install dm@latest, like: npm install dm@0.3.1-rc. In package.json you should use "dm": "0.3.1-rc0" - with concrete version number =)

franza commented 9 years ago

Argh, so it is npm install dm@0.3.1-rc0

gobwas commented 9 years ago

Yes, at my home npm with oldest version it worked =) Now tags must be not a semver like =(

franza commented 9 years ago

Ok, that worked and new feature works great. Thank you very much.

I also have a question about instantiating objects. So assume that you don't use a constructor and new word, but use plain old functions:

function getMySQLConfigs() {
  return { /* ... */ };
}

Is it supported in dm.js?

UPDATE: Another case is if we want to inject a plain object which is declared in other module.

gobwas commented 9 years ago

There is some issue for that puproses. Fell free to comment and improve an idea.