Skip to content

Public Read-Only Mode

HolySheets! supports a public read-only mode that lets you query public Google Sheets without any authentication setup. This is ideal for dashboards, static sites, public datasets, and rapid prototyping.

Under the hood, this mode uses the Google Visualization API to execute SQL-like queries server-side, returning only the matching rows.


Prerequisites

Your Google Sheet must be accessible publicly. Either:

  • Publish the spreadsheet via File → Share → Publish to the web, or
  • Share it as "Anyone with the link can view".

No service account, OAuth setup, or API key is required.


Getting Started

Typescript
import HolySheets from 'holysheets'

const reader = HolySheets.public({
  spreadsheetId: 'YOUR_PUBLIC_SPREADSHEET_ID'
})

const table = reader.base<{ name: string; age: string; city: string }>('Sheet1')

The HolySheets.public() factory returns a reader instance. Calling .base<T>('SheetName') sets the target sheet and returns a typed reader with only find methods.


Available Methods

In public mode, only read operations are available:

MethodDescription
findManyReturns all records matching the where clause.
findFirstReturns the first matching record.
findUniqueReturns the single matching record (throws if multiple).
findLastReturns the last matching record.
findManyOrThrowLike findMany, but throws if no records are found.
findFirstOrThrowLike findFirst, but throws if no records are found.
findUniqueOrThrowLike findUnique, but throws if none or multiple.
findLastOrThrowLike findLast, but throws if no records are found.

Write methods (insert, update, delete, clear) are not present on the public reader at the type level, so TypeScript will prevent you from calling them.


Examples

Finding Multiple Records

Typescript
const results = await table.findMany({
  where: { city: { equals: 'NYC' } }
})
console.log(results)
// [{ name: 'John', age: '30', city: 'NYC' }, ...]

Finding the First Record

Typescript
const first = await table.findFirst({
  where: { name: { startsWith: 'A' } }
})
console.log(first)
// { name: 'Alice', age: '28', city: 'SF' }

Using select to Limit Fields

Typescript
const results = await table.findMany({
  where: { age: { gt: 25 } },
  select: ['name', 'city']
})
console.log(results)
// [{ name: 'John', city: 'NYC' }, { name: 'Alice', city: 'SF' }]

Using omit to Exclude Fields

Typescript
const results = await table.findFirst({
  omit: ['age']
})
console.log(results)
// { name: 'John', city: 'NYC' }

Finding a Unique Record

Typescript
const record = await table.findUnique({
  where: { name: { equals: 'Alice' } }
})
console.log(record)
// { name: 'Alice', age: '28', city: 'SF' }

Note: findUnique throws a MultipleRecordsFoundForUniqueError if more than one record matches.

Handling Missing Records

Typescript
try {
  await table.findFirstOrThrow({
    where: { name: { equals: 'Nobody' } }
  })
} catch (error) {
  // RecordNotFoundError
  console.log('No record found')
}

Using with Schema

You can define a schema for type coercion and validation, just like in authenticated mode:

Typescript
import HolySheets, { DataTypes } from 'holysheets'

interface Product {
  name: string
  price: number
  active: boolean
}

const reader = HolySheets.public({ spreadsheetId: '...' })

const products = reader
  .base<Product>('Products')
  .defineSchema([
    { key: 'name', type: DataTypes.STRING },
    { key: 'price', type: DataTypes.NUMBER },
    { key: 'active', type: DataTypes.BOOLEAN }
  ])

const expensive = await products.findMany({
  where: { price: { gt: 100 } }
})

Custom Header Row

If your headers are not on the first row, specify headerRow:

Typescript
const table = reader.base<MyType>('Sheet1', { headerRow: 2 })

Where Filters

Public mode supports the same where filters as authenticated mode. See the Where Filters reference for the full list of available operators (equals, not, contains, startsWith, endsWith, gt, lt, in, notIn, search, etc.).


Comparison with Authenticated Mode

FeatureAuthenticated ModePublic Mode
Read operations (find)
Insert, update, delete, clear
Requires auth credentials
Works with private sheets
Schema support
Where filters
Select / Omit
Server-side filtering

Note: In public mode, filtering happens server-side via the Google Visualization API, which can be more efficient for large sheets since only matching rows are transferred.


API Reference

HolySheets.public(credentials)

Creates a public reader instance.

ParameterTypeDescription
spreadsheetIdstringThe ID of the public Google Spreadsheet.

Returns: A public reader instance with .base() and .defineSchema() methods.

.base<RecordType>(sheetName, options?)

Sets the target sheet.

ParameterTypeDefaultDescription
sheetNamestringThe name of the sheet (tab).
headerRownumber1The row number of the header.

Returns: A typed reader with find methods.

Released under the MIT License.