Namespaced Unlocked Packages are retrieved without namespace

Issue #1843 resolved
Aidan Harding created an issue

If I install a namespaced unlocked package into a dev org or sandbox, and then do a metadata retrieve with IC, it retrieves the classes from the package. The problem is that the source code for those classes doesn’t include the namespace.

For example, if I install our Nebua Core package, 04t6M000000km6rQAA, into a clean dev org and then retrieve, I get files such as nebc__Function.cls which contains

global interface Function {
    Object call(Object o);
}

Note the lack of a nebcnamespace.

The result of this is that the symbol table contains two definitions of Function. One with a namespace in the OST, and one without in the local source. So, I get code-completion suggestions like this:

Which is mildly inconvenient, but no big deal. However, this seems to confuse the inspections further down the line when I try to use my custom class. For example I may write:

public with sharing class MyClass {

    private class MyFunction implements nebc.Function {
        public Object call(Object o) {
            return null;
        }
    }

    private static void usesFunction() {
        new nebc.Composition(new MyFunction());
    }
}

That is, I’ve implemented nebc.Function locally, and then called a method from the nebc namespace which expects a nebc.Function. Apex is totally happy with this, but code inspections flag it as an error:

I worry that this might be a hairy one and/or Salesforce’s fault because viewing that class through the setup UI also shows it with no namespace.

Official response

  • Scott Wells repo owner

    Okay, I've just committed a partial fix for this, in this case to prohibit subscription to/retrieval of/etc. most of the contents of installed unlocked packages with namespaces. I basically allow the user to work with the same metadata types that are considered subscriber-editable in installed managed packages and no more.

    I did investigate just making IC2 support local copies of retrieved Apex (and other metadata) files from namespaced unlocked packages, but the issue is that while the retrieved copy does add a namespace qualification to the retrieved filename, e.g., namespace_TypeName.cls, no internal references are qualified. So if the implementation of TypeName references OtherTypeName from the same namespace, it appears in the retrieved source as OtherTypeName instead of TypeName. This can create resolution conflicts with local source that might contain its own TypeName, much less if you had multiple such packages installed and retrieved. Hopefully that makes sense... Ideally retrieved metadata for these types of packages would be segregated into namespace-scoped areas of the project so that resolution occurs locally first, therefore removing the need for explicit qualifications on internal references.

    So the next build will at least keep you from getting into the situation that was causing you grief. We'll see if there's much of a demand for installing unlocked packages with namespaces, retrieving the metadata from those packages, and working with it locally. If so...well...I'll deal with that when it's a real issue for folks.

Comments (7)

  1. Scott Wells repo owner

    Hmmm...this is interesting. So just to be clear, this happens when you retrieve a type from that unlocked package and not based on how that unlocked package is rendered into the OST, correct? Right now retrieved metadata only assumes the namespace of the org associated with the project's(/module's) connection. There's currently no distinction for metadata from installed unlocked packages with namespaces.

    As a workaround, what if instead of retrieving that metadata you remove it locally and regenerate your OST? Is the metadata for that installed unlocked package rendered into the OST with the correct namespace. Can you tell I haven't done this yet?!

    For convenience, is this a package I could install? That would allow me to try this out a bit without having to create a namespaced unlocked package first.

  2. Aidan Harding reporter

    Hi Scott,

    Yes, that’s right. It’s only about the retrieved code, not about the OST. Which is why I only see it in sandboxes, not in scratch orgs.

    It’s all fine if I don’t retrieve the unlocked package metadata. When I first create the project, it doesn’t fetch the unlocked package files. It only does that on a manual fetch. And it’s me being a little lazy and not filtering out the namespaced stuff. That might be a good solution for IC, to just stop it from ever fetching namespaced unlocked code. You can’t edit it here in the sandbox anyway, and it’s already in the OST.

    It’s a particular problem when I have a sandbox containing both namespaced (typically our consultancy libraries) and non-namespaced (customer’s modular features) together. I have to do a manual fetch to get the non-namespaced bit, and that defaults to pulling in the namespaced stuff too.

    By all means install the package id 04t6M000000km6rQAA from above. It contains the classes in my code example.

  3. Scott Wells repo owner

    Thanks, Aidan, both for confirming my thoughts and for providing access to a package to use for testing.

    Given the assumptions that IC2 makes about the relationship between namespaces and local project/module metadata, you're probably right that blocking retrieval of metadata from installed packages with namespaces is probably the correct...and certainly easiest...way to prevent this. Otherwise I'd need to have a way to partition retrieved metadata from namespaced unlocked packages and tag it with the appropriate namespace. Certainly doable, but likely not a small change.

    I'll play with this a bit next week and let you know where I land.

  4. Scott Wells repo owner

    Okay, I've just committed a partial fix for this, in this case to prohibit subscription to/retrieval of/etc. most of the contents of installed unlocked packages with namespaces. I basically allow the user to work with the same metadata types that are considered subscriber-editable in installed managed packages and no more.

    I did investigate just making IC2 support local copies of retrieved Apex (and other metadata) files from namespaced unlocked packages, but the issue is that while the retrieved copy does add a namespace qualification to the retrieved filename, e.g., namespace_TypeName.cls, no internal references are qualified. So if the implementation of TypeName references OtherTypeName from the same namespace, it appears in the retrieved source as OtherTypeName instead of TypeName. This can create resolution conflicts with local source that might contain its own TypeName, much less if you had multiple such packages installed and retrieved. Hopefully that makes sense... Ideally retrieved metadata for these types of packages would be segregated into namespace-scoped areas of the project so that resolution occurs locally first, therefore removing the need for explicit qualifications on internal references.

    So the next build will at least keep you from getting into the situation that was causing you grief. We'll see if there's much of a demand for installing unlocked packages with namespaces, retrieving the metadata from those packages, and working with it locally. If so...well...I'll deal with that when it's a real issue for folks.

  5. Log in to comment