diff --git a/examples/box/README.md b/examples/box/README.md index 1e3f125..97542c1 100644 --- a/examples/box/README.md +++ b/examples/box/README.md @@ -1,6 +1,6 @@ # Box -This is a small example Pack that demonstrates how to create an action formula that uploads a file to Box. The primary purpose of this example is to demonstrate how to use the `form-data` NPM library to send `multipart/form-data` payloads with the Fetcher. +This is a small example Plugin that demonstrates how to create an action formula that uploads a file to Box. The primary purpose of this example is to demonstrate how to use the `form-data` NPM library to send `multipart/form-data` payloads with the Fetcher. ## Setup @@ -12,7 +12,7 @@ as your "Redirect URIs" in order to run these examples locally. To run them on Coda after uploading & releasing, your authorization callback URL must change to be **`https://coda.io/packsAuth/oauth2/{PACK_ID}`**. -Run `coda auth examples/box/pack.ts`. You'll be prompted to enter your client id +Run `packs auth examples/box/pack.ts`. You'll be prompted to enter your client id and client secret, and then your browser will open and begin Box's OAuth flow. After the flow completes, the access token for that account will saved locally for use when executing formulas and syncs, so you only have to do this once. But you can @@ -24,7 +24,7 @@ becomes invalid. To upload a file run: ```bash -coda execute examples/box/pack.ts UploadFile "{FILE_URL}" +packs execute examples/box/pack.ts UploadFile "{FILE_URL}" ``` The file URL must be hosted on `codahosted.io`, which is where Coda stores uploaded files and images. You can test with this value: diff --git a/examples/box/helpers.ts b/examples/box/helpers.ts index 113fd57..8630e69 100644 --- a/examples/box/helpers.ts +++ b/examples/box/helpers.ts @@ -1,14 +1,14 @@ import * as ContentDisposition from "content-disposition"; import type {Folder} from "./types"; import type {User} from "./types"; -import * as coda from "@superhuman/plugins-sdk"; import * as mime from "mime-types"; +import * as sdk from "@superhuman/plugins-sdk"; export async function searchFolders( - context: coda.ExecutionContext, + context: sdk.ExecutionContext, search: string, ): Promise { - let url = coda.withQueryParams("https://api.box.com/2.0/search", { + let url = sdk.withQueryParams("https://api.box.com/2.0/search", { type: "folder", // If no query has been entered, search for "folder" to find all folders. query: search || "folder", @@ -22,7 +22,7 @@ export async function searchFolders( return response.body.entries; } -export async function getUser(context: coda.ExecutionContext): Promise { +export async function getUser(context: sdk.ExecutionContext): Promise { let response = await context.fetcher.fetch({ method: "GET", url: "https://api.box.com/2.0/users/me", diff --git a/examples/box/pack.ts b/examples/box/pack.ts index 850a6d2..99c12dd 100644 --- a/examples/box/pack.ts +++ b/examples/box/pack.ts @@ -1,15 +1,15 @@ import FormData from "form-data"; -import * as coda from "@superhuman/plugins-sdk"; import {getFilename} from "./helpers"; import {getUser} from "./helpers"; +import * as sdk from "@superhuman/plugins-sdk"; import {searchFolders} from "./helpers"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); pack.addNetworkDomain("box.com"); pack.setUserAuthentication({ - type: coda.AuthenticationType.OAuth2, + type: sdk.AuthenticationType.OAuth2, authorizationUrl: "https://account.box.com/api/oauth2/authorize", tokenUrl: "https://api.box.com/oauth2/token", getConnectionName: async function (context) { @@ -22,20 +22,20 @@ pack.addFormula({ name: "UploadFile", description: "Uploads a file to Box.", parameters: [ - coda.makeParameter({ - type: coda.ParameterType.File, + sdk.makeParameter({ + type: sdk.ParameterType.File, name: "file", description: "The file to upload.", }), - coda.makeParameter({ - type: coda.ParameterType.String, + sdk.makeParameter({ + type: sdk.ParameterType.String, name: "filename", description: "The filename to upload to. Default: the original filename of the file.", optional: true, }), - coda.makeParameter({ - type: coda.ParameterType.String, + sdk.makeParameter({ + type: sdk.ParameterType.String, name: "folderId", description: "The ID of the folder to upload to. Default: the root folder.", @@ -51,7 +51,7 @@ pack.addFormula({ }, }), ], - resultType: coda.ValueType.String, + resultType: sdk.ValueType.String, isAction: true, execute: async function (args, context) { let [fileUrl, filename, folderId = "0"] = args; diff --git a/examples/dictionary/README.md b/examples/dictionary/README.md index 9c13edb..eee0f14 100644 --- a/examples/dictionary/README.md +++ b/examples/dictionary/README.md @@ -7,14 +7,14 @@ with Merriam-Webster. ## Running the Example -Run `coda auth examples/dictionary/pack.ts` and enter your API key. +Run `packs auth examples/dictionary/pack.ts` and enter your API key. -Then run `coda execute examples/dictionary/pack.ts Define coda` to look +Then run `packs execute examples/dictionary/pack.ts Define coda` to look up definitions for a word, in this case `coda`. ## Running the Tests -Run the unittests just for this Pack by using: +Run the unittests just for this Plugin by using: ```bash mocha --require ts-node/register examples/dictionary/test/dictionary_test.ts @@ -24,7 +24,7 @@ The unittests use a mock http fetcher and do not connect to a real API. There is also an integration test, which makes real http requests to the API. To run successfully, this test requires that you've set up an API key already -using `coda auth examples/dictionary/pack.ts`. +using `packs auth examples/dictionary/pack.ts`. ```bash mocha --require ts-node/register examples/dictionary/test/dictionary_integration.ts diff --git a/examples/dictionary/helpers.ts b/examples/dictionary/helpers.ts index 5480d96..6a3eafe 100644 --- a/examples/dictionary/helpers.ts +++ b/examples/dictionary/helpers.ts @@ -1,10 +1,10 @@ -import type * as coda from "@superhuman/plugins-sdk"; +import type * as sdk from "@superhuman/plugins-sdk"; import type * as types from "./types"; const API_VERSION = "v3"; export async function lookupDefinition( - context: coda.ExecutionContext, + context: sdk.ExecutionContext, word: string, ): Promise { let escapedWord = encodeURIComponent(word); diff --git a/examples/dictionary/pack.ts b/examples/dictionary/pack.ts index a132fd6..5a646b0 100644 --- a/examples/dictionary/pack.ts +++ b/examples/dictionary/pack.ts @@ -1,31 +1,31 @@ -import * as coda from "@superhuman/plugins-sdk"; import * as helpers from "./helpers"; import * as schemas from "./schemas"; +import * as sdk from "@superhuman/plugins-sdk"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); // The Merriam-Webster API uses an API token, which should be included in // request urls in a "key=" parameter, so we configure that here. When -// running `coda auth examples/dictionary/pack.ts` you will be prompted -// to enter your API key to use when using `coda execute` to exercise formulas -// in this pack. Users would be prompted to enter an API key when installing -// this pack in the Coda UI. +// running `packs auth examples/dictionary/pack.ts` you will be prompted +// to enter your API key to use when using `packs execute` to exercise formulas +// in this plugin. Users would be prompted to enter an API key when installing +// this plugin in the Coda UI. pack.setUserAuthentication({ - type: coda.AuthenticationType.QueryParamToken, + type: sdk.AuthenticationType.QueryParamToken, paramName: "key", }); -// This tells Coda which domain the pack make requests to. Any fetcher +// This tells Coda which domain the plugin make requests to. Any fetcher // requests to other domains won't be allowed. pack.addNetworkDomain("dictionaryapi.com"); pack.addFormula({ - resultType: coda.ValueType.Object, + resultType: sdk.ValueType.Object, name: "Define", description: "Returns the definition and other metadata for a given word.", parameters: [ - coda.makeParameter({ - type: coda.ParameterType.String, + sdk.makeParameter({ + type: sdk.ParameterType.String, name: "word", description: "A word to define.", }), diff --git a/examples/dictionary/schemas.ts b/examples/dictionary/schemas.ts index f561219..b548cc0 100644 --- a/examples/dictionary/schemas.ts +++ b/examples/dictionary/schemas.ts @@ -1,26 +1,26 @@ -import * as coda from "@superhuman/plugins-sdk"; +import * as sdk from "@superhuman/plugins-sdk"; -export const DefinitionSchema = coda.makeObjectSchema({ +export const DefinitionSchema = sdk.makeObjectSchema({ properties: { - id: {type: coda.ValueType.String, required: true}, + id: {type: sdk.ValueType.String, required: true}, definitions: { - type: coda.ValueType.Array, - items: {type: coda.ValueType.String}, + type: sdk.ValueType.Array, + items: {type: sdk.ValueType.String}, required: true, }, - headword: {type: coda.ValueType.String, required: true}, - partOfSpeech: {type: coda.ValueType.String}, - firstUse: {type: coda.ValueType.String}, - offensive: {type: coda.ValueType.Boolean, required: true}, + headword: {type: sdk.ValueType.String, required: true}, + partOfSpeech: {type: sdk.ValueType.String}, + firstUse: {type: sdk.ValueType.String}, + offensive: {type: sdk.ValueType.Boolean, required: true}, }, // The display property tells Coda which of your object's properties - // should be used as a label for your object. Pack objects will be rendered + // should be used as a label for your object. Plugin objects will be rendered // as a chip showing the label, and the rest of the fields will show up // when hovering over the chip. displayProperty: "headword", }); -export const DefinitionArraySchema = coda.makeSchema({ - type: coda.ValueType.Array, +export const DefinitionArraySchema = sdk.makeSchema({ + type: sdk.ValueType.Array, items: DefinitionSchema, }); diff --git a/examples/dictionary/test/dictionary_integration.ts b/examples/dictionary/test/dictionary_integration.ts index 6684f28..85a033f 100644 --- a/examples/dictionary/test/dictionary_integration.ts +++ b/examples/dictionary/test/dictionary_integration.ts @@ -4,11 +4,11 @@ import {executeFormulaFromPackDef} from "@superhuman/plugins-sdk/dist/developmen import {it} from "mocha"; import {pack} from "../pack"; -describe("Dictionary pack integration test", () => { +describe("Dictionary plugin integration test", () => { it("executes Define", async () => { - // Here we execute the formula using a real http fetcher. Since this pack + // Here we execute the formula using a real http fetcher. Since this plugin // requires authentication, this requires that you've already run - // `coda auth examples/dictionary/pack.ts` to set up an API key. + // `packs auth examples/dictionary/pack.ts` to set up an API key. let response = await executeFormulaFromPackDef( pack, "Define", diff --git a/examples/dictionary/test/dictionary_test.ts b/examples/dictionary/test/dictionary_test.ts index 0c5201f..25a477f 100644 --- a/examples/dictionary/test/dictionary_test.ts +++ b/examples/dictionary/test/dictionary_test.ts @@ -9,7 +9,7 @@ import {newMockExecutionContext} from "@superhuman/plugins-sdk/dist/development" import {pack} from "../pack"; import * as sinon from "sinon"; -describe("Dictionary pack", () => { +describe("Dictionary plugin", () => { let context: MockExecutionContext; beforeEach(() => { @@ -48,7 +48,7 @@ describe("Dictionary pack", () => { assert.equal(1, response.length); // The response object has gone through normalization, standardizing the // capitalization and formatting of object propery names to be consistent - // across packs. + // across plugins. assert.deepEqual(response[0], { Id: "foo", Definitions: ["definition of foo"], @@ -63,7 +63,7 @@ describe("Dictionary pack", () => { }); }); - // It's important to verify how your pack behaves in edges cases. We've + // It's important to verify how your plugin behaves in edges cases. We've // checked that the real API returns an empty list as a response when it // cannot find the input word, so we simulate that here, and make sure // that our implementation doesn't throw any errors. diff --git a/examples/dictionary/types.ts b/examples/dictionary/types.ts index 3e31f29..d1d54b6 100644 --- a/examples/dictionary/types.ts +++ b/examples/dictionary/types.ts @@ -5,7 +5,7 @@ // A single response entry as described at https://dictionaryapi.com/products/json. // The http response from the API consists of an array of these objects. // For simplicity, we only include the subset of fields that care about for -// this pack. +// this plugin. export interface APIEntry { // One or more practical definitions of the word. shortdef: string[]; @@ -29,7 +29,7 @@ export interface APIEntry { } /** - * Type definitions for the transformed objects returned by the pack. + * Type definitions for the transformed objects returned by the plugin. * Generally these types match the schema(s) you define in schemas.ts. */ diff --git a/examples/github/README.md b/examples/github/README.md index 4bd3545..1b05773 100644 --- a/examples/github/README.md +++ b/examples/github/README.md @@ -1,6 +1,6 @@ # GitHub -This is a more substantive example Pack that connects to GitHub using OAuth2 authentication, +This is a more substantive example Plugin that connects to GitHub using OAuth2 authentication, and implements a table that syncs various pull requests for one or more repos that the user has access to, as well as an action formula to post a pull request review. @@ -15,7 +15,7 @@ on Coda after uploading & releasing, your authorization callback URL must change ## Running the Example -Run `coda auth examples/github/pack.ts`. You'll be prompted to enter you client id +Run `packs auth examples/github/pack.ts`. You'll be prompted to enter you client id and client secret, and then your browser will open and begin GitHub's OAuth flow. After the flow completes, the access token for that account will saved locally for use when executing formulas and syncs, so you only have to do this once. But you can @@ -25,13 +25,13 @@ becomes invalid. To sync pull requests and output them to the console, you can run: ```bash -coda execute examples/github/pack.ts PullRequests https://github.com// +packs execute examples/github/pack.ts PullRequests https://github.com// ``` To create a review on a pull request, you can run: ```bash -coda execute examples/github/pack.ts ReviewPullRequest https://github.com///pull/ COMMENT "Some comment" +packs execute examples/github/pack.ts ReviewPullRequest https://github.com///pull/ COMMENT "Some comment" ``` Note that this will actually update your pull request in GitHub! So be careful and make @@ -40,7 +40,7 @@ sure you don't inadvertently e.g. approve a real PR if you're just exploring. To execute the example `PullRequests` table sync, run: ```bash -coda execute examples/github/pack.ts PullRequests https://github.com// +packs execute examples/github/pack.ts PullRequests https://github.com// ``` This will fetch all of the pull requests in that repo, using multiple requests if there are multiple result @@ -51,7 +51,7 @@ parameter to the sync.) ## Running the Tests -Run the unittests just for this Pack by using: +Run the unittests just for this Plugin by using: ```bash mocha --require ts-node/register examples/github/test/github_test.ts @@ -61,7 +61,7 @@ The unittests use a mock http fetcher and do not connect to a real API. There is also an integration test, which makes real http requests to the API. To run successfully, this test requires that you've already setup an access token -using `coda auth examples/github/pack.ts`. +using `packs auth examples/github/pack.ts`. ```bash mocha --require ts-node/register examples/github/test/github_integration.ts diff --git a/examples/github/helpers.ts b/examples/github/helpers.ts index 9585e3f..7fd74f3 100644 --- a/examples/github/helpers.ts +++ b/examples/github/helpers.ts @@ -1,4 +1,4 @@ -import * as coda from "@superhuman/plugins-sdk"; +import * as sdk from "@superhuman/plugins-sdk"; import type * as types from "./types"; const PULL_REQUEST_URL_REGEX = @@ -15,14 +15,14 @@ const DEFAULT_PAGE_SIZE = 100; // meaningful but we do so to future-proof things. export function apiUrl(path: string, params?: Record): string { let url = `https://api.github.com${path}`; - return params ? coda.withQueryParams(url, params) : url; + return params ? sdk.withQueryParams(url, params) : url; } // This formula is used in the authentication definition in pack.ts. // It returns a simple label for the current user's account so the account // can be identified in the UI. -export async function getConnectionName(context: coda.ExecutionContext) { - let request: coda.FetchRequest = { +export async function getConnectionName(context: sdk.ExecutionContext) { + let request: sdk.FetchRequest = { method: "GET", url: apiUrl("/user"), headers: { @@ -40,7 +40,7 @@ export function parsePullUrl(url: string): { repo: string; pullNumber: string; } { - let match = coda.ensureExists( + let match = sdk.ensureExists( PULL_REQUEST_URL_REGEX.exec(url), "Received an invalid pull request URL", ); @@ -54,7 +54,7 @@ export function parsePullUrl(url: string): { // The user-facing formula uses a url to identify repos in a user-friendly way. // We parse such a url into its identifiers. export function parseRepoUrl(url: string): {owner: string; repo: string} { - let match = coda.ensureExists( + let match = sdk.ensureExists( REPO_URL_REGEX.exec(url), "Received an invalid repo URL", ); @@ -68,8 +68,8 @@ export function parseRepoUrl(url: string): {owner: string; repo: string} { // call this repeatedly with a continuation if the user has access to more // repos than can fit on one page (100). export async function getRepos( - context: coda.ExecutionContext, - continuation?: coda.Continuation, + context: sdk.ExecutionContext, + continuation?: sdk.Continuation, ) { let url = continuation?.nextUrl ? (continuation.nextUrl as string) @@ -93,8 +93,8 @@ export async function getRepos( // to fetch a subsequent result page. export async function getPullRequests( [repoUrl, base, state]: any[], - context: coda.SyncExecutionContext, -): Promise { + context: sdk.SyncExecutionContext, +): Promise { let {continuation} = context.sync; let {owner, repo} = parseRepoUrl(repoUrl); let params = {per_page: DEFAULT_PAGE_SIZE, base: base, state: state}; @@ -116,7 +116,7 @@ export async function getPullRequests( // This does some basic transformation and unnesting of a pull request // response object to make the response match the schema declared in // schemas.ts. Most of the property name remapping happens automatically -// with the packs infrastructure because the schema declares +// with the plugins infrastructure because the schema declares // `fromKey` properties in order to rename keys, so this function exists // mostly to do massaging beyond what can be done with `fromKey`. function parsePullRequest(pr: types.GitHubPullRequest) { @@ -131,7 +131,7 @@ function parsePullRequest(pr: types.GitHubPullRequest) { // See if GitHub has given us the url of a next page of results. function nextUrlFromLinkHeader( - result: coda.FetchResponse, + result: sdk.FetchResponse, ): string | undefined { let parsedHeader = typeof result.headers.link === "string" @@ -156,7 +156,7 @@ function nextUrlFromLinkHeader( // } // The npm library `parse-link-header` is useful for this purpose: https://www.npmjs.com/package/parse-link-header // We haven't used it here for simplicity of dependencies in this repo, -// but it may well be helpful in your own packs. +// but it may well be helpful in your own plugins. function parseLinkHeader(header: string): Record { let result: Record = {}; let parts = header.split(/,\s*/); diff --git a/examples/github/pack.ts b/examples/github/pack.ts index d0ba47b..8f2d373 100644 --- a/examples/github/pack.ts +++ b/examples/github/pack.ts @@ -1,19 +1,19 @@ -import * as coda from "@superhuman/plugins-sdk"; import * as helpers from "./helpers"; import * as schemas from "./schemas"; +import * as sdk from "@superhuman/plugins-sdk"; import * as types from "./types"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); -// This tells Coda which domain the pack make requests to. Any fetcher +// This tells Coda which domain the plugin make requests to. Any fetcher // requests to other domains won't be allowed. pack.addNetworkDomain("github.com"); -// The GitHub pack uses OAuth authentication, to allow each user to login -// to GitHub via the browser when installing the pack. The pack will +// The GitHub plugin uses OAuth authentication, to allow each user to login +// to GitHub via the browser when installing the plugin. The plugin will // operate on their personal data. pack.setUserAuthentication({ - type: coda.AuthenticationType.OAuth2, + type: sdk.AuthenticationType.OAuth2, // As outlined in https://docs.github.com/en/free-pro-team@latest/developers/apps/authorizing-oauth-apps, // these are the urls for initiating OAuth authentication and doing // token exchange. @@ -27,7 +27,7 @@ pack.setUserAuthentication({ // so we specify a non-default tokenPrefix here. tokenPrefix: "token", // These are the GitHub-specific scopes the user will be prompted to - // authorize in order for the functionality in this pack to succeed. + // authorize in order for the functionality in this plugin to succeed. scopes: ["read:user", "repo"], // This is a simple formula that makes an API call to GitHub to find // the name of the user associated with the OAuth access token. This @@ -40,16 +40,16 @@ pack.setUserAuthentication({ }); // A parameter that identifies a PR to review using its url. -const PullRequestUrlParameter = coda.makeParameter({ - type: coda.ParameterType.String, +const PullRequestUrlParameter = sdk.makeParameter({ + type: sdk.ParameterType.String, name: "pullRequestUrl", description: 'The URL of the pull request. For example, "https://github.com/[org]/[repo]/pull/[id]".', }); // A parameter that indicates what action to take on the review. -const PullRequestReviewActionTypeParameter = coda.makeParameter({ - type: coda.ParameterType.String, +const PullRequestReviewActionTypeParameter = sdk.makeParameter({ + type: sdk.ParameterType.String, name: "actionType", description: "Type of review action. One of Approve, Comment or Request Changes", @@ -67,8 +67,8 @@ const PullRequestReviewActionTypeParameter = coda.makeParameter({ // Free-form text to be included as the review comment, if this is a Comment // or Request Changes action. -const PullRequestReviewCommentParameter = coda.makeParameter({ - type: coda.ParameterType.String, +const PullRequestReviewCommentParameter = sdk.makeParameter({ + type: sdk.ParameterType.String, name: "comment", description: "Comment for review. Required if review action type is Comment or Request Changes.", @@ -78,7 +78,7 @@ const PullRequestReviewCommentParameter = coda.makeParameter({ // We use makeObjectFormula because this formula will return a structured // object with multiple pieces of data about the submitted rview. pack.addFormula({ - resultType: coda.ValueType.Object, + resultType: sdk.ValueType.Object, name: "ReviewPullRequest", description: "Review a pull request.", schema: schemas.PullRequestReviewResponseSchema, @@ -95,14 +95,14 @@ pack.addFormula({ if (actionType !== types.GitHubReviewEvent.Approve && !comment) { // You can throw a UserVisibleError at any point in a formula to provide // an error message to be displayed to the user in the UI. - throw new coda.UserVisibleError( + throw new sdk.UserVisibleError( "Comment parameter must be provided for Comment or Request Changes actions.", ); } let payload = {body: comment, event: actionType}; let {owner, repo, pullNumber} = helpers.parsePullUrl(pullRequestUrl); - let request: coda.FetchRequest = { + let request: sdk.FetchRequest = { method: "POST", url: helpers.apiUrl( `/repos/${owner}/${repo}/pulls/${pullNumber}/reviews`, @@ -123,13 +123,13 @@ pack.addFormula({ // user-visible errors, rather than letting these fall through as // uncaught errors. if (e.message.includes("Can not approve your own pull request")) { - throw new coda.UserVisibleError( + throw new sdk.UserVisibleError( "Can not approve your own pull request", ); } else if ( e.message.includes("Can not request changes on your own pull request") ) { - throw new coda.UserVisibleError( + throw new sdk.UserVisibleError( "Can not request changes on your own pull request", ); } @@ -140,7 +140,7 @@ pack.addFormula({ examples: [ { params: [ - "https://github.com/coda/packs-examples/pull/123", + "https://github.com/superhuman/plugins-examples/pull/123", "COMMENT", "Some comment", ], @@ -154,7 +154,7 @@ pack.addFormula({ }, Body: "Some comment", State: "COMMENTED", - Url: "https://github.com/coda/packs-examples/pull/123", + Url: "https://github.com/superhuman/plugins-examples/pull/123", CommitId: "ff3d90e1d62c37b93994078fad0dad37d3e", }, }, @@ -162,7 +162,7 @@ pack.addFormula({ }); // This formula demonstrates the use of incremental/progressive OAuth scopes. -// Calling this formula requires more permissions from GitHub than the pack +// Calling this formula requires more permissions from GitHub than the plugin // requests at its initial installation, and Coda will guide a user through // an additional authorization when they try to use a formula with greater // permissions like this and get an error. @@ -170,13 +170,13 @@ pack.addFormula({ name: "UserEmail", description: "Returns the primary email address used on this user's GitHub account.", - resultType: coda.ValueType.String, + resultType: sdk.ValueType.String, // This formula will need this additional OAuth permission to get the email // address of the user. extraOAuthScopes: ["user:email"], parameters: [], execute: async function ([_index], context) { - let request: coda.FetchRequest = { + let request: sdk.FetchRequest = { method: "GET", url: helpers.apiUrl("/user/emails"), }; @@ -184,7 +184,7 @@ pack.addFormula({ // give a 404 error, which will bubble up to Coda because there is no // try/catch on this fetch. When Coda sees an error from a formula like // that, it looks at the scopes the user is currently authenticated with - // compared to what scopes are requested by the pack's manifest and the + // compared to what scopes are requested by the plugin's manifest and the // formula. Here, Coda will see the extraOAuthScopes field on this // formula and replace the 404 error with an instruction to the user // to sign in again. @@ -200,8 +200,8 @@ pack.addFormula({ // However, a user can set up multiple sync configurations // and each one can individually sync from a separate repo. // (This is exported so that we can unittest the autocomplete formula.) -export const RepoUrlParameter = coda.makeParameter({ - type: coda.ParameterType.String, +export const RepoUrlParameter = sdk.makeParameter({ + type: sdk.ParameterType.String, name: "repoUrl", description: 'The URL of the repository to list pull requests from. For example, "https://github.com/[org]/[repo]".', @@ -211,7 +211,7 @@ export const RepoUrlParameter = coda.makeParameter({ // over the repo name. autocomplete: async (context, search) => { let results: types.GitHubRepo[] = []; - let continuation: coda.Continuation | undefined; + let continuation: sdk.Continuation | undefined; do { let response = await helpers.getRepos(context, continuation); results = results.concat(...response.result); @@ -224,19 +224,19 @@ export const RepoUrlParameter = coda.makeParameter({ // value when a user selects a result. // So here, this is saying "search the `name` field of reach result, and // use the html_url as the value once selected". - return coda.autocompleteSearchObjects(search, results, "name", "html_url"); + return sdk.autocompleteSearchObjects(search, results, "name", "html_url"); }, }); -const BaseParameterOptional = coda.makeParameter({ - type: coda.ParameterType.String, +const BaseParameterOptional = sdk.makeParameter({ + type: sdk.ParameterType.String, name: "base", description: 'The name of the base branch. For example, "main".', optional: true, }); -const PullRequestStateOptional = coda.makeParameter({ - type: coda.ParameterType.String, +const PullRequestStateOptional = sdk.makeParameter({ + type: sdk.ParameterType.String, name: "state", description: 'Returns pull requests in the given state. If unspecified, defaults to "open".', diff --git a/examples/github/schemas.ts b/examples/github/schemas.ts index 76de338..2628328 100644 --- a/examples/github/schemas.ts +++ b/examples/github/schemas.ts @@ -1,30 +1,30 @@ -import * as coda from "@superhuman/plugins-sdk"; +import * as sdk from "@superhuman/plugins-sdk"; // A user associated with an entity or action. This is a child property // in many other GitHub objects. // https://docs.github.com/en/free-pro-team@latest/rest/reference/users#get-a-user -export const UserSchema = coda.makeObjectSchema({ +export const UserSchema = sdk.makeObjectSchema({ // We list only the subset of fields we care about, the actual user objects // are much larger. properties: { - id: {type: coda.ValueType.Number, required: true}, - login: {type: coda.ValueType.String, required: true}, + id: {type: sdk.ValueType.Number, required: true}, + login: {type: sdk.ValueType.String, required: true}, // Using fromKey is a shortcut to avoid writing code to transform // GitHub's response to an object matching our schema. We simply specify // the name of the field in the GitHub response using fromKey, and Coda // will map it to the name of property declared here. avatar: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "avatar_url", // We return the image url of the GitHub user's avatar but declare it as // codaType: ImageAttachment, which instructs Coda to download the image // and host it from Coda for use in Coda docs. - codaType: coda.ValueHintType.ImageAttachment, + codaType: sdk.ValueHintType.ImageAttachment, }, url: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "html_url", - codaType: coda.ValueHintType.Url, + codaType: sdk.ValueHintType.Url, required: true, }, }, @@ -38,16 +38,16 @@ export const UserSchema = coda.makeObjectSchema({ // teams directly but they are embedded in other responses, representing // e.g. the teams requested to review a PR. // https://docs.github.com/en/free-pro-team@latest/rest/reference/teams#get-a-team-by-name -export const TeamSchema = coda.makeObjectSchema({ +export const TeamSchema = sdk.makeObjectSchema({ // We list only the subset of fields we care about, the actual team objects // are much larger. properties: { - id: {type: coda.ValueType.Number, required: true}, - name: {type: coda.ValueType.String, required: true}, + id: {type: sdk.ValueType.Number, required: true}, + name: {type: sdk.ValueType.String, required: true}, url: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "html_url", - codaType: coda.ValueHintType.Url, + codaType: sdk.ValueHintType.Url, required: true, }, }, @@ -59,21 +59,21 @@ export const TeamSchema = coda.makeObjectSchema({ // The response when creating a pull review request. // https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls#create-a-review-for-a-pull-request -export const PullRequestReviewResponseSchema = coda.makeObjectSchema({ +export const PullRequestReviewResponseSchema = sdk.makeObjectSchema({ // We list only the subset of fields we care about. properties: { - id: {type: coda.ValueType.Number, required: true}, + id: {type: sdk.ValueType.Number, required: true}, user: UserSchema, - body: {type: coda.ValueType.String, required: true}, + body: {type: sdk.ValueType.String, required: true}, commitId: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "commit_id", required: true, }, - state: {type: coda.ValueType.String, required: true}, + state: {type: sdk.ValueType.String, required: true}, url: { - type: coda.ValueType.String, - codaType: coda.ValueHintType.Url, + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.Url, fromKey: "html_url", required: true, }, @@ -87,20 +87,20 @@ export const PullRequestReviewResponseSchema = coda.makeObjectSchema({ // The handful of fields we care about for a Repo object. These are embedded // in PR objects. // https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#get-a-repository -export const RepoSchema = coda.makeObjectSchema({ +export const RepoSchema = sdk.makeObjectSchema({ properties: { - id: {type: coda.ValueType.Number, required: true}, - name: {type: coda.ValueType.String, required: true}, + id: {type: sdk.ValueType.Number, required: true}, + name: {type: sdk.ValueType.String, required: true}, fullName: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "full_name", required: true, }, - description: {type: coda.ValueType.String}, + description: {type: sdk.ValueType.String}, url: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "html_url", - codaType: coda.ValueHintType.Url, + codaType: sdk.ValueHintType.Url, required: true, }, }, @@ -118,68 +118,68 @@ export const RepoSchema = coda.makeObjectSchema({ // optional, are all required and important for creating a user-friendly table. // // https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls#get-a-pull-request -export const PullRequestSchema = coda.makeObjectSchema({ +export const PullRequestSchema = sdk.makeObjectSchema({ properties: { - title: {type: coda.ValueType.String, required: true}, + title: {type: sdk.ValueType.String, required: true}, author: { ...UserSchema, fromKey: "user", }, pullRequestNumber: { - type: coda.ValueType.Number, + type: sdk.ValueType.Number, fromKey: "number", required: true, }, url: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "html_url", - codaType: coda.ValueHintType.Url, + codaType: sdk.ValueHintType.Url, required: true, }, created: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "created_at", - codaType: coda.ValueHintType.Date, + codaType: sdk.ValueHintType.Date, required: true, }, modified: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "updated_at", - codaType: coda.ValueHintType.Date, + codaType: sdk.ValueHintType.Date, required: true, }, closed: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "closed_at", - codaType: coda.ValueHintType.Date, + codaType: sdk.ValueHintType.Date, }, merged: { - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "merged_at", - codaType: coda.ValueHintType.Date, - }, - mergeCommitSha: {type: coda.ValueType.String, fromKey: "merge_commit_sha"}, - body: {type: coda.ValueType.String, codaType: coda.ValueHintType.Markdown}, - labels: {type: coda.ValueType.Array, items: {type: coda.ValueType.String}}, - state: {type: coda.ValueType.String, required: true}, - sourceBranch: {type: coda.ValueType.String, required: true}, - targetBranch: {type: coda.ValueType.String, required: true}, - addedLineCount: {type: coda.ValueType.Number, fromKey: "additions"}, - deletedLineCount: {type: coda.ValueType.Number, fromKey: "deletions"}, - changedFileCount: {type: coda.ValueType.Number, fromKey: "changed_files"}, + codaType: sdk.ValueHintType.Date, + }, + mergeCommitSha: {type: sdk.ValueType.String, fromKey: "merge_commit_sha"}, + body: {type: sdk.ValueType.String, codaType: sdk.ValueHintType.Markdown}, + labels: {type: sdk.ValueType.Array, items: {type: sdk.ValueType.String}}, + state: {type: sdk.ValueType.String, required: true}, + sourceBranch: {type: sdk.ValueType.String, required: true}, + targetBranch: {type: sdk.ValueType.String, required: true}, + addedLineCount: {type: sdk.ValueType.Number, fromKey: "additions"}, + deletedLineCount: {type: sdk.ValueType.Number, fromKey: "deletions"}, + changedFileCount: {type: sdk.ValueType.Number, fromKey: "changed_files"}, mergedBy: {...UserSchema, fromKey: "merged_by"}, repo: {...RepoSchema, required: true}, assignees: { - type: coda.ValueType.Array, + type: sdk.ValueType.Array, items: UserSchema, }, reviewerUsers: { - type: coda.ValueType.Array, + type: sdk.ValueType.Array, items: UserSchema, fromKey: "requested_reviewers", }, reviewerTeams: { - type: coda.ValueType.Array, + type: sdk.ValueType.Array, items: TeamSchema, fromKey: "requested_teams", }, diff --git a/examples/github/test/github_integration.ts b/examples/github/test/github_integration.ts index 62bdead..56e4219 100644 --- a/examples/github/test/github_integration.ts +++ b/examples/github/test/github_integration.ts @@ -5,19 +5,19 @@ import {executeSyncFormulaFromPackDef} from "@superhuman/plugins-sdk/dist/develo import {it} from "mocha"; import {pack} from "../pack"; -describe("GitHub pack integration test", () => { +describe("GitHub plugin integration test", () => { it("executes PullRequests sync", async () => { - // Here we execute the sync using a real http fetcher. Since this pack + // Here we execute the sync using a real http fetcher. Since this plugin // requires authentication, this requires that you've already run - // `coda auth examples/github/packs.ts` to set up your OAuth credentials + // `packs auth examples/github/pack.ts` to set up your OAuth credentials // for GitHub. let response = await executeSyncFormulaFromPackDef( pack, "PullRequests", - // This integration test assumes you have access to the packs-examples + // This integration test assumes you have access to the plugins-examples // repo, which you should if you're looking at this example! [ - "https://github.com/coda/packs-examples", + "https://github.com/superhuman/plugins-examples", "", PullRequestStateFilter.All, ], @@ -34,7 +34,7 @@ describe("GitHub pack integration test", () => { // syncing all PRs and not just open ones, to guarantee we have at least // one PR to examine here. assert.isAtLeast(response.length, 1); - assert.equal(response[0].Repo.Name, "packs-examples"); + assert.equal(response[0].Repo.Name, "plugins-examples"); }); // You could similarly write an integration for the ReviewPullRequest diff --git a/examples/github/test/github_test.ts b/examples/github/test/github_test.ts index d54338e..3da0b95 100644 --- a/examples/github/test/github_test.ts +++ b/examples/github/test/github_test.ts @@ -18,7 +18,7 @@ import {pack} from "../pack"; import * as sinon from "sinon"; import {willBeRejectedWith} from "../../../lib/test_utils"; -describe("Github pack", () => { +describe("Github plugin", () => { describe("ReviewPullRequest", () => { let context: MockExecutionContext; @@ -257,7 +257,7 @@ describe("Github pack", () => { }); // We can even test the metadata formulas in the supporting - // parts of our pack. The repo url parameter to this sync table + // parts of our plugin. The repo url parameter to this sync table // has an autocomplete metadata formula to make it easier for users // to select the repo they want to sync from. This test exercises // that formula, which makes http requests to GitHub to listen diff --git a/examples/github/types.ts b/examples/github/types.ts index 829ded7..ea5e908 100644 --- a/examples/github/types.ts +++ b/examples/github/types.ts @@ -18,7 +18,7 @@ export enum PullRequestStateFilter { // Below are types for GitHub object responses. These only include the // subset of fields we -// care about for this pack. The actual responses are much larger. +// care about for this plugin. The actual responses are much larger. // https://docs.github.com/en/free-pro-team@latest/rest/reference/pulls#get-a-pull-request export interface GitHubPullRequest { diff --git a/examples/google-tables/README.md b/examples/google-tables/README.md index 8bb0314..dd59209 100644 --- a/examples/google-tables/README.md +++ b/examples/google-tables/README.md @@ -1,6 +1,6 @@ # Google Tables -This is an example Pack that syncs data from Google Tables (an Area 120 project). The primary purpose of this example is to demonstrate how to build a dynamic sync table with two-way sync enabled. +This is an example Plugin that syncs data from Google Tables (an Area 120 project). The primary purpose of this example is to demonstrate how to build a dynamic sync table with two-way sync enabled. ## Setup @@ -8,14 +8,14 @@ To run the example code and actually connect to Google Tables, you'll need to cr When configuring the OAuth settings you'll need to add **`http://localhost:3000/oauth`** as your "Redirect URIs" in order to run these examples locally. To run them on Coda after uploading & releasing, your authorization callback URL must change to be **`https://coda.io/packsAuth/oauth2/{PACK_ID}`**. -Run `coda auth examples/google-tables/pack.ts`. You'll be prompted to enter your client id and client secret, and then your browser will open and begin Google's OAuth flow. After the flow completes, the access token for that account will saved locally for use when executing formulas and syncs, so you only have to do this once. But you can run the command again to change to a different account, or to update your token if it becomes invalid. +Run `packs auth examples/google-tables/pack.ts`. You'll be prompted to enter your client id and client secret, and then your browser will open and begin Google's OAuth flow. After the flow completes, the access token for that account will saved locally for use when executing formulas and syncs, so you only have to do this once. But you can run the command again to change to a different account, or to update your token if it becomes invalid. ## Running the Example To sync a table run: ```bash -coda execute examples/google-tables/pack.ts Table --dynamicUrl="https://area120tables.googleapis.com/v1alpha1/tables/{TABLE_ID}" +packs execute examples/google-tables/pack.ts Table --dynamicUrl="https://area120tables.googleapis.com/v1alpha1/tables/{TABLE_ID}" ``` -To test two-way sync you'll need to upload the Pack and test it in a live doc. +To test two-way sync you'll need to upload the Plugin and test it in a live doc. diff --git a/examples/google-tables/convert.ts b/examples/google-tables/convert.ts index b0eabf6..59e2dee 100644 --- a/examples/google-tables/convert.ts +++ b/examples/google-tables/convert.ts @@ -10,8 +10,8 @@ import type {TablesDateTime} from "./types"; import type {TablesFile} from "./types"; import type {TablesLocation} from "./types"; import type {TablesTimestamp} from "./types"; -import * as coda from "@superhuman/plugins-sdk"; import {getTableUrl} from "./helpers"; +import * as sdk from "@superhuman/plugins-sdk"; const DriveOpenUrl = "https://drive.google.com/open"; const NanosPerMilli = 1000000; @@ -19,7 +19,7 @@ const MillisPerSecond = 1000; // Gets the column converter for a given column. export function getConverter( - context: coda.ExecutionContext, + context: sdk.ExecutionContext, column: Column, table: Table, ): ColumnConverter { @@ -86,15 +86,15 @@ export function getConverter( abstract class ColumnConverter { column: Column; table: Table; - context: coda.ExecutionContext; + context: sdk.ExecutionContext; - constructor(context: coda.ExecutionContext, column: Column, table: Table) { + constructor(context: sdk.ExecutionContext, column: Column, table: Table) { this.context = context; this.column = column; this.table = table; } - getSchema(): coda.Schema & coda.ObjectSchemaProperty { + getSchema(): sdk.Schema & sdk.ObjectSchemaProperty { let schema = this._getBaseSchema(); schema.fromKey = this.column.id; schema.fixedId = this.column.id; @@ -120,7 +120,7 @@ abstract class ColumnConverter { } // Each implementation must define the base property schema. - abstract _getBaseSchema(): coda.Schema & coda.ObjectSchemaProperty; + abstract _getBaseSchema(): sdk.Schema & sdk.ObjectSchemaProperty; // Default to passing through the value as-is, in both directions. formatValueForSchema(value: T): C { @@ -133,33 +133,33 @@ abstract class ColumnConverter { class TextColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, + return sdk.makeSchema({ + type: sdk.ValueType.String, }); } } class NumberColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.Number, + return sdk.makeSchema({ + type: sdk.ValueType.Number, }); } } class BooleanColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.Boolean, + return sdk.makeSchema({ + type: sdk.ValueType.Boolean, }); } } class DateColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, - codaType: coda.ValueHintType.Date, + return sdk.makeSchema({ + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.Date, }); } @@ -183,9 +183,9 @@ class DateColumnConverter extends ColumnConverter { class DateTimeColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, - codaType: coda.ValueHintType.DateTime, + return sdk.makeSchema({ + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.DateTime, }); } @@ -227,11 +227,11 @@ class DateTimeColumnConverter extends ColumnConverter { class PersonColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeObjectSchema({ - codaType: coda.ValueHintType.Person, + return sdk.makeObjectSchema({ + codaType: sdk.ValueHintType.Person, properties: { - name: {type: coda.ValueType.String}, - email: {type: coda.ValueType.String, required: true}, + name: {type: sdk.ValueType.String}, + email: {type: sdk.ValueType.String, required: true}, }, displayProperty: "name", idProperty: "email", @@ -252,10 +252,10 @@ class PersonColumnConverter extends ColumnConverter { class SelectListColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, - codaType: coda.ValueHintType.SelectList, - options: coda.OptionsType.Dynamic, + return sdk.makeSchema({ + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.SelectList, + options: sdk.OptionsType.Dynamic, }); } } @@ -266,7 +266,7 @@ class MultiSelectListColumnConverter extends ColumnConverter< > { selectListConverter: SelectListColumnConverter; - constructor(context: coda.ExecutionContext, column: Column, table: Table) { + constructor(context: sdk.ExecutionContext, column: Column, table: Table) { super(context, column, table); this.selectListConverter = new SelectListColumnConverter( context, @@ -276,8 +276,8 @@ class MultiSelectListColumnConverter extends ColumnConverter< } _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.Array, + return sdk.makeSchema({ + type: sdk.ValueType.Array, items: this.selectListConverter._getBaseSchema(), }); } @@ -285,11 +285,11 @@ class MultiSelectListColumnConverter extends ColumnConverter< class DriveFilesColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.Array, + return sdk.makeSchema({ + type: sdk.ValueType.Array, items: { - type: coda.ValueType.String, - codaType: coda.ValueHintType.Url, + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.Url, }, // Can't reasonably edit these in Coda. mutable: false, @@ -298,7 +298,7 @@ class DriveFilesColumnConverter extends ColumnConverter { formatValueForSchema(value: DriveFile[]) { return value.map(driveFile => { - return coda.withQueryParams(DriveOpenUrl, { + return sdk.withQueryParams(DriveOpenUrl, { id: driveFile.id, }); }); @@ -307,11 +307,11 @@ class DriveFilesColumnConverter extends ColumnConverter { class FilesColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.Array, + return sdk.makeSchema({ + type: sdk.ValueType.Array, items: { - type: coda.ValueType.String, - codaType: coda.ValueHintType.Attachment, + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.Attachment, }, // Can't reasonably edit these in Coda. mutable: false, @@ -325,8 +325,8 @@ class FilesColumnConverter extends ColumnConverter { class LocationColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, + return sdk.makeSchema({ + type: sdk.ValueType.String, // Can't reasonably edit these in Coda. mutable: false, }); @@ -342,7 +342,7 @@ class RelationshipColumnConverter extends ColumnConverter< RowReference > { _getBaseSchema() { - let referenceSchema = coda.makeReferenceSchemaFromObjectSchema( + let referenceSchema = sdk.makeReferenceSchemaFromObjectSchema( BaseRowSchema, "Table", ); @@ -369,9 +369,9 @@ class TimestampColumnConverter extends ColumnConverter< string > { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, - codaType: coda.ValueHintType.DateTime, + return sdk.makeSchema({ + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.DateTime, }); } @@ -394,8 +394,8 @@ class TimestampColumnConverter extends ColumnConverter< class UnknownColumnConverter extends ColumnConverter { _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.String, + return sdk.makeSchema({ + type: sdk.ValueType.String, mutable: false, }); } @@ -414,8 +414,8 @@ class ListColumnConverter extends ColumnConverter { } _getBaseSchema() { - return coda.makeSchema({ - type: coda.ValueType.Array, + return sdk.makeSchema({ + type: sdk.ValueType.Array, items: this.baseConverter._getBaseSchema(), }); } diff --git a/examples/google-tables/helpers.ts b/examples/google-tables/helpers.ts index 8cf23b8..afb4761 100644 --- a/examples/google-tables/helpers.ts +++ b/examples/google-tables/helpers.ts @@ -2,22 +2,22 @@ import type {CodaRow} from "./types"; import type {Column} from "./types"; import type {Row} from "./types"; import type {Table} from "./types"; -import * as coda from "@superhuman/plugins-sdk"; import {getConverter} from "./convert"; +import * as sdk from "@superhuman/plugins-sdk"; const BaseUrl = "https://area120tables.googleapis.com/v1alpha1"; const PageSize = 100; const ShortCacheTimeSecs = 60; export function getTableUrl(tableName: string): string { - return coda.joinUrl(BaseUrl, tableName); + return sdk.joinUrl(BaseUrl, tableName); } // Get the available tables from the API. export async function getTables( - context: coda.ExecutionContext, + context: sdk.ExecutionContext, ): Promise { - let url = coda.withQueryParams(coda.joinUrl(BaseUrl, "tables"), { + let url = sdk.withQueryParams(sdk.joinUrl(BaseUrl, "tables"), { pageSize: PageSize, }); let response = await context.fetcher.fetch({ @@ -30,7 +30,7 @@ export async function getTables( // Get a specific table from the API. export async function getTable( - context: coda.ExecutionContext, + context: sdk.ExecutionContext, tableUrl: string, ): Promise { let response = await context.fetcher.fetch({ @@ -43,11 +43,11 @@ export async function getTable( // Get a page of table rows from the API. export async function getRows( - context: coda.ExecutionContext, + context: sdk.ExecutionContext, tableUrl: string, pageToken?: string, ): Promise<{rows: Row[]; nextPageToken?: string}> { - let url = coda.withQueryParams(coda.joinUrl(tableUrl, "rows"), { + let url = sdk.withQueryParams(sdk.joinUrl(tableUrl, "rows"), { view: "COLUMN_ID_VIEW", pageSize: PageSize, pageToken: pageToken, @@ -61,10 +61,10 @@ export async function getRows( // Update a table row using the API. export async function updateRow( - context: coda.UpdateSyncExecutionContext, + context: sdk.UpdateSyncExecutionContext, row: Row, ) { - let url = coda.withQueryParams(coda.joinUrl(BaseUrl, row.name), { + let url = sdk.withQueryParams(sdk.joinUrl(BaseUrl, row.name), { view: "COLUMN_ID_VIEW", }); try { @@ -79,12 +79,12 @@ export async function updateRow( return response.body; } catch (error) { if ( - coda.StatusCodeError.isStatusCodeError(error) && + sdk.StatusCodeError.isStatusCodeError(error) && // Don't swallow 401's, since they are needed to trigger an OAuth refresh. error.statusCode !== 401 ) { if (error.body?.error) { - throw new coda.UserVisibleError(error.body.error.message); + throw new sdk.UserVisibleError(error.body.error.message); } } throw error; @@ -94,8 +94,8 @@ export async function updateRow( export function getPropertySchema( column: Column, table: Table, - context: coda.ExecutionContext, -): (coda.Schema & coda.ObjectSchemaProperty) | undefined { + context: sdk.ExecutionContext, +): (sdk.Schema & sdk.ObjectSchemaProperty) | undefined { let converter = getConverter(context, column, table); return converter.getSchema(); } @@ -103,7 +103,7 @@ export function getPropertySchema( export function formatRowForSchema( row: Row, table: Table, - context: coda.ExecutionContext, + context: sdk.ExecutionContext, label: string, ): CodaRow { let result: CodaRow = { @@ -127,7 +127,7 @@ export function formatRowForSchema( export function formatRowForApi( row: CodaRow, table: Table, - context: coda.ExecutionContext, + context: sdk.ExecutionContext, ): Row { let result: Row = { name: row.name, diff --git a/examples/google-tables/pack.ts b/examples/google-tables/pack.ts index 6861876..4287b39 100644 --- a/examples/google-tables/pack.ts +++ b/examples/google-tables/pack.ts @@ -1,6 +1,5 @@ import type {CodaRow} from "./types"; import type {RowsContinuation} from "./types"; -import * as coda from "@superhuman/plugins-sdk"; import {formatRowForApi} from "./helpers"; import {formatRowForSchema} from "./helpers"; import {getPropertySchema} from "./helpers"; @@ -8,26 +7,27 @@ import {getRows} from "./helpers"; import {getTable} from "./helpers"; import {getTableUrl} from "./helpers"; import {getTables} from "./helpers"; +import * as sdk from "@superhuman/plugins-sdk"; import {updateRow} from "./helpers"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); // A base schema, extended with additional properties depending on the table. -export const BaseRowSchema = coda.makeObjectSchema({ +export const BaseRowSchema = sdk.makeObjectSchema({ properties: { rowId: { description: "Internal ID of the row.", - type: coda.ValueType.String, + type: sdk.ValueType.String, fromKey: "name", required: true, }, rowLabel: { - type: coda.ValueType.String, + type: sdk.ValueType.String, required: true, }, lastUpdated: { - type: coda.ValueType.String, - codaType: coda.ValueHintType.DateTime, + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.DateTime, fromKey: "updateTime", }, }, @@ -58,7 +58,7 @@ pack.addDynamicSyncTable({ value: getTableUrl(table.name), }; }); - return coda.autocompleteSearchObjects(search, results, "display", "value"); + return sdk.autocompleteSearchObjects(search, results, "display", "value"); }, getName: async function (context) { let tableUrl = context.sync!.dynamicUrl!; @@ -68,7 +68,7 @@ pack.addDynamicSyncTable({ getSchema: async function (context) { let tableUrl = context.sync!.dynamicUrl!; let table = await getTable(context, tableUrl); - let schema: coda.GenericObjectSchema = { + let schema: sdk.GenericObjectSchema = { ...BaseRowSchema, properties: { ...BaseRowSchema.properties, @@ -87,7 +87,7 @@ pack.addDynamicSyncTable({ getDisplayUrl: async function (context) { let tableUrl = context.sync!.dynamicUrl!; let tableId = tableUrl.split("/").pop() as string; - return coda.joinUrl("https://tables.area120.google.com/table", tableId); + return sdk.joinUrl("https://tables.area120.google.com/table", tableId); }, // Get the options for select list columns. propertyOptions: async function (context) { @@ -173,7 +173,7 @@ pack.addDynamicSyncTable({ }); pack.setUserAuthentication({ - type: coda.AuthenticationType.OAuth2, + type: sdk.AuthenticationType.OAuth2, authorizationUrl: "https://accounts.google.com/o/oauth2/v2/auth", tokenUrl: "https://oauth2.googleapis.com/token", scopes: ["profile", "https://www.googleapis.com/auth/tables"], diff --git a/examples/google-tables/types.ts b/examples/google-tables/types.ts index 4fc96f0..553f4af 100644 --- a/examples/google-tables/types.ts +++ b/examples/google-tables/types.ts @@ -1,4 +1,4 @@ -import type * as coda from "@superhuman/plugins-sdk"; +import type * as sdk from "@superhuman/plugins-sdk"; // Google Tables API types. @@ -78,7 +78,7 @@ export interface TablesTimestamp { nanos: number; } -// Custom types for this Pack. +// Custom types for this Plugin. export interface CodaRow extends Record { name: string; @@ -86,7 +86,7 @@ export interface CodaRow extends Record { updateTime?: string; } -export interface RowsContinuation extends coda.Continuation { +export interface RowsContinuation extends sdk.Continuation { pageToken: string; rowNumber: number; } diff --git a/examples/template/pack.ts b/examples/template/pack.ts index 69f08ce..3f25788 100644 --- a/examples/template/pack.ts +++ b/examples/template/pack.ts @@ -1,3 +1,3 @@ -import * as coda from "@superhuman/plugins-sdk"; +import * as sdk from "@superhuman/plugins-sdk"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); diff --git a/examples/trigonometry/README.md b/examples/trigonometry/README.md index 18ecfe7..aa8e8b9 100644 --- a/examples/trigonometry/README.md +++ b/examples/trigonometry/README.md @@ -1,6 +1,6 @@ -# Trigonometry Pack +# Trigonometry Plugin -This is one of the simplest possible Packs, it just creates Coda wrappers for built-in +This is one of the simplest possible Plugins, it just creates Coda wrappers for built-in JavaScript formulas to expose them in Coda. It defines a handful of formulas which each take a numeric parameter and return a number. @@ -9,7 +9,7 @@ delegating to a built-in JavaScript `Math` function or performing a simple calcu ## Running the Tests -Run the test just for this Pack by using: +Run the test just for this Plugin by using: ```bash mocha --require ts-node/register examples/trigonometry/test/trigonometry_test.ts diff --git a/examples/trigonometry/pack.ts b/examples/trigonometry/pack.ts index 20ae68f..601950e 100644 --- a/examples/trigonometry/pack.ts +++ b/examples/trigonometry/pack.ts @@ -1,21 +1,21 @@ -import * as coda from "@superhuman/plugins-sdk"; +import * as sdk from "@superhuman/plugins-sdk"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); -const DegreesParameter = coda.makeParameter({ - type: coda.ParameterType.Number, +const DegreesParameter = sdk.makeParameter({ + type: sdk.ParameterType.Number, name: "angle", description: "An angle measured in degrees.", }); -const RadiansParameter = coda.makeParameter({ - type: coda.ParameterType.Number, +const RadiansParameter = sdk.makeParameter({ + type: sdk.ParameterType.Number, name: "angle", description: "An angle measured in radians.", }); pack.addFormula({ - resultType: coda.ValueType.Number, + resultType: sdk.ValueType.Number, name: "Sine", description: "Returns the angle (in radians) whose sine is the given number", parameters: [RadiansParameter], @@ -24,7 +24,7 @@ pack.addFormula({ }); pack.addFormula({ - resultType: coda.ValueType.Number, + resultType: sdk.ValueType.Number, name: "Cosine", description: "Returns the cosine of a number (in radians).", parameters: [RadiansParameter], @@ -33,7 +33,7 @@ pack.addFormula({ }); pack.addFormula({ - resultType: coda.ValueType.Number, + resultType: sdk.ValueType.Number, name: "Tangent", description: "Returns the tangent of a number (in radians).", parameters: [RadiansParameter], @@ -42,7 +42,7 @@ pack.addFormula({ }); pack.addFormula({ - resultType: coda.ValueType.Number, + resultType: sdk.ValueType.Number, name: "ToRadians", description: "Converts degrees to radians.", parameters: [DegreesParameter], @@ -51,7 +51,7 @@ pack.addFormula({ }); pack.addFormula({ - resultType: coda.ValueType.Number, + resultType: sdk.ValueType.Number, name: "ToDegrees", description: "Converts radians to degrees.", parameters: [RadiansParameter], diff --git a/examples/trigonometry/test/trigonometry_test.ts b/examples/trigonometry/test/trigonometry_test.ts index ede0633..9435f5f 100644 --- a/examples/trigonometry/test/trigonometry_test.ts +++ b/examples/trigonometry/test/trigonometry_test.ts @@ -4,9 +4,9 @@ import {executeFormulaFromPackDef} from "@superhuman/plugins-sdk/dist/developmen import {it} from "mocha"; import {pack} from "../pack"; -describe("Trigonometry pack", () => { +describe("Trigonometry plugin", () => { it("executes Cosine", async () => { - // Since our pack doesn't make any fetcher calls, we can very simply + // Since our plugin doesn't make any fetcher calls, we can very simply // invoke formulas directly with the default mock execution context. assert.equal(1, await executeFormulaFromPackDef(pack, "Cosine", [0])); assert.approximately( diff --git a/examples/vonage/README.md b/examples/vonage/README.md index 19219d3..9fa2682 100644 --- a/examples/vonage/README.md +++ b/examples/vonage/README.md @@ -1,18 +1,18 @@ -# Vonage - -This is an example Pack that syncs data from Vonage. The primary purpose of this example is to demonstrate how to perform JWT (JSON Web Token) authentication in a Pack. - -Coda doesn't yet have native support for JWT authentication, but when the API uses a shared set of system credentials you can approximate it. This example stores the shared credentials in a file and uses the `jsrsasign` library to generate the JWT. When using this pattern in your own Packs make sure not to check the credentials file into your version control system. - -## Setup - -To run the example code and actually connect to Vonage, you'll need to sign up for a Vonage account and create a new application. This can be done using the [Vonage API Dashboard](https://dashboard.nexmo.com/). After you have created the application, enter the generated application ID and private key in to the `credentials.ts` file. - - -## Running the Example - -To sync the list of conversations run: - -```bash -coda execute examples/vonage/pack.ts Conversations -``` +# Vonage + +This is an example Plugin that syncs data from Vonage. The primary purpose of this example is to demonstrate how to perform JWT (JSON Web Token) authentication in a Plugin. + +Coda doesn't yet have native support for JWT authentication, but when the API uses a shared set of system credentials you can approximate it. This example stores the shared credentials in a file and uses the `jsrsasign` library to generate the JWT. When using this pattern in your own Plugins make sure not to check the credentials file into your version control system. + +## Setup + +To run the example code and actually connect to Vonage, you'll need to sign up for a Vonage account and create a new application. This can be done using the [Vonage API Dashboard](https://dashboard.nexmo.com/). After you have created the application, enter the generated application ID and private key in to the `credentials.ts` file. + + +## Running the Example + +To sync the list of conversations run: + +```bash +packs execute examples/vonage/pack.ts Conversations +``` diff --git a/examples/vonage/credentials.ts b/examples/vonage/credentials.ts index 41f19d1..8dc0763 100644 --- a/examples/vonage/credentials.ts +++ b/examples/vonage/credentials.ts @@ -1,4 +1,4 @@ -// A file to hold the credentials used by the Pack. +// A file to hold the credentials used by the Plugin. // It's not possible to use the SDK's system authentication and store these in // Coda directly since you need direct access to the values in order to create diff --git a/examples/vonage/pack.ts b/examples/vonage/pack.ts index cbae6a8..2110ac6 100644 --- a/examples/vonage/pack.ts +++ b/examples/vonage/pack.ts @@ -1,23 +1,23 @@ -import * as coda from "@superhuman/plugins-sdk"; import * as credentials from "./credentials"; import * as rs from "jsrsasign"; +import * as sdk from "@superhuman/plugins-sdk"; -export const pack = coda.newPack(); +export const pack = sdk.newPack(); -const ConversationSchema = coda.makeObjectSchema({ +const ConversationSchema = sdk.makeObjectSchema({ properties: { id: { - type: coda.ValueType.String, + type: sdk.ValueType.String, }, name: { - type: coda.ValueType.String, + type: sdk.ValueType.String, }, display_name: { - type: coda.ValueType.String, + type: sdk.ValueType.String, }, image: { - type: coda.ValueType.String, - codaType: coda.ValueHintType.ImageReference, + type: sdk.ValueType.String, + codaType: sdk.ValueHintType.ImageReference, fromKey: "image_url", }, }, @@ -76,7 +76,7 @@ pack.addSyncTable({ // Create a JWT using the application ID and private key in credentials.ts. // See https://developer.vonage.com/en/getting-started/concepts/authentication#json-web-tokens -function createJwt(context: coda.ExecutionContext) { +function createJwt(context: sdk.ExecutionContext) { let now = Date.now() / 1000; let header = { alg: "RS256", diff --git a/package.json b/package.json index b4daf1d..7eb8e5b 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@superhuman/plugins-examples", "version": "0.0.1", - "description": "Examples of Coda (coda.io) packs.", + "description": "Examples of Superhuman Plugins.", "main": "index.js", "scripts": { "test": "mocha --require ts-node/register examples/**/*_test.ts", @@ -9,17 +9,17 @@ "compile": "tsc --noEmit", "lint": "find . -name \"*.ts\" | grep -v /node_modules/ | grep -v .d.ts | xargs node_modules/.bin/eslint", "lint-fix": "find . -name \"*.ts\" | grep -v /node_modules/ | grep -v .d.ts | xargs node_modules/.bin/eslint --fix", - "validate": "find examples/**/pack.ts -name '*.ts' | xargs -n1 -I {} sh -c 'NODE_OPTIONS=\"--no-deprecation\" coda validate {} || echo \"While validating {}\n\";'" + "validate": "find examples/**/pack.ts -name '*.ts' | xargs -n1 -I {} sh -c 'NODE_OPTIONS=\"--no-deprecation\" packs validate {} || echo \"While validating {}\n\";'" }, "repository": { "type": "git", - "url": "git+https://github.com/coda/packs-examples.git" + "url": "git+https://github.com/superhuman/plugins-examples.git" }, "license": "MIT", "bugs": { - "url": "https://github.com/coda/packs-examples/issues" + "url": "https://github.com/superhuman/plugins-examples/issues" }, - "homepage": "https://github.com/coda/packs-examples#readme", + "homepage": "https://github.com/superhuman/plugins-examples#readme", "engines": { "npm": ">=9", "node": ">=22.0.0"