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

coda-js

v4.2.0

Published

An eloquent Node API for interacting with your Coda Docs.

Downloads

2,225

Readme

An eloquent Node API for interacting with your Coda Docs. This API utilizes the Coda REST API.

npm npm type definitions npm bundle size


Features

  • list or get specific Folder, Section, Doc, Table, Column, Row, and Control information
  • query, insert, update, or delete table data
  • more formatting options than Coda's REST API for inserting or retrieving row values
  • an eloquent API (see examples)
  • handle Coda error types

Installation

# yarn
$ yarn add coda-js

# npm
$ npm install --save coda-js

Usage

This API uses the same method names as found in the Coda Docs. Review them for additional methods. Note that using item IDs is best (doesn't change), but each parameter that accepts an ID also accepts the name for convenience. All methods can be used from the base instance or from their respective parent. For example:

// uses two requests, but makes sense when you don't know all information ahead of time
const doc = await coda.getDoc('O7d9JvX0GY');
const table = await doc.getTable('grid-_14oaR8gdM');

could be consolidated into:

// uses only one request, which is best when you already know the exact IDs to get the item(s) directly
await coda.getTable('O7d9JvX0GY', 'grid-_14oaR8gdM');

Notice

Be aware that inserting, updating, and deleting methods are not synchronous. They return true if the operation successfully added the request to Coda's API queue. It does not directly mean that the operation was successful or that it is complete. As of v1 of the Coda API, there is a way to check if a mutation has finished. See the section on Checking Request Status to learn how to detect when an operation is completed.

Token

Generate your token in your Coda profile settings. Notice: Everyone with this token has full access to all your docs! It is recommended to not use this client-side or anywhere your API token could be found.

Pagination

Coda's v1 API added a more complete pagination system. Read the docs or the Pagination section in the Migration Guide.

TODOs

  • [ ] add formulas API

Examples

Please note that the examples are currently only displaying async/await usage. You may use any strategy to handle the returned promises.

Testing Connection

import { Coda } from 'coda-js';

const coda = new Coda('**********-********-*********'); // insert your token

// trick for using async in a script
(async () => {
  const whoAmI = await coda.whoAmI();
  console.log(whoAmI);
})().catch((error) => console.log(error));

Retrieving Data (List/Get)

const docs = await coda.listDocs();
console.log(docs);

const firstDoc = docs[0];
const firstDocTables = await firstDoc.listTables();
console.log(firstDocTables);

const columns = await firstDocTables[0].listColumns();
console.log(columns.map((column) => column.name)); // list column names

const table = docs.getTable('grid-**********'); // insert/inject table name or ID here
const rows = await table.listRows({
  useColumnNames: true, // param to display column names rather than key
});
const firstRow = rows[0];
console.log(firstRow.values); // column/value pairs
console.log(firstRow.listValues()); // each column is object with column and value properties

const tableType = table.tableType;
const parentTable = tableType === 'view' ? return table.parentTable : table; // if the table is a view, we can access its parent Table
console.log(parentTable.id);

const controls = await coda.listControls('some-doc-ID');
// or
const controls = await firstDoc.listControls();

Inserting

Inserting also has an optional second parameter of keyColumns that allows for an "upsert". If keyColumns is not specified, or the passed array is empty, the call returns an addedRowIds value which is an array of strings specifying the ID for each inserted row. See Coda documentation for details.

// inserting using object
await table.insertRows([
  {
    Name: 'Jacob',
    Action: 'Take out the trash',
    Completed: true,
  },
]);

// inserting via column objects
await table.insertRows([
  [
    { column: 'Name', value: 'Alexis' },
    { column: 'Action', value: 'Do the dishes' },
  ],
  [
    { column: 'Name', value: 'Parker' },
    { column: 'Action', value: 'Make dinner' },
    { column: 'Completed', value: true },
  ],
]);

Updating

// updating (using column name instead of ID)
await table.updateRow('i-cpDDo9hAEU', {
  Completed: false,
});

// updating via column objects
await table.updateRow('i-dF2-OoiiUi', [{ column: 'Action', value: 'Make the bed' }]);

// updating off of an already fetched row
await row2.update({
  'ai-dRD9afcc8': 'To the moon, Alice!',
});

Deleting

// delete row directly
const row4 = await table.getRow('i-Ef2-OoZxIi');
await row4.delete();

// delete row from table
await table.deleteRow('i-cpDDoshUEU');

// deleting multiple rows from table
await table.deleteRows(['i-cpDDoshUEU', 'i-jj81vtosO1']);

Checking Request Status

Inserting, updating, and deleting in Coda is not always processed immediately. Check the mutation status if you need to make sure it was completed:

// for an update
const request = await todo.update({
  Completed: !completed,
});
const requestCompleted = await request.isCompleted();

// for a delete
const request = await table.deleteRow('i-cpDDoshUEU');
if (await request.isCompleted()) {
  // ... do something
}

// a little more manually
const requestCompleted = await coda.mutationStatus('some-request-id');

Error Handling

Error types:

  • BadRequestError (400)
  • UnauthorizedError (401)
  • ForbiddenError (403)
  • NotFoundError (404)
  • GoneError (410)
  • TooManyRequestsError (429)
import { Coda, UnauthorizedError, NotFoundError } from '../index';
const coda = new Coda(process.env.TOKEN);

// doesn't have access to view docs
try {
  await coda.listDocs();
} catch (error) {
  // error is instance of UnauthorizedError
  // can also determine based on (error.name === 'UnauthorizedError')
}

// fails to find a doc with a bad ID
try {
  const BAD_DOC_ID = 'd-ckjd1013kkk';
  await coda.listTables(BAD_DOC_ID);
} catch (error) {
  // error is instance of NotFoundError
  // can also determine based on (error.name === 'NotFoundError')
}