pnpjs icon indicating copy to clipboard operation
pnpjs copied to clipboard

Version 4 Planning

Open patrick-rodgers opened this issue 2 years ago • 22 comments

Hello!

The PnPjs core team is discussing version 4 of PnPjs. No big changes planned for this go-round, just improvements and lots more coverage for Microsoft Graph.

We'd love to hear from all of you about your love/hate/wish was easier list in v3 to help guide our thinking for v4. The more detail you can share the better so we can understand your idea.

We setup a board so you can view our current thinking.

Please share your feedback as a comment below!

Thanks,

🐇🐇🐇 @bcameron1231, @juliemturner, @patrick-rodgers

patrick-rodgers avatar May 15 '23 14:05 patrick-rodgers

Something that would be really cool! - a fluent way to write the filter query

So "title eq 'test'" becomes something like .filter(textField("title").equals("test")) - CamlJS does this awesomely for CAML!

Thanks for all the awesome work you all are doing! 🙌

Tanddant avatar May 15 '23 16:05 Tanddant

Something that would be really cool! - a fluent way to write the filter query

So "title eq 'test'" becomes something like .filter(textField("title").equals("test")) - CamlJS does this awesomely for CAML!

Thanks for all the awesome work you all are doing! 🙌

I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...

juliemturner avatar May 15 '23 18:05 juliemturner

I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...

Dates, booleans (do you write true/false or 1 and 0), lookups, maybe even things like "in date rage" - also to bring forward some of the lesser known options like startsWith

Loads of awesome potential, but maybe also a bigger undertaking 😊

Tanddant avatar May 16 '23 12:05 Tanddant

I agree with this idea if it can happen as it would be especially useful to have helper functions here for things like dates...

Dates, booleans (do you write true/false or 1 and 0), lookups, maybe even things like "in date rage" - also to bring forward some of the lesser known options like startsWith

Loads of awesome potential, but maybe also a bigger undertaking 😊

I love this idea, and when it has come up in the past I've suggested it would be a great project for someone to undertake as a separate library. We can def take a look at it in our planning and see where it falls. Thanks for the suggestion!

patrick-rodgers avatar May 16 '23 14:05 patrick-rodgers

Please allow getting and setting lists from any site collection the easy way you had it in version 2... The whole business of changing the context with: export const getSP = (context?:WebPartContext ): SPFI => { if (_sp === null && context !== null) { _sp = spfi().using(SPFx({ pageContext: context.pageContext })); _context = context; } return _sp; }; Is cumbersome and in 3.18 causes bunch of TypeScript errors about not being null. We like simple :-)

Ofer-Gal avatar Oct 02 '23 11:10 Ofer-Gal

Please allow getting and setting lists from any site collection the easy way you had it in version 2... The whole business of changing the context with: export const getSP = (context?:WebPartContext ): SPFI => { if (_sp === null && context !== null) { _sp = spfi().using(SPFx({ pageContext: context.pageContext })); _context = context; } return _sp; }; Is cumbersome and in 3.18 causes bunch of TypeScript errors about not being null. We like simple :-)

@Ofer-Gal, I tend to just do

const sp = spfi().using(SPFx(this._Context));
const otherSite = spfi(<OtherSiteURL>).using(AssignFrom(sp.web));

Any reason that dosen't work for you? Gives me access to the current web, but also any other web the user has access to

Tanddant avatar Oct 02 '23 11:10 Tanddant

That's a good one to share @Tanddant ... my preference is below which is the most similar to v2 method.

const web = Web([sp.web, {Other Web URL}]);

Here are all the options: https://pnp.github.io/pnpjs/getting-started/#connect-to-a-different-web

juliemturner avatar Oct 02 '23 13:10 juliemturner

