Blazingly fast API development for BYU OIT
Requirements:
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.
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
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())
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
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())
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())
})()
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).
The BYU Client essentially wraps the Fetch API and adds a retry middleware and an optional authentication middleware.
A list of domain specific clients can be found here:
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:
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:
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:
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
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:
.mjs
extension(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
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.