Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor!: module to api and module config #943

Conversation

TimoGlastra
Copy link
Contributor

@TimoGlastra TimoGlastra commented Jul 11, 2022

Extracts all modules to a separate module class and rename all previous module classes to XXXApi. For now the module is still internal and takes config from the agent config, but it shows how custom module configuration works. This is one step closer to configurable modules.

Basically how you'd use it (if we have full modularization):

const agent = new Agent({
  modules: {
    credentials: new CredentialsModule({
        autoAcceptCredentials: AutoAcceptCredential.always
    })
  }
})

The credentials api can then depend on it like this:

CredentialsApi {
  public constructor(
    credentialsModuleConfig: CredentialsModuleConfig
  ) {
   const autoAcceptCredentials = this.credentialsModuleConfig.autoAcceptCredentials
  }
}

@karimStekelenburg @blu3beri @genaris @2byrds @JamesKEbert Thoughts? If we can agree on the approach for configuration, I can update it for all modules. We can still keep it in init config (so there won't be much breaking changes for now). But from then on it will be trivial to start extracting modules out of core

@TimoGlastra TimoGlastra requested a review from a team as a code owner July 11, 2022 15:57
@TimoGlastra TimoGlastra marked this pull request as draft July 11, 2022 15:57
@TimoGlastra TimoGlastra added the modularization Tasks related to modularization of the framework label Jul 11, 2022
@karimStekelenburg
Copy link
Contributor

I'm a bit confused on what the intent is of this addition. Is my understanding correct that we're currently in a sort of 'hybrid state' where we can register modules both the old and the new way?

Regardless, a showcase/reference implementation is useful indeed. Probably needless to say, but I would prefer to refactor the configuration for all modules before releasing 0.3.0.

@TimoGlastra
Copy link
Contributor Author

TimoGlastra commented Jul 12, 2022

Is my understanding correct that we're currently in a sort of 'hybrid state' where we can register modules both the old and the new way?

Well this PR is just to demonstrate how it would look and get some feedback (hence draft PR). If we think this is a good approach I'll update this PR to refactor all modules to the new format with config. However I won't immediately remove the old way, I'd like to do that in a separate PR

Copy link
Contributor

@berendsliedrecht berendsliedrecht left a comment

Choose a reason for hiding this comment

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

Really nice! Just let some comments, mainly on usability.

packages/core/src/agent/BaseAgent.ts Show resolved Hide resolved
packages/core/src/modules/credentials/CredentialsApi.ts Outdated Show resolved Hide resolved
// Api
dependencyManager.registerContextScoped(CredentialsModule)
dependencyManager.registerContextScoped(CredentialsApi)
Copy link
Contributor

Choose a reason for hiding this comment

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

I am still not the biggest fan of these register function names. I think that registerContextScoped is a bit ambiguous and does not tell me when to use this method in the context of AFJ.

aliassing it to something like: registerPublicApi or whatever fits better might be worth it to make writing external plugins a lot easier.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I see your point. What I'm not sure about is that we're not sure yet what types of components people want to register. Maybe we can come up with a set of components, but it would need to cover all cases.

  • registerApi for the api instead of registerContextScoped
  • registerStatelessService instead of registerSingleton
  • registerInstance stays as is

We would still need another name for the registerContextScoped if you have something that is not an API but needs to be unique per context. Do you like this direction better?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah this makes it a lot easier to understand. Maybe for the registerContextScoped without an api and needs to be unique, we can use registerStatefulService? I believe that that is what you want to register, 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.

I'll raise it during the WG call and gather some more input on this. If we agree we want to change something, I'll raise another PR

autoAcceptCredentials: AutoAcceptCredential
}

export class CredentialsModuleConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

This is awesome! Way more clear which properties from the agent config are with that module.

Just more curious, how do we deal with configuration shared between modules, if it ever occurs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question. I think either declare it in both modules and provide it twice, or one module can depend on the configuration of the other module (if they are dependant on each other).

