Skip to content

Repository files navigation

Google Apps Script + Vite

Plantilla base para construir una web app de Google Apps Script usando Vite y publicar el resultado con clasp.

Flujo básico

  1. Instala dependencias con pnpm install.
  2. Copia .clasp.json.example a .clasp.json.
  3. Reemplaza scriptId con el ID de tu proyecto de Apps Script.
  4. Inicia sesión si hace falta con npx clasp login.
  5. Ejecuta pnpm dev para desarrollo local con Vite.
  6. Ejecuta pnpm push para compilar y subir a Apps Script.

Scripts

  • pnpm dev: servidor local de Vite.
  • pnpm build: genera dist/ compatible con Apps Script.
  • pnpm push: compila y sube a Apps Script.
  • pnpm deploy: compila, sube y crea un deployment.

Google Sheets como base de datos

Una forma muy común de trabajar con Google Apps Script es usar un spreadsheet como si fuera una base de datos simple.

Modelo propuesto

  • Un spreadsheet representa la base de datos.
  • Cada hoja representa una tabla.
  • La primera fila de cada hoja contiene los nombres de las columnas.
  • Cada fila siguiente representa un registro.
  • Conviene tener una columna id como identificador único.

Ejemplo de hoja users:

idnameemailcreatedAt
usr_001Anaana@email.com2026-05-08T10:00:00.000Z
usr_002Luisluis@email.com2026-05-08T10:30:00.000Z

Operaciones CRUD

La idea es centralizar el acceso a Sheets en funciones de servidor dentro de Apps Script.

Puedes empezar con algo como esto en Code.js o moverlo luego a otro archivo .gs.

constDB_CONFIG={spreadsheetId: 'REEMPLAZA_CON_TU_SPREADSHEET_ID',};functiongetDb(){returnSpreadsheetApp.openById(DB_CONFIG.spreadsheetId);}functiongetTable(tableName){constsheet=getDb().getSheetByName(tableName);if(!sheet){thrownewError(`La hoja "${tableName}" no existe.`);}returnsheet;}functiongetHeaders(sheet){constlastColumn=sheet.getLastColumn();if(lastColumn===0){return[];}returnsheet.getRange(1,1,1,lastColumn).getValues()[0];}functiongetRows(sheet){constlastRow=sheet.getLastRow();constlastColumn=sheet.getLastColumn();if(lastRow<2||lastColumn===0){return[];}returnsheet.getRange(2,1,lastRow-1,lastColumn).getValues();}functionmapRow(headers,row){returnheaders.reduce((record,header,index)=>{record[header]=row[index];returnrecord;},{});}functionmapRows(headers,rows){returnrows.map((row)=>mapRow(headers,row));}

Create

Inserta un nuevo registro al final de la hoja.

functioninsertRecord(tableName,payload){constsheet=getTable(tableName);constheaders=getHeaders(sheet);if(!headers.length){thrownewError(`La hoja "${tableName}" no tiene encabezados.`);}constrecord={id: payload.id||Utilities.getUuid(),createdAt: payload.createdAt||newDate().toISOString(),
...payload,};constrow=headers.map((header)=>{returnheaderinrecord ? record[header] : '';});sheet.appendRow(row);returnrecord;}

Ejemplo:

functioncreateUser(){returninsertRecord('users',{name: 'Ana',email: 'ana@email.com',});}

Read all

Obtiene todos los registros de una hoja.

functiongetAllRecords(tableName){constsheet=getTable(tableName);constheaders=getHeaders(sheet);constrows=getRows(sheet);returnmapRows(headers,rows);}

Ejemplo:

functionlistUsers(){returngetAllRecords('users');}

Read by id

Busca un registro por su id.

functiongetRecordById(tableName,id){constrecords=getAllRecords(tableName);returnrecords.find((record)=>String(record.id)===String(id))||null;}

Ejemplo:

functionfindUser(){returngetRecordById('users','usr_001');}

Update

Actualiza una fila existente buscando por id.

functionupdateRecord(tableName,id,payload){constsheet=getTable(tableName);constheaders=getHeaders(sheet);constrows=getRows(sheet);constrowIndex=rows.findIndex((row)=>String(row[0])===String(id));if(rowIndex===-1){thrownewError(`No se encontró un registro con id "${id}".`);}constcurrentRecord=mapRow(headers,rows[rowIndex]);constnextRecord={
...currentRecord,
...payload,id: currentRecord.id,};constnextRow=headers.map((header)=>{returnheaderinnextRecord ? nextRecord[header] : '';});sheet.getRange(rowIndex+2,1,1,headers.length).setValues([nextRow]);returnnextRecord;}

Ejemplo:

functioneditUser(){returnupdateRecord('users','usr_001',{name: 'Ana Maria',});}

Delete

Elimina una fila por id.

functiondeleteRecord(tableName,id){constsheet=getTable(tableName);constrows=getRows(sheet);constrowIndex=rows.findIndex((row)=>String(row[0])===String(id));if(rowIndex===-1){thrownewError(`No se encontró un registro con id "${id}".`);}sheet.deleteRow(rowIndex+2);return{success: true, id };}

Ejemplo:

functionremoveUser(){returndeleteRecord('users','usr_001');}

Recomendación de estructura de hojas

Para que el CRUD sea fácil de mantener, intenta seguir estas reglas:

  • Usa siempre la fila 1 como encabezado.
  • Deja id en la primera columna.
  • Usa nombres de columnas estables: name, email, status, createdAt, updatedAt.
  • Evita celdas combinadas, colores como fuente de datos o fórmulas mezcladas con registros.

Cómo llamarlo desde el frontend

Cuando la app ya corre dentro de Google Apps Script, puedes usar google.script.run.

Ejemplo desde el cliente:

functionloadUsers(){google.script.run.withSuccessHandler((users)=>{console.log('Usuarios:',users);}).withFailureHandler((error)=>{console.error('Error:',error);}).getAllRecords('users');}

Limitaciones de este enfoque

Usar Google Sheets como base de datos funciona bien para proyectos internos, MVPs y automatizaciones, pero tiene límites:

  • No reemplaza una base de datos relacional real.
  • Las búsquedas grandes pueden ser lentas si la hoja crece mucho.
  • No hay relaciones, índices ni transacciones reales.
  • Hay que cuidar la concurrencia si varios usuarios escriben al mismo tiempo.

Recomendaciones prácticas

  • Agrega una hoja por entidad: users, orders, products.
  • Crea funciones genéricas como las de arriba y luego wrappers por entidad.
  • Si habrá escrituras simultáneas, considera LockService.
  • Si necesitas auditoría, agrega columnas como createdAt, updatedAt, createdBy.

Próximo paso sugerido

Una buena evolución para esta plantilla sería mover el CRUD a un archivo como src/server/sheets.gs o Code.js dividido por responsabilidades, y crear en el frontend una capa cliente que encapsule google.script.run.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages