tl:dr: There is a new library to manage address books & contacts in Solid Pods. Please try it and give feedback.
Hi all,
as part of the solid-data-modules initiative I have built a library that is meant to make it easier for developers to handle address books and contacts in Solid Pods.
For experimentation Iām using a straight-up browser app with .bundle.js dependencies (based on my empty-solid-app) and Iām trying to include your .mjs files. If I get it working Iāll add it to your docs in case there are other people who also donāt want to have a build step in their app.
I noticed that if you do npm install rdflib and then npm install @solid-data-modules/contacts-rdflib it fails, see issue 99
I think this line of work is awesome, and I hope to see a lot more of this in Solid :D. Good job!
Iāve tinkered with the snippet for a bit, and hereās my first impressions:
I like the TypeScript typings, they are helpful and quite easy to follow without looking at the docs. There were some syntax errors (Iāll share them below), but I was able to fix them without much trouble.
Calling createAddressBook worked properly, but it doesnāt seem like it did anything with the type index. Should I do something to register it? I was expecting it to be done out of the box. Basically, I created an address book and then calling listAddressBooks returned empty arrays, so after reloading I wasnāt able to obtain the uri of the bookmark I had created (it was also unintuitive that it asked for a webId when I hadnāt provided one to create an address book).
I noticed itās always creating documents and containers using a random string. For example I passed /contacts/ to create an address book and it created it under /contacts/QBLL34/. Is there a way to specify the exact container name? And maybe get an error if it already existed or something.
Finally, if I were to implement a real app, Iām sure Iād want to add some fields that arenāt covered by the library. Do you have any plans for extending the core fields? For example, if I wanted to add the birthday for a contact, how hard would it be to make it work nicely with the library?
PS: Hereās the syntax errors I found in the snippet:
The second import is missing the s from @solid-data-modules/contacts-rdflib.
The contacts variable doesnāt exist (I suppose it should be module instead).
The createAddressBook method takes containerUri, not container.
The createNewContact method takes contact.phoneNumber, not contact.phone.
Great that you could resolve it yourself and thanks for the compliment. What do you think would have been needed to not run into the issue at all? I tried to improve the docs in that regard here
I adjusted the peer dependencies, this should be fixed with the next release
I am going to fix those good catch. The markdown did not get the latest changes.
This is a tricky one. I am still unsure what user expectations are: Should everything be indexed by default? Should they be asked? How to decide what goes into private and what into public index? I took a look at how SolidOS handles this for address books, and it does not add anything to the type index unless you check one of those āpublic link toā / āprivate link toā boxes:
This is why I did not implement it either. There might be reasons to want to create an address book, but not index it. Another reason is that one would need to pass a WebID when creating an address book. That seemd unintuitive to me.
But: I totally get the confusion this creates regarding listAddressBooks. This actually needs the WebID to find the type indexes, so it would be āsymetricā to pass a WebID to create as well as to list.
I am thinking about changing the interface and put new address books to the private type index by default. Other options like adding it to the public type index or prevent all indexing could be added optionally. What do you think?
I wanted to keep it simple. You already pass a human readable title for the address book. I thought it might be confusing to differ between container name and address book name. I thought about slugifying the title, but this brings other issues, like title and slug diverging when changing the title or accidentally expose a sensitive address book title via the URI. If this is important to you anyway, please raise a feature request on github. It could still be added as an option.
Contact related fields like birthday should definetly be added to the data-module as a first-class citizen in the long run. For now and for more complex or unrelated properties / statements, you can still use rdflib directly. As a consumer of the library you have to create a store / updater / fetcher anyway. The module makes common address book related things easier, but does not take control away from your rdflib usage.
I think itās ok that address books are not listed on the type indexes by default, but I guess Iād improve two things:
In the docs and code examples, make sure to mention the type index and how things can be registered using the library. Otherwise, people may not event be aware that those exist.
If an address book is not registered, Iām not sure how I can retrieve it after reloading. Hard-coding the url doesnāt work, so I guess I should list all the documents in a container and filter the documents containing address books myself? I would also clarify this use case in the docs.
The thing is, that the data module does not have any means to add things to a type index. And I donāt want to add those since type index is not specific to address books. Currently I am thinking it would be best to implicitly add it to the private type index when an optional owner WebID is passed on create.
You will get the uri as the response to create. An app could store It anywhere it likes, e.g. in local storage write it to some document in a pod. But I see how this burdens the developer which is the opposite of what a data module should do. Which brings me back to the approach of choosing a reasonable default and add it to the private type index.
@NoelDeMartin and all who are interested: I published version 0.6.0 of the data module, which now allows to optionally pass a ownerWebId when creating an address book. If so the private type index of that WebID will be updated to include the new address book.
Additionally features to update existing phone numbers and email addresses have been added as well as renaming a contact.
After tinkering with it, there are a couple of issues Iāve found:
I tried to use it with an empty POD, but it didnāt work and I think thatās because it expects the type index to exist. What do you think about that, is that an expectation apps should make? In my apps, Iām currently creating a type index if it doesnāt exist. Which brings me to the next point.
If the type index exists, but itās declared in the profile, it doesnāt work. Now, I understand the rationale behind this, because I am declaring solid:privateTypeIndex in the profile which is probably not the best idea. I think Iām doing this because thatās how it worked before in SolidOS (the document itself is private though, so it shouldnāt be that much of a problem). What your library expects, which seems to be better, is that itās declared in a pim:preferencesFile, which I assume should be private. The thing is that the type-indexes spec is still a draft, so Iām not sure if I should change the way my apps work until thatās stable :/. Also, there is already some data in the wild using that old approach, so maybe the library should support it as well; even if itās just to read data and not to create new type indexes.
I wanted to debug using breakpoints, but I noticed that the source files are not included in the npm package. But the source maps are included, so you probably want to do something about that. I copy&pasted the sources manually and it seems to work, but itās still not working perfectly. Maybe that has something to do with the minification; Iām not sure how you could improve it (to be honest, I donāt think my libraries are perfectly debuggable either ). But at least including the TypeScript sources should be a better experience :).
you are right, the data module does not create type indexes at the moment. The whole type index thing is quite complex and there have been discussions in the data-modules group on how and where to handle them. Since this is not specific to the contacts module I will give it some more thought while working on other data-modules implementation, and see if a common pattern emerges.
correct, the module assumes that the private type index is linked from the preferences file as described in the current version of the type index spec (Type Indexes). But you are probably right that it would be pragmatic to at least read from the other location
it never occured to me to include the sources, but I guess it makes sense for debugging