@Tanddant I use hooks so this._Context does not exist. @juliemturner I tried: const projWeb: IWeb = Web([sp.web, { window.location.origin + "/Teams/" + projectNumber}]); but TypeScript says: Argument of type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to parameter of type 'SPInit'. Type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to type 'ISPQueryable | [ISPQueryable, string]'. Type '[any, { window: Window & typeof globalThis; "": string; }]' is not assignable to type '[ISPQueryable, string]'. Type at position 1 in source is not compatible with type at position 1 in target. Type '{ window: Window & typeof globalThis; "": string; }' is not assignable to type 'string'.ts(2345)

Where should sp come from?

Ofer-Gal avatar Oct 02 '23 15:10 Ofer-Gal

@Ofer-Gal - The second paramater is a string, try:

const projWeb: IWeb = Web([sp.web, `${window.location.origin}/Teams/${projectNumber}`])

As for my solution, the context I'm referencing is the WebPartContext, I've just passed it to my provider class, that's available in the root of your Web Part as this.context, from the sample you have it would just be

const sp = spfi().using(SPFx(context));
const otherSite = spfi(<OtherSiteURL>).using(AssignFrom(sp.web));

Or with @juliemturner's admittedly more sleek approach

const sp = spfi().using(SPFx(context));
const OtherWeb = Web([sp.web, <OtherSiteURL>])

Tanddant avatar Oct 02 '23 15:10 Tanddant

Works great thanks!

Ofer-Gal avatar Oct 03 '23 09:10 Ofer-Gal

@juliemturner or @patrick-rodgers

Is anyone looking to the filter query builder? - I would love to collaborate on it, I have a starting point that work for the most basic things

  • TextField
    • equals
    • not equals
  • Number, Date
    • equals
    • not equals
    • greater than
    • greater than equals
    • less than
    • less that equals

But ideally I would love a second opinion, and maybe someone with more insights into PnPJS to be able to help out

Tanddant avatar Nov 20 '23 13:11 Tanddant

@Tanddant - Yes, @bcameron1231 got quite a ways on it but as a team there are some things that weren't exactly the way we'd want them to be, I think Beau could go into more detail, but it was around nested filters I believe

Here's his PR WIP: https://github.com/pnp/pnpjs/pull/2781

juliemturner avatar Nov 20 '23 13:11 juliemturner

Hey @Tanddant definitely take a look at the PR Julie linked.

It's a bit crude at the moment and needs work, but it's my first exploration at possibly using Lamba type expressions instead. While Camljs is great, I personally prefer the look of a lambda expressions rather than consecutive chaining -- from a readability perspective.

Inside that branch, you'll see what I've done to handle scenarios like Number/Date versus Text field, specifically in the fomatValue() method within spqueryable. The reason I opted for an internal check/conversion on types is to make it easier for the consumer of the library... so they don't have to think about field types.

I'm very open to improving this, and certainly open to alternatives all together.

bcameron1231 avatar Nov 20 '23 14:11 bcameron1231

Hi, I hope, its not completly off topic. I just come across limitation to query length. Query is limited to 160 characters.

  1. could be there an info about too long url? Happens usually with multiple filter conditions.
  2. automatically convert GET to POST with CAML format. I'm not sure it would be possible do that, but would be nice, right?

m0jimo avatar Dec 08 '23 15:12 m0jimo

@m0jimo - I think there is some confusion. The URL length is certainly a thing but it's a different thing than the overall length. So, one of the common ways to work around the URL length is to use alias parameters and we support that (https://pnp.github.io/pnpjs/sp/alias-parameters/). The second option if you go over the ~2000 character length (different for different browsers) is to use CAML queries because that would be in the post body, but we would not do that conversion for you. We do however support you doing it with the renderListDataAsStream or the getItemsByCAMLQuery methods.

juliemturner avatar Dec 08 '23 16:12 juliemturner

Thanks @juliemturner for provided links and ideas. I made a mistake in filter query which was not caused by its length. I'm aware of CAML support in PnpJs. I also found a parsers for OData filter, so I should be able to convert it to CAML myself in case it overcomes its length.

m0jimo avatar Dec 11 '23 06:12 m0jimo

What about SharePoint alerts? We built our own custom document library UI web part using the files/folders PnP JS API but it doesn't have anything for alerts. We have a button on the page where they can manage alerts without having to use the backend SharePoint pages.

We had to create Azure functions which call the PnP PowerShell APIs to get/add/delete alerts. I wasn't sure if that's not possible to add to PnP JS or if it's just something that has never been added. It would be nice if we could get rid of all our Azure functions and be able to use PnP JS for that.

kbeeveer46 avatar Jan 19 '24 16:01 kbeeveer46

@kbeeveer46 - "Alerts" is a bit vague, I can think of 2 or 3 different things you might mean.

If you want to submit an enhancement request and give us details of what specific endpoints you're referencing we might be able to help but based on what you're describing it might be that the limitation is what you can do with delegated vs application level permissions. If the api endpoint was supported with delegated permissions then you wouldn't have to use an azure function... if you're using the azure function because that's how you're running PowerShell then if you can articulate what PowerShell commands you're referencing specifically I suspect you can do this already in the client side code, but maybe only with an extension method.

juliemturner avatar Jan 19 '24 19:01 juliemturner

@juliemturner When you're in a document library in SharePoint there's a set of buttons at the top like upload, delete etc. There's also a button that lets you set up alerts if anything has been added/changed/deleted from the library. I put a screen shot below.

Is there a way to manage (add/edit/delete) these using PnP JS? In PnP PowerShell they have the following cmdlets. I created Azure Functions that are called via http requests that run these cmdlets and return a response since I am not aware of another way to add/edit/delete alerts. We are using SharePoint online as a client portal so we don't want to make our clients use the "backend" pages of SharePoint like in my screen shot below. We wrote a custom document library web part that has an alert manager inside of it that does the same thing as the backend pages but with a better UI.

https://pnp.github.io/powershell/cmdlets/Get-PnPAlert.html https://pnp.github.io/powershell/cmdlets/Add-PnPAlert.html https://pnp.github.io/powershell/cmdlets/Remove-PnPAlert.html

image

kbeverforden avatar Jan 19 '24 21:01 kbeverforden

@juliemturner What's the opinion on "undocumented APIs"?

I've been reverse engineering the news API, now not quite sure what to do with that 😅 - if it doesn't fit here I'll do an SPFx sample on it instead, the API isn't officially documented, so it might change and break, but it seemingly hasn't changed for a few years

Tanddant avatar Jan 24 '24 21:01 Tanddant

@Tanddant well that's a good question. We have in the past reverse engineered APIs (pages forex) and used them in the library, but that isn't the best path forward as things can change/break unexpectedly. Depending on the API we can weigh the pros/cons. In my job-job I have to say, don't do that. But wearing my PnPjs hat I understand that sometimes folks need to solve issues we haven't fully supported in the service yet and generally encourage finding ways to solve the customer need.

patrick-rodgers avatar Jan 29 '24 15:01 patrick-rodgers

@patrick-rodgers

Here's my current work: https://github.com/Tanddant/pnpjs/tree/v4-ODataFilterQuery

export interface IDepartment {
    Id: number;
    Manager: IDepartment;
    Alias: string;
    HasSharedMailbox: boolean;
    DepartmentNumber: number;
}

export interface IEmployee {
    Id: number;
    Age: number;
    Firstname: string;
    Lastname: string;
    Employed: boolean;
    Department: IDepartment;
    DepartmentId: number
    Manager: IEmployee;
    Created: Date;
    SecondaryDepartment: IDepartment[];
    SecondaryDepartmentId: number[];
}

const r = await sp.web.lists.getByTitle("Employees").items.filter<IEmployee>(
    Or(
        And(
            TextField("Firstname").Equals("Dan"),
            TextField("Lastname").Contains("Tof"),
            NumberField("Age").GreaterThan(25),
            BooleanField("Employed").IsTrue(),
            DateField("Created").IsBetween(new Date(2000, 1, 1), new Date(2024, 12, 31)),
            TextField("Firstname").Equals("Dan"),
        ),
        And(
            TextField("Firstname").In(["Beau", "Bob", "Dan"]),
            TextField("Lastname").Equals("Cameron"),
            NumberField("Age").LessThan(35),
            BooleanField("Employed").IsTrue(),
            LookupField<IEmployee, IDepartment>("Department").TextField("Alias").Equals("Intern Management"),
        ),
    )
)()

It works, but I can't start my code unless I comment out this stuff ^ - and then bring it back while running the code

Tanddant avatar Feb 22 '24 15:02 Tanddant

There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.

HughAJWood avatar Mar 26 '24 12:03 HughAJWood

There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.

We'd certainly welcome a community sample, but it's hard to support making samples for all the possible SDK/lang/framework variants in the world. If it has its own fetch API and it matches the browser's/node-fetch than the behavior should be trivial. You can use our node fetch behavior as an example.

patrick-rodgers avatar Mar 28 '24 00:03 patrick-rodgers

Indeed, there needs to be some work first looking at v3 though, maybe to make custom behaviours easier or you remove shim dependencies as it's currently not compatible without changes to the core sadly

On Wed, 27 Mar 2024, 21:53 Patrick Rodgers, @.***> wrote:

There are some slightly coupled parts to nodejs that don't work in React Native due to mobile only view. While I can see it is possible with behaviours to do this maybe, I've yet to come across a sample of using things like React Native Fetch instead. I know work on the React Native Components is underway so I think this would be a nice round solution for React Native components, especially as you can now build React Native Apps via cli for Windows as well.

We'd certainly welcome a community sample, but it's hard to support making samples for all the possible SDK/lang/framework variants in the world. If it has its own fetch API and it matches the browser's/node-fetch than the behavior should be trivial. You can use our node fetch behavior as an example https://github.com/pnp/pnpjs/blob/version-4/packages/nodejs/behaviors/fetch.ts#L10 .

— Reply to this email directly, view it on GitHub https://github.com/pnp/pnpjs/issues/2678#issuecomment-2024214443, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABIQ5ACI6KXO2VNNLLKLL33Y2NSYDAVCNFSM6AAAAAAYCKC5FGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRUGIYTINBUGM . You are receiving this because you commented.Message ID: @.***>

HughAJWood avatar Mar 28 '24 01:03 HughAJWood

@HughAJWood - I am unfamiliar with react native. If there are things in pnpjs that block it from working, please do open an issue and describe them so we can review and see if/what changes we can make to accomodate. With v4 coming soon it would be a good time to review.

patrick-rodgers avatar Mar 28 '24 15:03 patrick-rodgers

I will do that, I'll do some discovery and testing and submit thanks

On Thu, 28 Mar 2024, 12:28 Patrick Rodgers, @.***> wrote:

@HughAJWood https://github.com/HughAJWood - I am unfamiliar with react native. If there are things in pnpjs that block it from working, please do open an issue and describe them so we can review and see if/what changes we can make to accomodate. With v4 coming soon it would be a good time to review.

— Reply to this email directly, view it on GitHub https://github.com/pnp/pnpjs/issues/2678#issuecomment-2025501170, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABIQ5AD62ISCYISJ72SBXUDY2QZLLAVCNFSM6AAAAAAYCKC5FGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDAMRVGUYDCMJXGA . You are receiving this because you were mentioned.Message ID: @.***>

HughAJWood avatar Mar 28 '24 17:03 HughAJWood

Thank you everyone for the great feedback and ideas for version 4. As we are getting close to launch I encourage everyone to try out the nightly builds for v4 and report any issues here in the list as normal. And of course please continue to share ideas on how we can continue to improve the library!

Thanks!

patrick-rodgers avatar Apr 04 '24 17:04 patrick-rodgers

This issue is locked for inactivity or age. If you have a related issue please open a new issue and reference this one. Closed issues are not tracked.

github-actions[bot] avatar Apr 07 '24 00:04 github-actions[bot]