E.g. the outOfBandModule can depend on the autoAcceptConnections from the ConnectionsModule (as you can't use the oob module without the connections module). Does that make sense?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah that makes sense. Is it obvious to the user that the autoAcceptConnections from the ConnectionsModule will be used in the outOfBandModule?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure. We could add it to the documentation of the out of band module. So in the receiveInvitation method documentation we can mention it will use the autoAcceptConnections property from the connections module config to determine whether to auto accept the config.

I've added the config of each module as a public readonly property to the api class, which means it's public api and makes sense it can be used by other modules.

So agent.connections.config is a public property that exposes the config of the connections module

@TimoGlastra TimoGlastra force-pushed the feat/module-configuration branch 2 times, most recently from 5141660 to 20c35d0 Compare July 13, 2022 22:14
@codecov-commenter
Copy link

codecov-commenter commented Jul 13, 2022

Codecov Report

Merging #943 (af8f301) into 0.3.0-pre (d8ec58b) will increase coverage by 0.14%.
The diff coverage is 82.60%.

@@              Coverage Diff              @@
##           0.3.0-pre     #943      +/-   ##
=============================================
+ Coverage      87.13%   87.28%   +0.14%     
=============================================
  Files            539      562      +23     
  Lines          13086    13272     +186     
  Branches        2244     2142     -102     
=============================================
+ Hits           11403    11584     +181     
- Misses          1587     1684      +97     
+ Partials          96        4      -92     
Impacted Files Coverage Δ
packages/core/src/agent/AgentConfig.ts 95.00% <ø> (ø)
...les/credentials/models/CredentialAutoAcceptType.ts 100.00% <ø> (ø)
...s/generic-records/services/GenericRecordService.ts 88.88% <ø> (ø)
packages/core/src/plugins/Module.ts 50.00% <0.00%> (-50.00%) ⬇️
...ages/core/src/storage/migration/UpdateAssistant.ts 89.41% <33.33%> (-4.26%) ⬇️
...e/src/modules/question-answer/QuestionAnswerApi.ts 56.41% <56.41%> (ø)
packages/core/src/modules/routing/RecipientApi.ts 63.36% <63.36%> (ø)
...c/modules/discover-features/DiscoverFeaturesApi.ts 63.46% <63.46%> (ø)
packages/core/src/modules/dids/DidsApi.ts 64.70% <64.70%> (ø)
...ges/core/src/modules/connections/ConnectionsApi.ts 66.07% <66.07%> (ø)
... and 111 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d8ec58b...af8f301. Read the comment docs.

@TimoGlastra TimoGlastra added the breaking change PR that introduces a breaking change label Jul 14, 2022
@TimoGlastra TimoGlastra changed the title feat(credentials): credential module config @TimoGlastra refactor!: module to api and module config Jul 15, 2022
@TimoGlastra TimoGlastra changed the title @TimoGlastra refactor!: module to api and module config refactor!: module to api and module config Jul 15, 2022
Signed-off-by: Timo Glastra <timo@animo.id>
@TimoGlastra TimoGlastra force-pushed the feat/module-configuration branch 2 times, most recently from b6f3256 to 55b94ac Compare July 15, 2022 20:31
@TimoGlastra TimoGlastra marked this pull request as ready for review July 15, 2022 20:31
Signed-off-by: Timo Glastra <timo@animo.id>
Signed-off-by: Timo Glastra <timo@animo.id>
Copy link
Contributor

@berendsliedrecht berendsliedrecht left a comment

Choose a reason for hiding this comment

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

Nice stuff in here! Also a good idea to mark stuff with @deprecated. However, do we have any backwards compatibility with the agent config from before?

@TimoGlastra
Copy link
Contributor Author

Nice stuff in here! Also a good idea to mark stuff with @deprecated. However, do we have any backwards compatibility with the agent config from before?

What do you mean exactly with from before?

@berendsliedrecht
Copy link
Contributor

What do you mean exactly with from before?

Well, you added a deprecation notice like so:

  /**
    * @deprecated use indyLedgers from the `LedgerModuleConfig` class
    */
   public get indyLedgers() {
     return this.initConfig.indyLedgers ?? []
   }

This would mean that this is still works and will get the value from the initConfig. Is that correct?

@TimoGlastra
Copy link
Contributor Author

Yes, currently all values still come from the init config. This is mainly because there's no way to configure the internal modules yet. So the main init config is the easiest to make sure it keeps working, but already allowing custom config for custom modules.

I'm still not sure what the best approach is for internal module configuration. My thoughts were to maybe allow to define the module yourself and we'll only register it internally with default config if you don't provide the module.

Without custom config the connections module is registerd internally and auto accept connections will have default value false.

const agent = new Agent({
  modules: {

  }
})

If i register it, it won't be registered internally and we'll use the config as passed by the user.

const agent = new Agent({
  connections: new ConnectionsModule({
     autoAcceptConnections: true
  })
})

But maybe there's other / better appraoches?

@berendsliedrecht
Copy link
Contributor

But maybe there's other / better appraoches?

I quite like this approach and I think that we should do it like that.

One thing that might become slightly annoying here is that shared configuration, I don't think it will happen a lot so it might just be ignored for now.

One quick fix that I have for that is to do it like so:

const agent = new Agent({
  config: {
     autoAcceptConnections: true
  },
  connections: new ConnectionsModule()
})

We can create some cool type that infers the config types from the modules you have added, but this will leave us again with a large object where all the configuration is mashed together...

TBH I prefer your method, but maybe this can give some inspiration for another solution that fixes every problem :)

