Documentation
    Preparing search index...

    Documentation

    BYU OIT SDK

    Blazingly fast API development for BYU OIT

    Requirements:

    • Node.js 18+
      • or Node.js 10+ with fetch and crypto polyfills
    • npm v9+

    Note that while Node.js 10 (with crypto/fetch polyfills) is supported, you should probably be using at least the LTS version of node (v18 at time of writing) except in cases where a lower version is absolutely necessary.

    Quick-start

    Below are code examples for basic use cases of making HTTP requests using the byu-oit-sdk. These examples show how to use the client-byu package, one of the more commonly used packages in the SDK. To learn about the other packages and for more details, you can find the full documentation at the link below.

    These examples demonstrate how to call the Echo v1 API in order to demonstrate how to call BYU APIs using the byu-oit-sdk.

    This example initializes the client by setting the discovery endpoint, client id, and client secret through environment variables. For this code to work, all you have to do is run the npm install command below, copy the code, and then set the process.env.BYU_OIT_CLIENT_ID, process.env.BYU_OIT_CLIENT_SECRET, and process.env.BYU_OIT_DISCOVERY_ENDPOINT.

    The discovery endpoint for Tyk will be https://api-sandbox.byu.edu/.well-known/openid-configuration. Remove the -sandbox if using production credentials.

    npm i @byu-oit-sdk/client-byu
    
    ESM (and Typescript)
    import { Client } from '@byu-oit-sdk/client-byu'

    /**
    * You should change these hardcoded environment names and url prefixes
    * to match your projects environments and deployment strategy
    */
    const production = process.env.ENVIRONMENT_NAME === 'prd'
    const host = production ? 'api.byu.edu' : 'api-sandbox.byu.edu'

    /**
    * Given an empty constructor, config and credentials will be fetched
    * from `BYU_OIT_`-prefixed environment variables.
    */
    const client = new Client()

    const response = await client.fetch(`https://${host}/echo/v1/echo/test`)
    console.log(await response.json())
    CommonJS
    const { Client } = require('@byu-oit-sdk/client-byu')

    /**
    * You should change these hardcoded environment names and url prefixes
    * to match your projects environments and deployment strategy
    */
    const production = process.env.ENVIRONMENT_NAME === 'prd'
    const host = production ? 'api.byu.edu' : 'api-sandbox.byu.edu'

    ;(async () => {
    /**
    * Given an empty constructor, config and credentials will be fetched
    * from `BYU_OIT_`-prefixed environment variables.
    */
    const client = new Client()

    const response = await client.fetch(`https://${host}/echo/v1/echo/test`)
    console.log(await response.json())
    })()

    This example initializes the client by setting the discovery endpoint, client id, and client secret in the code itself. For this code to work, all you have to do is run the npm install command below, copy the code, and then replace myClientId and myClientSecret with your actual Tyk credentials.

    npm i @byu-oit-sdk/client-byu @byu-oit-sdk/credential-provider
    
    ESM (and Typescript)
    import { Client } from '@byu-oit-sdk/client-byu'
    import { ClientCredentialsProvider } from '@byu-oit-sdk/credential-provider'

    /**
    * You should change these hardcoded environment names and url prefixes
    * to match your projects environments and deployment strategy
    */
    const production = process.env.ENVIRONMENT_NAME === 'prd'
    const host = production ? 'api.byu.edu' : 'api-sandbox.byu.edu'

    const client = new Client({
    credentials: new ClientCredentialsProvider({
    /* DO NOT commit any files with hardcoded credentials */
    clientId: 'myClientId',
    clientSecret: 'myClientSecret',
    discoveryEndpoint: `https://${host}/.well-known/openid-configuration`
    })
    })

    const response = await client.fetch(`https://${host}/echo/v1/echo/test`)
    console.log(await response.json())
    CommonJS
    const { Client } = require('@byu-oit-sdk/client-byu')
    const { ClientCredentialsProvider } = require('@byu-oit-sdk/credential-provider')

    /**
    * You should change these hardcoded environment names and url prefixes
    * to match your projects environments and deployment strategy
    */
    const production = process.env.ENVIRONMENT_NAME === 'prd'
    const host = production ? 'api.byu.edu' : 'api-sandbox.byu.edu'

    ;(async () => {
    const client = new Client({
    credentials: new ClientCredentialsProvider({
    /* DO NOT commit any files with hardcoded credentials */
    clientId: 'myClientId',
    clientSecret: 'myClientSecret',
    discoveryEndpoint: `https://${host}/.well-known/openid-configuration`
    })
    })

    const response = await client.fetch(`https://${host}/echo/v1/echo/test`)
    console.log(await response.json())
    })()

    SDK Deep Dive

    There are a number client packages to facilitate calling APIs with or without authentication. All clients will work in the browser and in Node.js (ESM or CJS).

    1. The BYU Client essentially wraps the Fetch API and adds a retry middleware and an optional authentication middleware.

    2. A list of domain specific clients can be found here:

      Domain Specific Clients
      Name Domain
      IdentitiesClient https://api.byu.edu/byuapi/identities
      PersonsClient https://api.byu.edu/byuapi/persons
      WorkdayClient Workday tenant domains vary between institutions

    To start developing a new or existing client, please refer to the Client Development documentation

    Currently, the BYU OIT SDK supports Authorization Code Provider implementations for Fastify and Express and Svelte.

    OAuth Credential Providers facilitate interactions with an OAuth 2.0-compliant authorization server. Please see the documentation on credential providers for more information.

    The supported credential providers are:

    Contributing

    The BYU OIT SDK uses Lerna with Nx to build, test, and lint the source code. Please consult their documentation when making modifications to the maintenance process of this project.

    There are a few commands that most of the packages share:

    • build: Compile the distribution code
    • lint: Lint the source code
    • test: Test the source code with Ava

    If you notice a problem, please submit an issue or create a PR with the fix!

    Commit messages must adhere to the angular conventional commit standard. commitlint will enforce commit messages to follow this standard. Following a commit standard enables our distribution pipeline to publish new versions of each package automatically.

    This library exposes files in both CJS and ESM syntax in order to accommodate browser environments and legacy Node.js applications. CJS support may be dropped in the future but is supported for the time being.

    There are two ways that we know of to support both CJS and ESM syntax:

    1. Create a localized package.json file in each packages' cjs directory with the contents { type: 'commonjs' }. This effectively overwrites the package's own package.json which is set to module.

      Node Resolution Algorithm: See ESM_FILE_FORMAT

      ESM & CommonJS Module Tutorial: https://www.sensedeep.com/blog/posts/2021/how-to-create-single-source-npm-module.html

    2. Use a tool such as unbuild which outputs files with the .cjs and .mjs extensions.

      Example of Using unbuild: https://github.com/unjs/radix3/blob/main/package.json

      MDN Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules

    This library uses the first method for two reasons:

    1. Some tools may never support the .mjs extension
    2. (package.json).type is more deterministic since the resolution algorithm is built into node and bundlers.

    The choice to use Ava was made because it

    1. supports TypeScript and ESM out of the box
    2. parallelizes tests in separate environments making it typically faster
    3. does not mutate Node.js globals like Jest
    4. follows a similar convention as the node test runner which we may adopt eventually

    Running tests requires building the source code first, which should be handled for you by lerna.

    From the root of the project you can run:

    npm test
    

    Or you can run the following from anywhere within the project.

    # use npx if you don't want to install lerna globally
    lerna run test

    Note There is a bug in Node.js Worker threads which requires us to use the --no-worker-threads flag when running tests. Even with that flag enabled, some tests run into this bug. There isn't a bug report for the issue yet (See this discussion). Currently, this seems to only affect the @byu-oit-sdk/client package.

    Merging changes into the main branch will automatically update the version of each package, publish the package, and publish the changelog according to the commit messages.

    Merging changes into the beta branch will trigger the same GitHub workflow but the beta prefix will be prepended to the new pre-release versions published.

    The publish workflow was heavily inspired by the article "Automatic versioning in a Lerna monorepo using GitHub actions" by Xavier Canchal :clap:.

    Writing SDKs with TypeScript and TSDocs provides consumers with the code and documentation all from their development environments. To that end, running the linter without documenting code with TSDocs style documentation (similar to JSDocs or JavaDocs), will return a non-zero exit code.