Search code examples
angulartypescriptazure-devopsazure-devops-rest-apiazure-devops-extensions

Angular10 DevOps Extension RestApi


I found this very helpful github project which is a proof of concept to make angular work in an extension of Azure DevOps. Everything works fine until i want to use the build in rest api's like "VSS/Service" or "TFS/VersionControl/GitRestClient". I found out that when i add to the includes from the tsconfig.app.json my visual studio codium ide recognizes the types in my component with import { VssService } from 'VSS/Service'; but when i try to build the file with ng build the following error comes up:

Module not found: Error: Can't resolve 'VSS/Service'

I tried to add to angular.json scripts[] the VSS.SDK.min.js file which didn't change anything.

I see that over the init-vss-angular.js VSS gets initialized but i have no idea how to get the rest service to use in my angular app

regads


Solution

  • So the guy from the helpful github wrote back to me and said he has another project which uses the REST services. Following is a simple solution to use DevOps RestServices within an DevOps extension with angular and typescript.

    vss-extension.json in the "files" section add:

    {
      "path": "node_modules/vss-web-extension-sdk/lib",
      "addressable": true,
      "packagePath": "lib"
    },
    

    Include in the header of your extension.html file:

      <script src="init-vss-angular.js"></script>
      <script>
        initialize();
      </script>
    

    init-vss-angular.js:

    function initialize(explicitNotifyLoaded, usePlatformStyles, usePlatformScripts, afterSdkReadyCallback) {
        appendScript('../lib/VSS.SDK.min.js').onload = function () {
            VSS.init({
                explicitNotifyLoaded: explicitNotifyLoaded || false,
                usePlatformStyles: usePlatformStyles || false,
                usePlatformScripts: usePlatformScripts || false
            });
        };
    
        function appendScript(scriptSource) {
            let scriptTag = document.createElement('script');
            scriptTag.src = scriptSource;
            document.head.appendChild(scriptTag);
            return scriptTag;
        }
    };
    

    In my case I wanted to retrieve all the Repositories from the RestService and there is the magic that answers my question.

    http-client-factory.service.ts:

    /// <reference path="../../../node_modules/vss-web-extension-sdk/typings/tfs.d.ts" />.
    /// <reference path="../../../node_modules/vss-web-extension-sdk/typings/VSS.SDK.d.ts" />.
    
    import { Injectable } from '@angular/core';
    import { GitHttpClient } from 'TFS/VersionControl/GitRestClient';
    
    @Injectable({
      providedIn: 'root'
    })
    export class HttpClientFactoryService {
      public retrieveGitHTTPClient(): Promise<GitHttpClient> {
        return new Promise((resolve: any, _: any) => {
          VSS.require(['TFS/VersionControl/GitRestClient'], (wit: any) => {
            const client = <GitHttpClient>wit.getClient();
            return resolve(client);
          });
        });
      }
    }
    

    and to get the repositories in the end with http-repository.service.ts

    /// <reference path="../../../node_modules/vss-web-extension-sdk/typings/tfs.d.ts" />.
    /// <reference path="../../../node_modules/vss-web-extension-sdk/typings/VSS.SDK.d.ts" />.
    
    import { Injectable } from '@angular/core';
    import { HttpClientFactoryService } from './http-client-factory.service';
    import { GitRepository } from 'TFS/VersionControl/Contracts';
    
    @Injectable({
      providedIn: 'root'
    })
    export class HttpRepositoryService {
      public constructor(
        private httpClientFactory: HttpClientFactoryService) {
      }
    
      public async loadRepositories(): Promise<GitRepository[]> {
        const client = await this.httpClientFactory.retrieveGitHTTPClient();
        return client.getRepositories();
      }
    }
    

    Give thanks to DrMueller for the original code.