@TimoGlastra
Copy link
Contributor Author

Merging as only failing test is BBS+ test

@TimoGlastra TimoGlastra merged commit 0f4cc18 into openwallet-foundation:0.3.0-pre Jul 19, 2022
@TimoGlastra TimoGlastra deleted the feat/module-configuration branch July 19, 2022 09:49
@TimoGlastra TimoGlastra restored the feat/module-configuration branch July 20, 2022 19:34
TimoGlastra added a commit that referenced this pull request Aug 11, 2022
Signed-off-by: Timo Glastra <timo@animo.id>

BREAKING CHANGE: All module api classes have been renamed from `XXXModule` to `XXXApi`. A module now represents a module plugin, and is separate from the API of a module. If you previously imported e.g. the `CredentialsModule` class, you should now import the `CredentialsApi` class
TimoGlastra added a commit that referenced this pull request Aug 26, 2022
Signed-off-by: Timo Glastra <timo@animo.id>

BREAKING CHANGE: All module api classes have been renamed from `XXXModule` to `XXXApi`. A module now represents a module plugin, and is separate from the API of a module. If you previously imported e.g. the `CredentialsModule` class, you should now import the `CredentialsApi` class
TimoGlastra added a commit that referenced this pull request Aug 26, 2022
Signed-off-by: Timo Glastra <timo@animo.id>

BREAKING CHANGE: All module api classes have been renamed from `XXXModule` to `XXXApi`. A module now represents a module plugin, and is separate from the API of a module. If you previously imported e.g. the `CredentialsModule` class, you should now import the `CredentialsApi` class
genaris pushed a commit to 2060-io/aries-framework-javascript that referenced this pull request Sep 16, 2022
Signed-off-by: Timo Glastra <timo@animo.id>

BREAKING CHANGE: All module api classes have been renamed from `XXXModule` to `XXXApi`. A module now represents a module plugin, and is separate from the API of a module. If you previously imported e.g. the `CredentialsModule` class, you should now import the `CredentialsApi` class

Signed-off-by: Ariel Gentile <gentilester@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change PR that introduces a breaking change modularization Tasks related to modularization of the framework
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants