npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@joeldodge/sdk-node

v21.1.1

Published

Looker SDK Runtime for Node Library

Downloads

10

Readme

Looker SDK for Node

BUMP The Looker SDK for Typescript/Javascript works with Node and browser run-times. The SDK provides a convenient way to communicate with a Looker server's APIs.

This package is specifically for using the Looker Typescript SDK with Node. It depends on the @joeldodge/sdk package and @joeldodge/sdk-rtl.

The SDK uses a plug-in architecture (also known as dependency injection) for initializing that supports run-time specific transports (like NodeTransport and BrowserTransport) and different approaches for managing API authentication (like NodeSession, BrowserSession, ProxySession, and OauthSession).

DISCLAIMER: This is a beta version of the Looker SDK. Implementations are still subject to change, but SDK method calls are expected to work correctly. Please report any issues encountered, and indicate the SDK language in the report.

Getting started

The Looker SDK can be used in a node application in 3 steps:

  • install
  • configure
  • use

Install the Looker SDK into your node application

Using yarn:

yarn add @joeldodge/sdk @joeldodge/sdk-rtl @joeldodge/sdk-node

Using npm:

npm install @joeldodge/sdk @joeldodge/sdk-rtl @joeldodge/sdk-node

Note: If you are only intending to use the SDK in a browser, omit @joeldodge/sdk-node.

Configure the SDK for your Looker server

Note: The .ini configuration for the Looker SDK is a sample implementation intended to speed up the initial development of Node applications using the Looker API. Environment variables can also be used to configure the SDK.

Create a looker.ini file with your server URL and API credentials assigned as shown below:

[Looker]
# Base URL for API. Do not include /api/* in the url
base_url=https://<your-looker-server>:19999
# API 3 client id
client_id=your_API3_client_id
# API 3 client secret
client_secret=your_API3_client_secret

Note: If the application using the Looker SDK is going to be committed to a version control system, be sure to ignore the looker.ini file to avoid publishing your API credentials.

Note: The Browser SDK does not use a looker.ini or environment variables.

Use the SDK in your code

When the SDK is installed and the server location and API credentials are configured in your looker.ini file, it's ready to be used.

Verify authentication works and that API calls will succeed with code similar to the following:

import { LookerNodeSDK } from '@joeldodge/sdk-node'
(async () => {
  // create a Node SDK object for API 3.1
  const sdk = LookerNodeSDK.init31()
  // retrieve your user account to verify correct credentials
  const me = await sdk.ok(sdk.me(
    "id, first_name, last_name, display_name, email, personal_space_id, home_space_id, group_ids, role_ids"))
  console.log({me})
  // make any other calls to the Looker SDK
  const dashboards = await sdk.ok(
    sdk.search_dashboards({title: 'My SDK dashboard'})
  )
  if (dashboards.length === 0) {
    console.log('Dashboard not found')
  }
  const [ dashboard ] = dashboards
  // do stuff with dashboard

  ...

  await sdk.authSession.logout()
  if (!sdk.authSession.isAuthenticated()) {
    console.log('Logout successful')
  }
})()

NOTE: By default, LookerNodeSDK.init31() and LookerNodeSDK.init40() will check for environment variables. Environment variables can be ignored by passing an empty string to the NodeSettings constructor.

// Ignore any SDK environment variables for the node runtime
const settings = new NodeSettingsIniFile('')
const sdk = LookerNodeSDK.init40(settings)
const sdk31 = LookerNodeSDK.init31(settings)

Developing with multiple API versions

Starting with Looker release 7.2, the experimental version of API 4.0 is available. To support iterative migration to API 4.0 from API 3.1, the single Looker SDK package now supports multiple API versions for the generated SDK classes. Both API 3.1 and API 4.0 are supported for Node and Browser-based use.

LookerNodeSDK.init31() LookerBrowserSDK.init31() and Looker31SDK() all initialize the API 3.1 implementation of the SDK.

LookerNodeSDK.init40() LookerBrowserSDK.init40() and Looker40SDK() all initialize the API 4.1 implementation of the SDK.

Code similar to the following can be used to develop with both the 3.1 and 4.0 SDKs in the same source file:

import { Looker40SDK, Looker31SDK } from '@joeldodge/sdk'
import { NodeSession, NodeSettingsIniFile } from '@joeldodge/sdk-node'

const settings = new NodeSettingsIniFile()
const session = new NodeSession(settings)
const sdk = new Looker40SDK(session)
const sdk31 = new Looker31SDK(session)

const me40 = await sdk.ok(sdk.me())
const me31 = await sdk.ok(sdk31.me()) // or sdk31.ok(sdk31.me())

