5

I build Managed Packages (with namespaces) for my ISV customers. I use external libraries and Open-Source frameworks like fflib or apex-domainbuilder and find dependency management gets more cumbersome the more external libs I use.

I decided to use Unlocked Packages to bundle and manage such dependencies better. Here are the sfdx-project.json files for the app and for a sample dependency.

sfdx-project.json of the Managed Package (Customer DevHub)

{
    "namespace": "NAMESPACE",
    "sfdcLoginUrl": "https://login.salesforce.com",
    "sourceApiVersion": "48.0",
    "packageDirectories": [{
        "path": "force-app",
        "versionNumber": "1.1.0.NEXT",
        "package": "myManagedPackage",
        "dependencies": [
            {
            "package": "noNsUnlockedDependency@LATEST",
            }
        ]
    }],
    "packageAliases": {
        "noNsUnlockedDependency": "0Ho4A000000fxXpSAI",
        "noNsUnlockedDependency@LATEST": "04t4A000000onRXQAI",
    }
}

sfdx-project.json of the Required Library (Developer Devhub XYZ)

{
    "packageDirectories": [{
        "path": "force-app",
        "default": true,
        "package": "apex-domainbuilder",
        "versionName": "Summer '20",
        "versionNumber": "1.1.0.NEXT"
    }],
    "namespace": "",
    "sfdcLoginUrl": "https://login.salesforce.com",
    "sourceApiVersion": "48.0",
    "packageAliases": {
    "noNsUnlockedDependency": "0Ho4A000000fxXpSAI",
    "noNsUnlockedDependency@1.1.0-1": "04t4A000000onRXQAI"
    }
}

As the sample dependency is created from another DevHub and/or doesnt have a namespace I can't install them.

ERROR running force:package:install: You cannot install an unlocked package without a namespace into an org with a namespace.

  1. Why is that a requirement?
  2. Is it because the libraries use a different DevHub (the one of our company) than the Managed package (the one of the customer)?
  3. I don't want (I read here that this has some problems and limitations) or can't (because they are not my repos) add namespaces.
  4. What will I win and lose when adding namespace to the dependencies?
  • 1
    I wonder if the package can even be install if it's namespaces but has a uses different namespace? – NSjonas Jun 24 at 16:09
  • Absolutely, how would I every be able to use the fflib and another lib on a customer managed package without that being possible. – Robert Sösemann Jun 24 at 16:57
3

Why is that a requirement?

Because it is intended that those packages will become part of a Classic Managed Package (1GP). This restriction prevents you from accidentally creating dependencies on a package that won't become part of the namespace and Managed Package.

Is it because the libraries use a different DevHub (the one of our company) than the Managed package (the one of the customer)?

No, it's just as explained above. You can't create managed dependencies on unmanaged packages, which could cause things to break.

I don't want (I read here that this has some problems and limitations) or can't (because they are not my repos) add namespaces.

They need to be, or you can't build dependencies on them. Also, the linked FAQ is very out of date (2018). Things have changed since then. There are still some limitations, but they are very close to parity with 1GP at this point. You shouldn't be worried about the limitations too much at this point.

What will I win and lose when adding namespace to the dependencies?

You get most of the properties of 1GP (Classic Managed Packages) by adding namespaces, including upgradeability, protected components, etc. I suggest you go through the documentation and read about the latest updates. Most documents from 2018 or 2019 are outdated and the information therein should not be relied on.

| improve this answer | |
  • 1) Should not apply. I dont want to install them in the Packaging org. Just namespaced scratch orgs. In the package its just a soup of mixed metadata. – Robert Sösemann Jun 24 at 17:01
  • 2) Good. 3) Are you saying there is no reason to not put namespaces on all my open source library repos or repo forks? Is there an up-to-date faq about limitations elsewhere? 4) Last but not least: Have you seen people use Unlocked Packages to organize external libs as I plan to do? – Robert Sösemann Jun 24 at 17:03
  • 1
    @RobertSösemann (1) You could still end up creating dependencies, which is why I think this restriction exists. (3) Not sure about a FAQ, the docs are the primary resource now. (4) We're doing this internally, but it's not namespaced. I haven't had a chance to 2GMP/ISV in a good six years or so now, so I don't know how they're supposed to work. I'd imagine that most are probably not doing this. Maybe ask on Twitter to Wade Wilson or someone who could be more definitive about it? – sfdcfox Jun 24 at 17:07
2

My gut feeling is that you're facing an uphill battle here. To answer a question with a question: What are you hoping to gain by using unlocked packaging to manage your dependencies?

Dependency management is one of the things that 2GP is worst at.

If you just want a clear separation between the OS libraries and the rest of the code, then an alternative may be to use SFDX format in your main project, then divide the project into top-level folders. You then check the whole thing in/out of source control.

So you end up with a folder structure like this:

  • force-app/myApp - My custom code, containing classes/, triggers/ etc.
  • force-app/fflib - The FFlib code, again with subdirectories in the normal format
  • force-app/apex-domainbuilder - The domain builder

Your sfdx-project.json then just has to target force-app to build the whole project.

See this outstanding answer about the folder structure: Two SFDX project folder structure questions

And also the developer blog here: https://developer.salesforce.com/blogs/2018/06/working-with-modular-development-and-unlocked-packages-part-2.html

| improve this answer | |
  • I already do that. But its not about folder seperation. I want to make sure my zillion of customer apps get upgraded to the latest lib versions always. That can only be done when on every scratch org (re) creation the LATEST is pulled in automatically. – Robert Sösemann Jun 24 at 16:59
  • 1
    @RobertSösemann Wondering what if you pull from the github releases directly or master branch of git than unlocked package? – Mohith Shrivastava Jun 24 at 17:06
  • @MohithShrivastava after a week of frustration I actually think your idea is the best just pull the latest trunk of those libs into my project from the createScatchOrg.sh. Would you be so kind a create an answer showing how exactely? – Robert Sösemann Jun 29 at 13:10
  • 1
    @RobertSösemann yes sure I will find some time to show you how we can approach this. – Mohith Shrivastava Jun 29 at 13:12
  • @MohithShrivastava awesome! Here are the script(s) we normally use: github.com/logiclinegmbh/sfdxproject/blob/trunk/scripts/… – Robert Sösemann Jun 29 at 13:14
2

One viable solution would be to directly clone the source code from git repo of these open source libraries into your project folder.

You can subfolders under the main folder as discussed by one of the answers

  • force-app/myApp - My custom code, containing classes/, triggers/ etc.
  • force-app/fflibapexcommon - The FFlib code, again with subdirectories in the normal format
  • force-app/fflibapexmocks - The domain builder

Here is a sample bash script showing how to achieve this,

#/bin/bash

fflib="git@github.com:apex-enterprise-patterns/fflib-apex-common.git"

localFolderapexcommon="/Users/myname/dev/force-app/fflibapexcommon"

git clone "$fflib" "$localFolderapexcommon"

fflibapexmocks="git@github.com:apex-enterprise-patterns/fflib-apex-mocks.git"

localfolderapexmocks="/Users/myname/dev/force-app/fflibapexcommon"

git clone "$fflibapexmocks" "$localfolderapexmocks"

These assume SSH but you can also switch to HTTPS version as well but using the right command.

Note it is still important to put these dependencies in the config JSON in proper order in which you want to push these to the salesforce org.

Example first push apex-mocks before the apex commons.

Note you can further externalize this by maintaining a JSON or text file where you can list the git repo URL and its corresponding local path.

If you prefer this via SFDX plugin than bash script, you can check shanes custom-designed command here

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.