@groton/canvas-api
v0.3.4
Published
Typed access to Canvas LMS API with embedded documentation
Downloads
8
Readme
@groton/canvas-api
Typed access to Canvas LMS API with embedded documentation
Clients
This started as a component of @groton/canvas-cli, a command-line set of administrative scripts that I have banged together. However, access to the inline documentation and IntelliSense autocompletions in a few front-end applications evolved this package into an API-only package that depends on purpose-dependent client for use:
- @groton/canvas-api.client.base provides interfaces and types to be used by any implementing classes.
- @groton/canvas-api.client.node-cli is a client for use in Node command-line apps, which takes advantage of the @oauth2-cli/canvas to handle authentication to a Canvas LMS instance from the command-line.
- @groton/canvas-api.client.qui-cli encapsulates the Node client in a @battis/qui-cli.plugin for ease of use within that small ecosystme for rapidly developing Node command-line apps.
Install
Using the Node client.
npm install @groton/canvas-api @groton/canvas-api.client.node-cliUsage
Again, using the Node client. See @groton/canvas-cli for a working example of using the @battis/qui-cli encapsulation.
import * as Canvas from '@groton/canvas-api';
import { Client } from '@groton/canvas-api.client.node-cli';
// initialize the client from environment variables
Canvas.init(
new Client({
instance_url: process.env.INSTANCE_URL,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: process.env.REDIRECT_URI
})
);
// pull a paginated list of typed users from the API
for (const user of await Canvas.v1.Accounts.Users.list({
pathParams: { account_id: 1 }
})) {
console.log(user.name);
}Mapping Canvas LMS documentation to TypeScript API
The automatically-generated documentation provided by the Canvas LMS API is automatically processed by @groton/canvas-api.swagger-renderer to generate TypeScript API.
Resources
Resources are organized as in the Canvas LMS API documentation, given that they are built from the same files. For example, a CourseProgress object is typed:
let progress: Canvas.Courses.CourseProgress;…noting that, for all objects:
Sentence caseandsnake_caseobject names are all converted toCamelCase.- Properties remain unchanged in
snake_case. - All namespaces are capitalized, and properties are lower-case per TypeScript norms.
Endpoints
In general, the endpoints map to method calls that are predictably named. For example, listing subgroups of outcome groups:
GET /api/v1/accounts/{account_id}/outcome_groups/{id}/subgroups…is handled by:
await Canvas.v1.Accounts.OutcomeGroups.Subgroups.list({
pathParams: {
account_id: 123,
id: 456
},
searchParams: {
as_user_id: 789,
per_page: 20
}
});…in which:
snake_casebecomesCamelCasefor namespaces and objects andpascalCasefor methods.- Method names are shortened from their nicknames (
list_subgroups_accounts) to remove redundancies in the TypeScript API. - All method calls are asynchronous.
- Path parameters are passed as properties of the
pathParamsproperty, search/query parameters are passed as properties of thesearchParamsproperty, and body/form parameters are passed as properties of theparamsproperty. - Methods that upload files also require a
fileproperty, which may have either afilePathproperty or aurlproperty. (Not all clients support both local and URL uploads). - All methods support masquerading via the
as_user_idparameter passed as either insearchParamsor the bodyparams(if available). - Methods that return paginated responses can adjust the pagination via
per_pagesand will return the complete list as a result of the method.
Caution regarding === comparisons
Note that, in order to provide data integrity in JavaScript, per Instructure's note about large numbers in that language, I have introduced some type ambiguity into the model, which has ramifications for value tests:
Because numerical values may be represented as either strings or numbers, be very, very cautious about using === comparisons, which will fail when comparing a number to an equivalent string.
Known Issues
This is under steady development, as it underpins my own administrative and user-facing Canvas LMS tools. Known issues are documented in the GitHub repo.
Be aware that, due to eccentricities in the documentation of the Canvas LMS API, a number of the typing decisions have been manually overriden to provide empirically more accurate type definitions. This work is on-going and incomplete (and should end up in a pull request to the LMS repo).
overrides.json documents these eccentricities, is supported by src/Overrides.ts and is processed by @groton/canvas-api.swagger-renderer to generate the contents of src/Resources/ and src/Endpoints/.
