Execute generic Graph call in SPFx with PnP 3 - graph

So far I have been using the following to execute a request against the Graph API.
import { MSGraphClient } from '#microsoft/sp-http';
const graphClient: MSGraphClient = await context.msGraphClientFactory.getClient();
const uriGetAccessPackageAssignmentRequests = `/identityGovernance/entitlementManagement/accessPackageAssignments/filterByCurrentUser(on='target')?$select=id&$expand=accessPackageAssignmentResourceRoles&$filter=assignmentState ne 'Expired'`;
graphClient.api(uriGetAccessPackageAssignmentRequests).version('beta').get();
This has been working without any problems until I decided to change to #pnp/graph in the newest version (3.4.1).
I can use all the preset calls, but I cannot find a way to execute a generic graph call with a custom endpoint.
In all the tutorials they talk about
import { graph } from "#pnp/graph";
But if I do so, I get the following error -> Module '"#pnp/graph"' has no exported member 'graph'.
As I said, the described way in the documentation of using
import { graphfi, GraphFI, SPFx as graphSPFx } from '#pnp/graph'
export const getGraph = (context?: WebPartContext): GraphFI => {
if (_graph === null && context != null) {
//You must add the #pnp/logging package to include the PnPLogging behavior it is no longer a peer dependency
// The LogLevel set's at what level a message will be written to the console
_graph = graphfi().using(graphSPFx(context)).using(PnPLogging(LogLevel.Warning))
}
return _graph
}
is working fine.
I just cannot find anything on how to do a custom endpoint (like the one above) with pnp v3.
Can anyone help here or do I have to stick to the MSGraphClient for that purpose?

Related

How can I check the actual URL path in Next.js 13?

In head.tsx (I am using AppDir) of each page of my site, I pass canonicalPath (among others) to a server component that renders all <meta> tags.
I want to make a simple development only validation that the canonicalPath supplied is actually the same as the actual current path in the browser and throw an Error if it isn't. I cannot figure out how to do this:
Serverside, the only thing I found is headers() which for some reason contains the hostname but not the path. And besides, it's a dynamic function and will force dynamic rendering.
So I created a client component:
"use client";
import { usePathname } from "next/navigation";
import { LayoutHeadProps } from "./layout-head";
export default function LayoutHeadClient(props: LayoutHeadProps): React.ReactNode {
const path = usePathname();
if (process.env.NODE_ENV === "development") {
if (props.canonicalPath !== path) {
throw new Error(`Actual path does not correspond to canonical path: "${path}" != "${props.canonicalPath}"`);
}
}
return <></>;
}
But this does not work either:
Warning: Cannot update a component (`HotReload`) while rendering a different component (`LayoutHeadClient`). To locate the bad setState() call inside `LayoutHeadClient`
and then it throws the Error because at the time it is evaluated, canonicalPath still evaluates to the previous page. When I later look it up in the source code, it is correct.

The UseSWR hook not working in nextjs component

I am trying to use the useSWR hook to fetch data from an API.
The API and requests works fine but the data is never updating.
Here is the code:
import useSWR from 'swr'
import { SERVER_URL } from '../config';
import axios from 'axios'
const fetcher = url => axios.get(url).then(res => res.data)
export default function MainPageView() {
const { routines, error } = useSWR(`${SERVER_URL}/api/routines`, fetcher, { refreshInterval: 1000 })
return (...The rest of the component)
When using the routines inside I call it like that {routines?routines:[]}
Thank you for your help and sorry for my english :)
Edited:
I will also mention that if i inspect the page with F12 and go to the network tab, I do see the requests being sent and received with the desired data (with response STATUS 304) but it never updates the routines variable.
Try using const { data: routines, error } = useSWR(...), the data returned by the fetcher function is available in the data property
The answer was given by juliomalves
useSWR hook returns 3 states data, loading and error
try something like this
const { data, error } = useSWR(`${SERVER_URL}/api/routines`, fetcher, { refreshInterval: 1000 })
using data
{data?.properties?.map((item)=>...) }

Is it possible to stub meteor methods and publications in cypress tests?

Is it possible to stub meteor methods and publications in cypress tests?
In the docs (https://docs.cypress.io/guides/getting-started/testing-your-app#Stubbing-the-server) it says:
This means that instead of resetting the database, or seeding it with
the state we want, you can force the server to respond with whatever
you want it to. (...) and even test all of the edge cases, without needing a server.
But I do not find more details about that. All I can find is, that when not using the virtual user in the tests to fill the database, it is possible to call API calls on the app, like so:
cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
.its('body')
.as('currentUser')
In my opinion that is not a "stub". It is a method to "seed" the database.
Is it possible to tell cypress to answer a meteor method in the client code like
Meteor.call('getUser', { username: 'jane.lane' }, callbackFunction);
with some data, it would give back in production?
I can only show an example using sinon to stub Meteor method calls:
const stub = sinon.stub(Meteor, 'call')
stub.callsFake(function (name, obj, callback) {
if (name === 'getUser' && obj.username === 'jane.lane') {
setTimeout(function () {
callback(/* your fake data here */)
})
}
})
That would be of corse a client-side stub. You could also simply override your Meteor method for this one test.

firebase serve: From a locally served app, call locally served functions

How can I properly simulate a cloud function locally so that it has all data as when being invoked on firebase servers? (e.g. the context.auth)
I am serving my project with firebase serve, it runs ok on http://localhost:5000/, however, my cloud functions are being called from https://us-central1-<my-app>.cloudfunctions.net/getUser. (The function is not even deployed.)
To avoid XY problem, I am trying to debug my function, but calling it from firebase shell results in context.auth being undefined, same when calling via postman from http://localhost:5000/<my-app>/us-central1/getUser.
This is my ./functions/src/index.ts file
import * as functions from 'firebase-functions'
import admin from 'firebase-admin'
import { inspect } from 'util'
admin.initializeApp()
export const getUser = functions.https.onCall((data, context) => {
console.debug('== getUser called =========================================')
console.log('getUser', inspect(data), inspect(context.auth))
return admin.database().ref('userRights/admin').child(context.auth.uid).once('value', snapshot => {
console.log(snapshot.val())
if (snapshot.val() === true) {
return 'OK'
// return {status: 'OK'}
} else {
return 'NOK'
// return {status: 'error', code: 401, message: 'Unauthorized'}
}
})
})
file ./firebase.functions.ts
import { functions } from '~/firebase'
export const getUser = functions.httpsCallable('getUser')
Consumer ./src/pages/AdminPanel/index.tsx
import { getUser } from '~/firebase.functions'
//...
getUser({myDataX: 'asd'}).then(response => console.debug('response', response))
UPDATE - April/2021
As of April/2021, method useFunctionsEmulator has been deprecated. It is suggested to use method useEmulator(host, port) instead.
Original post:
By default, firebase serve sends queries to CLOUD function instead of localhost, but it is possible to change it to to point to localhost.
#gregbkr found a workaround for that at this github thread.
You basically add this after firebase initialization script (firebase/init.js) in html head.
<script>
firebase.functions().useFunctionsEmulator("http://localhost:5001");
</script>
Make sure to REMOVE it when deploying to SERVER
There is currently no support for local testing of callable functions like this. The team is working on a way for you to specify the URL endpoint of a callable function so that you can redirect it to a different location for testing.
Just found a workaround.
using fiddlers AutoResponder to redirect the function call to the local served function.
step 1
copy the target url of the function from the client
step 2
copy the local served function url
step 3
active the auto respoder and use the following rules
(the second rule is also importent to allow all outher requests
That worked for me, thank you #GorvGoyl!
script src="/__/firebase/init.js?useEmulator=true"></script

How to access custom response values from a page script?

This might sound like a silly question but I have really tried everything I could to figure it out. I am creating a variable and adding it to my response object in custom Express server file like so:
server.get('*', (req, res) => {
res.locals.user = req.user || null;
handle(req, res);
});
Now I want to access this res.locals.user object from all of my pages, i.e. index.js, about.js, etc., in order to keep a tab on the active session's user credentials. It's got to be possible some way, right?
P.S.: Reading some thread on the NextJS Github page, I tried accessing it from my props object as this.props.user but it keeps returning null even when a server-side console.log shows non-null values.
The res object is available on the server as a parameter to getInitialProps. So, with the server code you have above, you can do
static async getInitialProps({res}) {
return { user: res.locals.user }
}
to make it available as this.props.user.

Resources