What steps can be taken to ensure that a second Pinia plugin waits for the completion of the

I am currently developing a Vue application with Pinia as the state manager. I have created two plugins - one for authentication and another to set up my API instance. The second plugin relies on the token obtained from the first plugin.

Upon analyzing the execution order, I noticed that the second plugin runs immediately while the first one is still waiting for the token retrieval. Both plugins are asynchronous functions. Is there a way to adjust this sequence?

Here is the code snippet for my authentication plugin:

export async function authenticationPlugin({ store }: PiniaPluginContext) {
  console.log('starting authentication');
  const msalInstance = store.msalInstance as PublicClientApplication;

  try {
    console.log('starting await for silent sso')
    const { idToken } = await msalInstance.ssoSilent(store.msalRequest);
    console.log('signed in using silent sso and fetched id token');
    const account = msalInstance.getAllAccounts()[0];
    msalInstance.setActiveAccount(account);
    console.log('active account set');
    store.idToken = idToken;
    console.log('id token stored in store');
  } catch (error) {
    if (error instanceof InteractionRequiredAuthError) {
      const { idToken } = await store.msalInstance.acquireTokenPopup(store.msalRequest);
      store.idToken = idToken;
    }
  }
}

And here is the implementation of my API plugin:

export async function apiPlugin({ store }: PiniaPluginContext) {
  console.log('starting api plugin');
  const msalInstance = store.msalInstance as PublicClientApplication;

  console.log('setting up subscription');
  store.$subscribe((mutation, store) => {
    // @ts-ignore
    if (mutation.events.key === 'idToken') {
      console.log('inside subscription');
      store.api = new Api(new Configuration({
        basePath: config.BASE_PATH,
        // @ts-ignore
        accessToken: mutation.events.newValue
      }));
      console.log('end of subscription');
    }
  });

  const api = new Api(new Configuration({
    basePath: config.BASE_PATH,
    accessToken: store.idToken
  }));

  console.log('api instance made');

  // @ts-ignore
  api.axios.interceptors.request.use(async (config) => {
    const tokenResponse = await msalInstance.acquireTokenSilent(store.msalRequest);

    if (tokenResponse.expiresOn!.getTime() < new Date().getTime()) {
      console.log('expire?');
      await msalInstance.ssoSilent(store.msalRequest);
      const { idToken } = await msalInstance.acquireTokenSilent(store.msalRequest);

      config.headers.Authorization = `Bearer ${idToken}`;
    }

    return config;
  });

  console.log('interceptor set');

  store.api = api;

  console.log('api added to store');
}

However, when the component utilizing the API for making calls is rendered, the token seems to not be set in the API instance for some reason, even though the idToken has been successfully populated in the store. Any suggestions on how to proceed would be greatly appreciated.

Answer №1

Successfully resolved my issue using a unique approach.

To tackle my problem, I created two plugins. The first plugin requests a token and saves it in the store. Only after the token is retrieved should the second plugin initiate its tasks.

In order to achieve this, I made modifications to the second plugin as shown below:

export async function apiPlugin({ store }: PiniaPluginContext) {
 store.$subscribe(({ events }, store) => {
  // @ts-ignore
  if(events.key === "token") {
   // execute your second plugin
  }
 })
}

This might not be the most efficient method, but it worked for me.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Combining React Context and Typescript using a Custom Hook

I have been working on a context provider in React and Chakra-UI, but I seem to be facing some issues: import { useBoolean } from "@chakra-ui/react" import { createContext } from "react" const MobileContext = createContext<typeof us ...

The parameter type 'Object' cannot be assigned to the parameter type 'JSON' in the HttpClient GET method

Hey there! Currently, I'm deep into developing an Angular 6 + Flask application and I've encountered a bit of a snag: Error TS2345: Argument of type 'Object' is not assignable to parameter of type 'JSON'. This issue arises w ...

Connecting a Node server with Vue socket: A step-by-step guide

I'm currently using vue.js (Laravel) to connect to my chat node server. While the socket connection is working fine, I'm facing issues with emitting data with a function. var socket = io.connect('http://localhost:3000/api/message'); so ...

Problem with exporting default class in Babel/Jest conflict

Currently, I am facing a challenge while testing the code using jest. The issue seems to be related to babel, especially regarding the export of a default class. Here is an example of the code causing the problem... export default class Test { get() { ...

What could be the reason for the list being undefined even though I explicitly defined it within the <script setup> section of my Nuxt 3 Project?

I am currently working on a Nuxt 3 Project and have created a component that generates a variable amount of elements. When calling the element, it is passed an array as a parameter. In the script setup, I define this array as 'list' and intend to ...

Using Vue to download a file by linking to the href and incorporating a Vuetify v-btn

Having recently started learning Vue.js, I am currently encountering difficulty with a seemingly simple task. My goal is to add a Vuetify button to my webpage that allows users to download a file. However, I am struggling with getting the href attribute t ...

"I am having trouble calling the useStyles function in React with Typescript and Material-

There seems to be a problem with calling the useStyles function as it is throwing the following error message: This expression is not callable. Type 'never' has no call signatures.ts(2349) const useStyles: never Below is the complete code snip ...

Transforming text colors dynamically using Vue.js

Here is an Angular code snippet: <div [style.color]="'#' + prod.id.substring(0,6)"> <small>{{ prod.id }}</small> </div> Now I want to create a similar code using vue.js. ...

Issue encountered while attempting to utilize the useRef function on a webpage

Is it possible to use the useRef() and componentDidMount() in combination to automatically focus on an input field when a page loads? Below is the code snippet for the page: import React, { Component, useState, useEffect } from "react"; import st ...

Is it possible to determine when a Vue.js component instance has been successfully mounted?

Can we access a boolean in each component instance to determine when a component has been mounted? Something along the lines of: <template> <div> <span v-if="$mounted">I am mounted</span> <span v-if="$created">I am ...

Displaying a Vue.js component only when a specific API condition is satisfied: A step-by-step guide

After experimenting with v-if, I encountered the following error: Uncaught TypeError: Cannot read property '0' of undefined I have identified the issue to be related to the fact that the code cannot execute without the data being fetched first. ...

How can I properly include DefinitelyTyped TypeScript definition files in a .NET Core project?

Previously, under asp.net for .net framework, I utilized NuGet to incorporate TypeScript type definitions from third-party libraries (*.d.ts files) provided by DefinitelyTyped. However, with the shift to .NET Core, it seems that NuGet is no longer recommen ...

Only encountering a 401 error with API requests in the production environment

Having an issue where Laravel 6 API requests are functioning smoothly on the local server, but encountering a 401 error on the remote server. Both servers are nginx-driven with php-fpm setup. Authentication is done using Laravel Passport ...

Unique TypeScript code snippets tailored for VSCode

Is it possible to create detailed custom user snippets in VS Code for TypeScript functions such as: someArray.forEach((val: getTypeFromArrayOnTheFly){ } I was able to create a simple snippet, but I am unsure how to make it appear after typing an array na ...

Cross-origin requests are being blocked when attempting to import PHP scripts

I'm facing challenges with configuring CORS to allow cross-origin requests from imported PHP scripts. My website has two subdomains: 'php.<my wesbite>.com' where I host PHP scripts, and 'admin.<my website>.com' where I ...

How can you iterate over an array of objects that are sent to a component using Vuex Store and a computed property?

I am currently working on a project to familiarize myself with Vuex. As part of this project, I am setting up an array of objects in my store as shown below: Vuex Store: import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); export default new ...

How do you structure `en.js` or `ja.js` files for lazy loading in vue-i18n?

What is the correct format for lazy loading en.js or ja.js? The code below is not working: // en.js export default { title: 'Title', greeting: 'How are you' }; and import Vue from 'vue'; import Inven ...

Mastering Angular Service Calls in TypeScript: A Comprehensive Guide

In the midst of my TypeScript angular project, I am aiming to revamp it by incorporating services. However, I have encountered an issue where when calling a function within the service, the runtime does not recognize it as the service class but rather the ...

Exploring nested contexts in react testing library with renderHook

This is a sample code snippet in TypeScript that uses React and Testing Library: import React, { FC, useEffect, useMemo, useState } from 'react'; import { renderHook, waitFor } from '@testing-library/react'; interface PropsCtx { inpu ...

Assist with the integration of Pug block folding within Vue components on Visual Studio Code

How can VS Code be configured to enable folding blocks within Pug when utilized in Vue single-file components? For example: <template lang="pug" ... </template> ...