Using NodeSession for automatic authentication

Almost all requests to Looker's API require an access token. Typically, this token is established when the login endpoint is called with correct API3 credentials for client_id and client_secret. When login is successful, the provided API3 credentials are used to look up the active API user.

The settings provided to the NodeSession class include the base URL for the Looker instance, and the desired API version. When API requests are made, if the auth session is not yet established, NodeSession will automatically authenticate the API User.

Sudo behavior with NodeSession

The NodeSession also directly supports logging in as another user, which is usually called sudo as another user in the Looker browser application.

An API user with appropriate permissions can sudo as another user by passing a different user ID to the NodeSession.login() method. Only one user can be impersonated at a time via NodeSession. When a sudo session is active, all SDK requests are processed as that user.

The test below shows use cases for authentication and sudo. This code sample is extracted directly from the sdk methods functionla tests, and assumes apiUser is the default authenticated user record with sudo abilities, and sudoA and sudoB are other enabled Looker user accounts.

describe('sudo', () => {
  it(
    'login/logout',
    async () => {
      const sdk = new LookerSDK(session)
      const apiUser = await sdk.ok(sdk.me())
      let all = await sdk.ok(
        sdk.all_users({
          fields: 'id,is_disabled',
        })
      )

      // find users who are not the API user
      const others = all
        .filter((u) => u.id !== apiUser.id && !u.is_disabled)
        .slice(0, 2)
      expect(others.length).toEqual(2)
      if (others.length > 1) {
        // pick two other active users for `sudo` tests
        const [sudoA, sudoB] = others
        // get auth support for login()
        const auth = sdk.authSession as IAuthSession

        // login as sudoA
        await auth.login(sudoA.id.toString())
        let sudo = await sdk.ok(sdk.me()) // `me` returns `sudoA` user
        expect(sudo.id).toEqual(sudoA.id)

        // login as sudoB directly from sudoA
        await auth.login(sudoB.id)
        sudo = await sdk.ok(sdk.me()) // `me` returns `sudoB` user
        expect(sudo.id).toEqual(sudoB.id)

        // logging out sudo resets to API user
        await auth.logout()
        let user = await sdk.ok(sdk.me()) // `me` returns `apiUser` user
        expect(sdk.authSession.isAuthenticated()).toEqual(true)
        expect(user).toEqual(apiUser)

        // login as sudoA again to test plain `login()` later
        await auth.login(sudoA.id)
        sudo = await sdk.ok(sdk.me())
        expect(sudo.id).toEqual(sudoA.id)

        // login() without a sudo ID logs in the API user
        await auth.login()
        user = await sdk.ok(sdk.me()) // `me` returns `apiUser` user
        expect(sdk.authSession.isAuthenticated()).toEqual(true)
        expect(user.id).toEqual(apiUser.id)
      }
      await sdk.authSession.logout()
      expect(sdk.authSession.isAuthenticated()).toEqual(false)
    },
    testTimeout
  )
})

Environment variable configuration

Environment variables can be used to configure access for the Node version of the Looker SDK.

Once the desired environment variables are set, the following code is all that's required to initialize the Looker SDK and retrieve the API credential's User information.

const sdk = LookerNodeSDK.init31(new NodeSettings())
const me = await sdk.ok(sdk.me())

Streaming API responses

The streaming version of the SDK methods should be initialized using the same AuthSession as the main SDK to reduce authentication thrashing.

Construction of the streaming SDK can use code similar to the following, which is taken from the downloadTile.ts example:

/**
 * Use the streaming SDK to download a tile's query
 * @param sdk to use
 * @param tile to download
 * @param format to download
 * @returns name of downloaded file (undefined on failure)
 */
const downloadTileAs = async (
  sdk: LookerSDK,
  tile: IDashboardElement,
  format: string
) => {
  let fileName
  fileName = `${tile.title}.${format}`

  const writer = fs.createWriteStream(fileName)
  const request: IRequestRunQuery = {
    result_format: format,
    query_id: tile.query_id!,
    // apply_formatting: true,
    // apply_vis: true
  }
  const sdkStream = new Looker40SDKStream(sdk.authSession)
  await sdkStream.run_query(async (readable: Readable) => {
    return new Promise<any>((resolve, reject) => {
      readable
        .pipe(writer)
        .on('error', () => {
          fileName = undefined
          throw reject
        })
        .on('finish', resolve)
    })
  }, request)

  return fileName
}

More examples

See the SDK Examples folder for additional Typescript SDK examples.

A note about security

Any script or configuration file used to provide credentials to your Looker SDK instance needs to be secured.