8

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",
    "[email protected]": "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?
9
  • 1
    I wonder if the package can even be install if it's namespaces but has a uses different namespace?
    – NSjonas
    Commented Jun 24, 2020 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. Commented Jun 24, 2020 at 16:57
  • 1
    @RobertSösemann. Just ran into this situation where I had developed an unlocked package for customer orgs (no namespace and I wanted to add this package as a dependency to a managed package. I thought I should check here first. This is frustrating. Is giving the unlocked package a namespace a viable alternative?
    – muchavie
    Commented Dec 1, 2020 at 19:52
  • 1
    Hi @RobertSösemann, I ran into the same thing and I was wondering if you had a chance to find the "best" solution? I wanted to make my Unlocked namespaced package to depend on some OS code, but struggled getting this code into the scratch org where I develop. When I include the code in my project it gets the namespace and I can't reference it without it. If I create a separate package without a namespace then I can't install it. Was the solution for you to just bundle the OS code as part of your package? I understand that's probably the only safe way to use it and depend on it, right?
    – alesremta
    Commented Jul 29, 2021 at 8:49
  • 1
    @RobertSösemann yea I say, but I assumed it meant to include the OS code you depend on in the package that I am creating (be it a Managed or Unlocked one). For a managed package that's fine I guess, unless you have multiple packages depending on the same. It works, but feels wrong.
    – alesremta
    Commented Jul 29, 2021 at 11:14

3 Answers 3

4

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.

3
  • 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. Commented Jun 24, 2020 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? Commented Jun 24, 2020 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
    Commented Jun 24, 2020 at 17:07
4

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="[email protected]:apex-enterprise-patterns/fflib-apex-common.git"

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

git clone "$fflib" "$localFolderapexcommon"

fflibapexmocks="[email protected]: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

3

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

6
  • 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. Commented Jun 24, 2020 at 16:59
  • 1
    @RobertSösemann Wondering what if you pull from the github releases directly or master branch of git than unlocked package? Commented Jun 24, 2020 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? Commented Jun 29, 2020 at 13:10
  • 1
    @RobertSösemann yes sure I will find some time to show you how we can approach this. Commented Jun 29, 2020 at 13:12
  • @MohithShrivastava awesome! Here are the script(s) we normally use: github.com/logiclinegmbh/sfdxproject/blob/trunk/scripts/… Commented Jun 29, 2020 at 13:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .