Skip to content

Daylight sample

This Pack provides a Daylight formula that determines the daylight, sunrise, and sunset at a given location using the Sunrise Sunset API. It accepts a latitude, longitude, an optional date and returns a rich object (schema) as a result. It uses the Fetcher to pull data from an external API.

/**
 * This Pack provides a "Daylight" formula that determines the daylight,
 * sunrise, and sunset at a given location using the Sunrise Sunset API.
 * The results are returns as a rich object.
 * @see {@link https://sunrise-sunset.org/api|Sunrise Sunset API}
 */

// This import statement provides access to all parts of the Coda Packs SDK.
import * as coda from "@codahq/packs-sdk";

// This line creates the new Pack.
export const pack = coda.newPack();

// The domain that the Pack will match fetcher requests to.
pack.addNetworkDomain("sunrise-sunset.org");

// Define a schema that will be used to bundle up the multiple pieces of data
// our formula will return. In the Coda doc this will be displayed as a chip.
const SunSchema = coda.makeObjectSchema({
  properties: {
    // The values we return are simple strings, but we use the codaType field to
    // to tell Coda to interpret them as durations and time values.
    daylight: {
      description: "How much daylight there will be.",
      type: coda.ValueType.String,
      codaType: coda.ValueHintType.Duration,
    },
    sunriseUTC: {
      description: "When the sun will rise (in UTC).",
      type: coda.ValueType.String,
      codaType: coda.ValueHintType.Time,
    },
    sunsetUTC: {
      description: "When the sun will set (in UTC).",
      type: coda.ValueType.String,
      codaType: coda.ValueHintType.Time,
    },
  },
  // Which of the properties defined above will be shown inside the chip.
  primary: "daylight",
});

// Add a "Daylight" formula to the Pack.
pack.addFormula({
  name: "Daylight",
  description: "Returns the sunrise and sunset for a given location.",

  // This formula takes two required numeric inputs (the latitude and longitude)
  // and one optional date.
  parameters: [
    coda.makeParameter({
      type: coda.ParameterType.Number,
      name: "lat",
      description: "The latitude to use.",
    }),
    coda.makeParameter({
      type: coda.ParameterType.Number,
      name: "lng",
      description: "The longitude to use.",
    }),
    coda.makeParameter({
      type: coda.ParameterType.Date,
      name: "date",
      description: "The date to use. Defaults to today.",
      // This date parameter is an optional input.
      optional: true,
    }),
  ],

  // In this formula, we're returning an object with multiple properties.
  resultType: coda.ValueType.Object,

  // This object will be defined according to the schema written above.
  schema: SunSchema,

  // Everything inside this execute statement will happen anytime the Coda
  // formula is called in a doc. An array of all user inputs is passed as the
  // first parameter. The context object is always the second parameter and is
  // used for fetching data.
  execute: async function ([lat, lng, date], context) {
    // Default to today if no date is provided.
    let lookupDate = date || new Date();

    // Format date to yyyy-mm-dd format as required by this API.
    let formattedDate = lookupDate.toISOString().split("T")[0];

    // Create the URL to fetch, using the helper function coda.withQueryParams
    // to add on query parameters (ex: "?lat=40.123...").
    let url = coda.withQueryParams("https://api.sunrise-sunset.org/json", {
      lat: lat,
      lng: lng,
      date: formattedDate
    });

    // Fetch the URL and get the response.
    let response = await context.fetcher.fetch({
      method: "GET",
      url: url
    });

    // The JSON returned by the API is parsed automatically and available in
    // `response.body`. Here we pull out the content in the "results" key.
    let results = response.body.results;

    // Re-format the day_length string to [h] hrs [m] mins [s] secs to work as a
    // duration.
    let hours = results.day_length.split(":")[0];
    let mins = results.day_length.split(":")[1];
    let secs = results.day_length.split(":")[2];

    let daylight = `${hours} hrs ${mins} mins ${secs} secs`;

    // Return the final object. The keys here must match with the properties
    // defined above in the schema.
    return {
      daylight: daylight,
      sunriseUTC: response.body.results.sunrise,
      sunsetUTC: response.body.results.sunset,
    };
  },
});