Intervalos de Tiempo
Un atributo timeInterval es una regla de recurrencia, no una lista de espacios: una fecha de anclaje, rangos de tiempo diarios y banderas de repetición. Resuélvelo en pares concretos [inicio, fin] para la ventana que realmente renderizas con los ayudantes de nivel superior expandAttributeTimeIntervals, expandTimeIntervals y el guardia de tipo isTimeIntervalAttribute.
import { expandAttributeTimeIntervals } from 'oneentry';
const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
// [['2025-04-14T09:00:00.000Z', '2025-04-14T10:00:00.000Z'], …]
Los tres ayudantes son puros: no mutan su entrada y no realizan solicitudes.
Dónde viven los horarios
La API devuelve horarios en dos formas, y ambas son aceptadas por los ayudantes:
| Forma | Dónde encontrarlo | Contiene |
|---|---|---|
Entidad (ITimeIntervalEntitySchedule) | attributeValues[marker].value[].values[] en páginas, productos, bloques y conjuntos de atributos | un rango de fechas con pares de tiempos |
Formulario (ITimeIntervalSchedule) | attributes[].localizeInfos.intervals[] en formularios | un rango con intervalos que llevan un periodo de espacio en minutos |
expandAttributeTimeIntervals(attr, window)
El camino de una sola llamada para atributos de entidad: recorre los grupos y horarios del atributo, expande cada uno de ellos y fusiona los resultados. La fusión es importante: la deduplicación y el orden solo se mantienen dentro de un solo horario, por lo que combinar grupos manualmente puede resultar en espacios duplicados o desordenados.
Cualquier cosa que no sea un atributo timeInterval produce un array vacío, por lo que es seguro llamarlo sin verificar type primero.
import { expandAttributeTimeIntervals } from 'oneentry';
const page = await Pages.getPageByUrl('booking');
const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
expandTimeIntervals(schedule, window)
Resuelve un único horario. Utilízalo cuando ya tengas uno: notablemente en formularios, cuyos horarios ya están tipados en localizeInfos.intervals:
import { expandTimeIntervals } from 'oneentry';
const form = await Forms.getFormByMarker('booking_form');
const field = form.attributes.find((a) => a.marker === 'schedule');
const slots = (field?.localizeInfos.intervals ?? []).flatMap((schedule) =>
expandTimeIntervals(schedule, { from: '2025-05-01', to: '2025-05-31' }),
);
isTimeIntervalAttribute(attr)
IAttributeValue.value está tipado como unknown, porque su forma depende de type. Este guardia de tipo reduce un atributo a ITimeIntervalAttributeValue, que es lo que te permite acceder a los horarios sin un cast:
import { isTimeIntervalAttribute } from 'oneentry';
const attr = page.attributeValues.interval;
if (isTimeIntervalAttribute(attr)) {
attr.value[0].values[0].dates; // fully typed
}
La ventana
const window = { from: '2025-04-01', to: '2025-04-30' };
fromytoaceptan unaDate, una cadena ISO o milisegundos de época.- Ambos límites son inclusivos y se comparan a una granularidad de día UTC: la parte de hora del día de
from/tose ignora. - La ventana es requerida: un horario es una regla de recurrencia abierta, y solo tú sabes hasta dónde debe resolverse.
Semántica de recurrencia
dates[0]/range[0]es tanto la fase de recurrencia como el primer día válido: nada anterior se emite, por amplio que sea la ventana.dates[1]/range[1]termina la validez. Cuando no se extiende más allá del inicio, el horario está anclado a ese único día; con una bandera de recurrencia establecida, la recurrencia es entonces abierta y solo la ventana limita el resultado.inEveryWeekse repite cada 7 días desde el ancla.inEveryMonthse repite en el mismo día del mes, omitiendo meses que son demasiado cortos.- Con ambas banderas establecidas, se aplica la regla semanal, que es lo que siempre ha significado en la práctica.
- Con ninguna bandera, el horario es un rango de fechas simple: cada día de él produce espacios.
- El resultado se deduplica y se ordena por inicio, luego por fin.
- Toda la aritmética es UTC, por lo que el resultado no depende de la zona horaria de la máquina.
Migrando del campo timeIntervals
Las versiones anteriores del SDK inyectaban un array timeIntervals computado en cada valor de atributo timeInterval. Ese campo ya no existe. Materializaba un año completo de espacios independientemente de lo que necesitara el llamador: un solo atributo con espacios horarios se expandía a aproximadamente 2,000 líneas de JSON, y períodos de espacio más finos alcanzaban megabytes, suficiente para superar los límites de caché de datos del marco. Nunca se declaró en ninguna interfaz o esquema, por lo que los consumidores de TypeScript solo podían acceder a él a través de un cast.
// before — read the pre-computed field
const slots = page.attributeValues.interval.value[0].values[0].timeIntervals;
// now — expand the window you actually render
import { expandAttributeTimeIntervals } from 'oneentry';
const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
Los datos fuente que se están expandiendo (dates/range, times/intervals, inEveryWeek, inEveryMonth) no han cambiado y siguen presentes en cada horario: nada se pierde, simplemente se resuelve bajo demanda en lugar de de manera anticipada, y la regla compacta es lo que se almacena en caché.
Los métodos _addTimeIntervalsToSchedules y _addTimeIntervalsToFormSchedules fueron eliminados de cada módulo también (a pesar del prefijo _, eran invocables, por ejemplo, Pages._addTimeIntervalsToSchedules). Usa expandTimeIntervals en su lugar.
Tipos
Todos estos se exportan desde la raíz del paquete y desde oneentry/types (ver Importando Tipos):
| Tipo | Describe |
|---|---|
ITimeIntervalAttributeValue | Un IAttributeValue reducido a type: 'timeInterval', cuyo value es un array de grupos |
ITimeIntervalGroup | Una entrada del value del atributo: horarios que comparten un intervalId |
ITimeIntervalEntitySchedule | Un horario de entidad: dates, times, inEveryWeek, inEveryMonth |
ITimeIntervalSchedule | Un horario de formulario: range, intervals, inEveryWeek, inEveryMonth |
ITimeIntervalRange | Un rango diario con start, end y un periodo de espacio en minutos (null cuando no está segmentado) |
ITimeIntervalPoint | Un punto en un día - { horas, minutos } |
ITimeIntervalWindow | La ventana de expansión - { from, to } |
TimeIntervalPair | Un espacio resuelto - [start, end], ambas cadenas ISO 8601 UTC |
Ejemplo: renderizando un mes de espacios
import { expandAttributeTimeIntervals } from 'oneentry';
const page = await Pages.getPageByUrl('booking');
if ('statusCode' in page) {
throw new Error(page.message);
}
const slots = expandAttributeTimeIntervals(page.attributeValues.interval, {
from: '2025-04-01',
to: '2025-04-30',
});
// Group the slots by day for a calendar view
const byDay = slots.reduce((acc, [start, end]) => {
const day = start.slice(0, 10);
(acc[day] ??= []).push([start, end]);
return acc;
}, {});
🔗 Documentación Relacionada
- Valores de Atributo - la forma normalizada de cada valor de atributo
- Importando Tipos - importando
ITimeIntervalWindowy amigos - Módulo de Formularios - atributos de formulario que llevan
localizeInfos.intervals