soff-cron 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +300 -0
  3. package/dist/core/formatter.cjs +2 -0
  4. package/dist/core/formatter.cjs.map +1 -0
  5. package/dist/core/formatter.d.cts +19 -0
  6. package/dist/core/formatter.d.ts +19 -0
  7. package/dist/core/formatter.js +2 -0
  8. package/dist/core/formatter.js.map +1 -0
  9. package/dist/core/parser.cjs +2 -0
  10. package/dist/core/parser.cjs.map +1 -0
  11. package/dist/core/parser.d.cts +20 -0
  12. package/dist/core/parser.d.ts +20 -0
  13. package/dist/core/parser.js +2 -0
  14. package/dist/core/parser.js.map +1 -0
  15. package/dist/core/types.cjs +2 -0
  16. package/dist/core/types.cjs.map +1 -0
  17. package/dist/core/types.d.cts +142 -0
  18. package/dist/core/types.d.ts +142 -0
  19. package/dist/core/types.js +2 -0
  20. package/dist/core/types.js.map +1 -0
  21. package/dist/core/validator.cjs +2 -0
  22. package/dist/core/validator.cjs.map +1 -0
  23. package/dist/core/validator.d.cts +19 -0
  24. package/dist/core/validator.d.ts +19 -0
  25. package/dist/core/validator.js +2 -0
  26. package/dist/core/validator.js.map +1 -0
  27. package/dist/i18n/en.cjs +2 -0
  28. package/dist/i18n/en.cjs.map +1 -0
  29. package/dist/i18n/en.d.cts +5 -0
  30. package/dist/i18n/en.d.ts +5 -0
  31. package/dist/i18n/en.js +2 -0
  32. package/dist/i18n/en.js.map +1 -0
  33. package/dist/i18n/es.cjs +2 -0
  34. package/dist/i18n/es.cjs.map +1 -0
  35. package/dist/i18n/es.d.cts +61 -0
  36. package/dist/i18n/es.d.ts +61 -0
  37. package/dist/i18n/es.js +2 -0
  38. package/dist/i18n/es.js.map +1 -0
  39. package/dist/index.cjs +2 -0
  40. package/dist/index.cjs.map +1 -0
  41. package/dist/index.d.cts +4 -0
  42. package/dist/index.d.ts +4 -0
  43. package/dist/index.js +2 -0
  44. package/dist/index.js.map +1 -0
  45. package/package.json +124 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Luis C. Rojas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,300 @@
1
+ <div align="center">
2
+ <img src="https://raw.githubusercontent.com/bledxs/soff-monorepo/master/assets/logo.png" alt="Soff Logo" width="100" height="100">
3
+ <h1>Soff Cron</h1>
4
+ <p>Lightweight, tree-shakeable cron expression parser and human-readable formatter.</p>
5
+ </div>
6
+
7
+ <div align="center">
8
+
9
+ [![npm](https://img.shields.io/npm/v/soff-cron)](https://www.npmjs.com/package/soff-cron)
10
+ [![License](https://img.shields.io/github/license/bledxs/soff-monorepo)](LICENSE)
11
+ [![Build Status](https://github.com/bledxs/soff-monorepo/actions/workflows/ci.yml/badge.svg)](https://github.com/bledxs/soff-monorepo/actions)
12
+ [![codecov](https://codecov.io/gh/bledxs/soff-monorepo/branch/master/graph/badge.svg)](https://codecov.io/gh/bledxs/soff-monorepo)
13
+ [![minzipped size](https://img.shields.io/bundlephobia/minzip/soff-cron)](https://bundlephobia.com/package/soff-cron)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ **Zero dependencies** · **TypeScript** · **~2KB minzipped** · **i18n ready**
20
+
21
+ ## Table of Contents
22
+
23
+ - [🤔 Why?](#-why)
24
+ - [📦 Install](#-install)
25
+ - [🚀 Quick Start](#-quick-start)
26
+ - [🌍 i18n Support](#-i18n-support)
27
+ - [API Reference](#api-reference)
28
+ - [`formatCron(expression, options?)`](#formatcronexpression-options)
29
+ - [`parseCron(expression, allowSeconds?)`](#parsecronexpression-allowseconds)
30
+ - [`validateCron(expression, allowSeconds?)`](#validatecronexpression-allowseconds)
31
+ - [Supported Cron Syntax](#supported-cron-syntax)
32
+ - [Examples](#examples)
33
+ - [Types](#types)
34
+ - [Contributing](#contributing)
35
+ - [License](#license)
36
+
37
+ ## 🤔 Why?
38
+
39
+ Cron expressions like `*/15 9-17 * * 1-5` are powerful but hard to read. This library:
40
+
41
+ - ✅ **Converts cron to human text**: "Every 15 minutes, between 9:00 AM and 5:00 PM, Monday through Friday"
42
+ - ✅ **Validates cron syntax**: Catch errors before execution
43
+ - ✅ **Parses to structured data**: Extract minute/hour/day patterns
44
+ - ✅ **Zero dependencies**: No bloat, pure TypeScript
45
+ - ✅ **i18n ready**: Built-in Spanish and English support
46
+ - ✅ **Tree-shakeable**: Only import what you need
47
+
48
+ **Perfect for:** Dashboards, task schedulers, configuration UIs, logs, and documentation.
49
+
50
+ ## 📦 Install
51
+
52
+ ```bash
53
+ # npm
54
+ npm install soff-cron
55
+
56
+ # pnpm
57
+ pnpm add soff-cron
58
+
59
+ # yarn
60
+ yarn add soff-cron
61
+
62
+ # bun
63
+ bun add soff-cron
64
+ ```
65
+
66
+ ## 🚀 Quick Start
67
+
68
+ ```typescript
69
+ import { formatCron, validateCron, parseCron } from 'soff-cron';
70
+
71
+ // 📝 Format cron expressions to human-readable text
72
+ formatCron('0 2 * * *', { locale: 'en' });
73
+ // → "At 02:00, every day"
74
+
75
+ formatCron('*/15 9-17 * * 1-5', { locale: 'es' });
76
+ // → "Cada 15 minutos, entre las 09:00 y 17:00, día de semanas"
77
+
78
+ formatCron('@daily', { locale: 'en' });
79
+ // → "every day"
80
+
81
+ // ✅ Validate cron expressions
82
+ validateCron('0 2 * * *');
83
+ // → { isValid: true }
84
+
85
+ validateCron('60 * * * *');
86
+ // → { isValid: false, error: 'Value 60 is out of range...', field: 'minute' }
87
+
88
+ // 🔍 Parse cron expressions into structured data
89
+ parseCron('*/15 9-17 * * 1-5');
90
+ // → {
91
+ // minute: { raw: '*/15', values: [0, 15, 30, 45], isStep: true, ... },
92
+ // hour: { raw: '9-17', values: [9, 10, 11, ..., 17], isRange: true, ... },
93
+ // dayOfWeek: { raw: '1-5', values: [1, 2, 3, 4, 5], isRange: true, ... },
94
+ // ...
95
+ // }
96
+ ```
97
+
98
+ ## 🌍 i18n Support
99
+
100
+ Built-in support for **Spanish** and **English**:
101
+
102
+ ```typescript
103
+ import { formatCron } from 'soff-cron';
104
+
105
+ // English (default)
106
+ formatCron('0 9 * * 1-5', { locale: 'en' });
107
+ // → "At 09:00, Monday through Friday"
108
+
109
+ // Spanish
110
+ formatCron('0 9 * * 1-5', { locale: 'es' });
111
+ // → "A las 09:00, de lunes a viernes"
112
+
113
+ // 12-hour format
114
+ formatCron('0 14 * * *', { locale: 'en', use24HourFormat: false });
115
+ // → "At 2:00 PM, every day"
116
+ ```
117
+
118
+ Want to add more languages? Check out [`src/i18n/`](src/i18n/) for examples!
119
+
120
+ ## API Reference
121
+
122
+ ### `formatCron(expression, options?)`
123
+
124
+ Converts a cron expression to human-readable text.
125
+
126
+ **Parameters:**
127
+
128
+ - `expression` (string): The cron expression (5 or 6 fields)
129
+ - `options` (object, optional):
130
+ - `locale` ('en' | 'es'): Output language (default: `'en'`)
131
+ - `use24HourFormat` (boolean): Use 24-hour time format (default: `true`)
132
+ - `includeSeconds` (boolean): Support 6-field cron with seconds (default: `false`)
133
+ - `verbose` (boolean): Use more detailed descriptions (default: `false`)
134
+
135
+ **Returns:** `string` - Human-readable description
136
+
137
+ **Example:**
138
+
139
+ ```typescript
140
+ formatCron('0 */2 * * *', { locale: 'en' });
141
+ // → "At minute 0, every 2 hours"
142
+
143
+ formatCron('0 0 1 * *', { locale: 'es' });
144
+ // → "A las 00:00, el día 1"
145
+ ```
146
+
147
+ ---
148
+
149
+ ### `parseCron(expression, allowSeconds?)`
150
+
151
+ Parses a cron expression into structured data.
152
+
153
+ **Parameters:**
154
+
155
+ - `expression` (string): The cron expression
156
+ - `allowSeconds` (boolean, optional): Allow 6-field expressions (default: `false`)
157
+
158
+ **Returns:** `ParsedCron` - Structured cron data
159
+
160
+ **Throws:** `Error` if expression is invalid
161
+
162
+ **Example:**
163
+
164
+ ```typescript
165
+ const parsed = parseCron('*/5 * * * *');
166
+
167
+ console.log(parsed.minute.values);
168
+ // → [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55]
169
+
170
+ console.log(parsed.minute.isStep);
171
+ // → true
172
+ ```
173
+
174
+ ---
175
+
176
+ ### `validateCron(expression, allowSeconds?)`
177
+
178
+ Validates a cron expression syntax.
179
+
180
+ **Parameters:**
181
+
182
+ - `expression` (string): The cron expression
183
+ - `allowSeconds` (boolean, optional): Allow 6-field expressions (default: `false`)
184
+
185
+ **Returns:** `ValidationResult`
186
+
187
+ ```typescript
188
+ {
189
+ isValid: boolean;
190
+ error?: string;
191
+ field?: 'minute' | 'hour' | 'dayOfMonth' | 'month' | 'dayOfWeek' | 'second';
192
+ }
193
+ ```
194
+
195
+ **Example:**
196
+
197
+ ```typescript
198
+ validateCron('0 0 * * *');
199
+ // → { isValid: true }
200
+
201
+ validateCron('0 25 * * *');
202
+ // → { isValid: false, error: 'Value 25 is out of range for hour (0-23)', field: 'hour' }
203
+ ```
204
+
205
+ ## Supported Cron Syntax
206
+
207
+ | Syntax | Example | Description |
208
+ | ------- | ------------- | ----------------------------------------------------- |
209
+ | `*` | `* * * * *` | Wildcard (all values) |
210
+ | `-` | `9-17` | Range (9 through 17) |
211
+ | `,` | `1,3,5` | List (1, 3, and 5) |
212
+ | `/` | `*/15` | Step (every 15) |
213
+ | `?` | `? * * * *` | Question mark (day fields only) |
214
+ | Names | `JAN`, `MON` | Month/day names (JAN-DEC, SUN-SAT) |
215
+ | Special | `@daily` | `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly` |
216
+ | 6-field | `0 0 2 * * *` | Includes seconds (requires `allowSeconds: true`) |
217
+
218
+ ## Examples
219
+
220
+ ```typescript
221
+ // Every day at 2 AM
222
+ formatCron('0 2 * * *', { locale: 'en' });
223
+ // → "At 02:00, every day"
224
+
225
+ // Every 15 minutes during work hours on weekdays
226
+ formatCron('*/15 9-17 * * 1-5', { locale: 'es' });
227
+ // → "Cada 15 minutos, entre las 09:00 y 17:00, día de semanas"
228
+
229
+ // Every Monday at 9 AM
230
+ formatCron('0 9 * * MON', { locale: 'en' });
231
+ // → "At 09:00, on Monday"
232
+
233
+ // First day of every month at midnight
234
+ formatCron('0 0 1 * *', { locale: 'en' });
235
+ // → "At 00:00, on day 1"
236
+
237
+ // Special keywords
238
+ formatCron('@hourly', { locale: 'es' });
239
+ // → "cada hora"
240
+
241
+ // 6-field with seconds
242
+ formatCron('30 0 2 * * *', { locale: 'en', includeSeconds: true });
243
+ // → "At 02:00, every day"
244
+ ```
245
+
246
+ ## Types
247
+
248
+ ```typescript
249
+ export interface ParsedCron {
250
+ expression: string;
251
+ minute: CronField;
252
+ hour: CronField;
253
+ dayOfMonth: CronField;
254
+ month: CronField;
255
+ dayOfWeek: CronField;
256
+ second?: CronField;
257
+ isSpecial: boolean;
258
+ specialKeyword?: string;
259
+ }
260
+
261
+ export interface CronField {
262
+ raw: string;
263
+ values: number[];
264
+ isWildcard: boolean;
265
+ isRange: boolean;
266
+ isStep: boolean;
267
+ isList: boolean;
268
+ }
269
+
270
+ export interface FormatterOptions {
271
+ locale?: 'es' | 'en';
272
+ use24HourFormat?: boolean;
273
+ includeSeconds?: boolean;
274
+ verbose?: boolean;
275
+ }
276
+
277
+ export interface ValidationResult {
278
+ isValid: boolean;
279
+ error?: string;
280
+ field?: 'minute' | 'hour' | 'dayOfMonth' | 'month' | 'dayOfWeek' | 'second';
281
+ }
282
+ ```
283
+
284
+ ## Contributing
285
+
286
+ Contributions are welcome! Please read the [contributing guidelines](../../CONTRIBUTING.md) before submitting PRs.
287
+
288
+ **Want to add a new locale?** Check out [`src/i18n/`](src/i18n/) and submit a PR!
289
+
290
+ ## License
291
+
292
+ MIT © [Luis C. Rojas](https://github.com/bledxs)
293
+
294
+ See [LICENSE](LICENSE) for details.
295
+
296
+ ---
297
+
298
+ <div align="center">
299
+ <sub>Part of the <a href="https://github.com/bledxs/soff-monorepo">Soff Monorepo</a></sub>
300
+ </div>
@@ -0,0 +1,2 @@
1
+ 'use strict';var h={"@yearly":"0 0 1 1 *","@annually":"0 0 1 1 *","@monthly":"0 0 1 * *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@midnight":"0 0 * * *","@hourly":"0 * * * *"},l={minute:{min:0,max:59,name:"minute"},hour:{min:0,max:23,name:"hour"},dayOfMonth:{min:1,max:31,name:"day of month"},month:{min:1,max:12,name:"month"},dayOfWeek:{min:0,max:7,name:"day of week"},second:{min:0,max:59,name:"second"}},p={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12},$={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6};function V(r,e=false){if(!r||typeof r!="string")return {isValid:false,error:"Cron expression must be a non-empty string"};let t=r.trim();if(t.startsWith("@"))return h[t]?{isValid:true}:{isValid:false,error:`Unknown special keyword: ${t}`};let n=t.split(/\s+/),s=e?6:5;if(n.length!==s)return {isValid:false,error:`Expected ${s} fields, got ${n.length}`};let a=e?["second","minute","hour","dayOfMonth","month","dayOfWeek"]:["minute","hour","dayOfMonth","month","dayOfWeek"];for(let i=0;i<n.length;i++){let o=a[i],u=n[i],d=l[o],f=A(u,d,o);if(!f.isValid)return {isValid:false,error:f.error,field:o}}return {isValid:true}}function A(r,e,t){return r?r==="*"?{isValid:true}:r==="?"?t==="dayOfMonth"||t==="dayOfWeek"?{isValid:true}:{isValid:false,error:`Question mark (?) is only valid for day fields, not ${e.name}`}:r.includes("/")?E(r,e,t):r.includes(",")?D(r,e,t):r.includes("-")?S(r,e,t):C(r,e,t):{isValid:false,error:`${e.name} field cannot be empty`}}function E(r,e,t){let n=r.split("/");if(n.length!==2)return {isValid:false,error:`Invalid step syntax in ${e.name}: ${r}`};let[s,a]=n,i=parseInt(a,10);return isNaN(i)||i<=0?{isValid:false,error:`Invalid step value in ${e.name}: ${a}`}:s==="*"?{isValid:true}:s.includes("-")?S(s,e,t):C(s,e,t)}function S(r,e,t){let n=r.split("-");if(n.length!==2)return {isValid:false,error:`Invalid range syntax in ${e.name}: ${r}`};let[s,a]=n,i=b(s,t),o=b(a,t);return i===null?{isValid:false,error:`Invalid start value in ${e.name} range: ${s}`}:o===null?{isValid:false,error:`Invalid end value in ${e.name} range: ${a}`}:i<e.min||i>e.max?{isValid:false,error:`Start value ${i} is out of range for ${e.name} (${e.min}-${e.max})`}:o<e.min||o>e.max?{isValid:false,error:`End value ${o} is out of range for ${e.name} (${e.min}-${e.max})`}:i>o?{isValid:false,error:`Start value ${i} cannot be greater than end value ${o} in ${e.name}`}:{isValid:true}}function D(r,e,t){let n=r.split(",");for(let s of n){let a=s.trim();if(!a)return {isValid:false,error:`Empty value in ${e.name} list`};if(a.includes("-")){let i=S(a,e,t);if(!i.isValid)return i}else {let i=C(a,e,t);if(!i.isValid)return i}}return {isValid:true}}function C(r,e,t){let n=b(r,t);return n===null?{isValid:false,error:`Invalid value in ${e.name}: ${r}`}:n<e.min||n>e.max?{isValid:false,error:`Value ${n} is out of range for ${e.name} (${e.min}-${e.max})`}:{isValid:true}}function b(r,e){let t=parseInt(r,10);if(!isNaN(t))return t;if(e==="month"){let n=p[r.toUpperCase()];if(n!==void 0)return n}if(e==="dayOfWeek"){let n=$[r.toUpperCase()];if(n!==void 0)return n}return null}function M(r,e=false){let t=V(r,e);if(!t.isValid)throw new Error(t.error||"Invalid cron expression");let n=r.trim();if(n.startsWith("@")){let s=h[n];return {expression:n,...W(s,false),isSpecial:true,specialKeyword:n}}return {expression:n,...W(n,e),isSpecial:false}}function W(r,e){let t=r.split(/\s+/);if(e&&t.length===6){let[u,d,f,I,R,j]=t;return {second:m(u,l.second,"second"),minute:m(d,l.minute,"minute"),hour:m(f,l.hour,"hour"),dayOfMonth:m(I,l.dayOfMonth,"dayOfMonth"),month:m(R,l.month,"month"),dayOfWeek:m(j,l.dayOfWeek,"dayOfWeek")}}let[n,s,a,i,o]=t;return {minute:m(n,l.minute,"minute"),hour:m(s,l.hour,"hour"),dayOfMonth:m(a,l.dayOfMonth,"dayOfMonth"),month:m(i,l.month,"month"),dayOfWeek:m(o,l.dayOfWeek,"dayOfWeek")}}function m(r,e,t){let n=r,s=r==="*"||r==="?",a=r.includes("/"),i=r.includes("-")&&!a,o=r.includes(","),u;if(s)u=k(e.min,e.max);else if(a)u=P(r,e,t);else if(o)u=T(r,e,t);else if(i)u=O(r,e,t);else {let d=g(r,t);u=d!==null?[d]:[];}return t==="dayOfWeek"&&(u=u.map(d=>d===7?0:d),u=[...new Set(u)]),u.sort((d,f)=>d-f),{raw:n,values:u,isWildcard:s,isRange:i,isStep:a,isList:o}}function P(r,e,t){let[n,s]=r.split("/"),a=parseInt(s,10),i;if(n==="*")i=k(e.min,e.max);else if(n.includes("-"))i=O(n,e,t);else {let u=g(n,t);i=u!==null?[u]:[];}let o=[];for(let u=0;u<i.length;u+=a)o.push(i[u]);return o}function O(r,e,t){let[n,s]=r.split("-"),a=g(n,t),i=g(s,t);return a===null||i===null?[]:k(a,i)}function T(r,e,t){let n=r.split(","),s=[];for(let a of n){let i=a.trim();if(i.includes("-")){let o=O(i,e,t);s.push(...o);}else {let o=g(i,t);o!==null&&s.push(o);}}return s}function g(r,e){let t=parseInt(r,10);if(!isNaN(t))return t;if(e==="month"){let n=p[r.toUpperCase()];if(n!==void 0)return n}if(e==="dayOfWeek"){let n=$[r.toUpperCase()];if(n!==void 0)return n}return null}function k(r,e){let t=[];for(let n=r;n<=e;n++)t.push(n);return t}var w={at:"a las",every:"cada",everyMinute:"cada minuto",everyHour:"cada hora",everyDay:"todos los d\xEDas",everyWeek:"cada semana",everyMonth:"cada mes",everyYear:"cada a\xF1o",minute:"minuto",minutes:"minutos",day:"d\xEDa",days:"d\xEDas",on:"el",in:"en",and:"y",between:"entre",through:"hasta",second:"segundo",sunday:"domingo",monday:"lunes",tuesday:"martes",wednesday:"mi\xE9rcoles",thursday:"jueves",friday:"viernes",saturday:"s\xE1bado",january:"enero",february:"febrero",march:"marzo",april:"abril",may:"mayo",june:"junio",july:"julio",august:"agosto",september:"septiembre",october:"octubre",november:"noviembre",december:"diciembre",am:"AM",pm:"PM",midnight:"medianoche",weekday:"d\xEDa de semana",weekend:"fin de semana"};var x={at:"at",every:"every",everyMinute:"every minute",everyHour:"every hour",everyDay:"every day",everyWeek:"every week",everyMonth:"every month",everyYear:"every year",minute:"minute",minutes:"minutes",day:"day",days:"days",on:"on",in:"in",and:"and",between:"between",through:"through",second:"second",sunday:"Sunday",monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",january:"January",february:"February",march:"March",april:"April",may:"May",june:"June",july:"July",august:"August",september:"September",october:"October",november:"November",december:"December",am:"AM",pm:"PM",midnight:"midnight",weekday:"weekday",weekend:"weekend"};function N(r){if(r.length<2)return false;for(let e=1;e<r.length;e++)if(r[e]!==r[e-1]+1)return false;return true}function ie(r,e={}){let{locale:t="en",use24HourFormat:n=true,includeSeconds:s=false,verbose:a=false}=e,i=t==="es"?w:x,o=M(r,s);return o.isSpecial&&o.specialKeyword?L(o.specialKeyword,i):_(o,i,n,a)}function L(r,e){return {"@yearly":e.everyYear,"@annually":e.everyYear,"@monthly":e.everyMonth,"@weekly":e.everyWeek,"@daily":e.everyDay,"@midnight":`${e.at} ${e.midnight}`,"@hourly":e.everyHour}[r]||r}function _(r,e,t,n){let s=[],a=Y(r,e,t);a&&s.push(a);let i=U(r,e,n);return i&&s.push(i),s.join(", ")}function Y(r,e,t){let{minute:n,hour:s,second:a}=r;if(n.isWildcard&&s.isWildcard)return a&&!a.isWildcard?`${e.at} ${e.second} ${a.values.join(", ")}`:e.everyMinute;if(n.isWildcard){if(s.values.length===1){let i=c(s.values[0],t,e);return `${e.everyMinute} ${e.at} ${i}`}if(s.values.length>1&&s.isRange){let i=c(s.values[0],t,e),o=c(s.values[s.values.length-1],t,e);return `${e.everyMinute}, ${e.between} ${i} ${e.and} ${o}`}}if(s.isWildcard&&!n.isWildcard){if(n.values.length===1)return `${e.at} ${e.minute} ${n.values[0]}`;if(n.isStep){let i=n.values[1]-n.values[0];return `${e.every} ${i} ${e.minutes}`}}if(!n.isWildcard&&!s.isWildcard){if(n.values.length===1&&s.values.length===1){let i=v(s.values[0],n.values[0]),o=t?i:y(s.values[0],n.values[0],e);return `${e.at} ${o}`}if(n.values.length>1||s.values.length>1){if(n.values.length===1&&s.isRange&&s.values.length>1&&N(s.values)){let i=t?v(s.values[0],n.values[0]):y(s.values[0],n.values[0],e),o=t?v(s.values[s.values.length-1],n.values[0]):y(s.values[s.values.length-1],n.values[0],e);return `${e.between} ${i} ${e.and} ${o}`}if(n.isStep){let i=n.values[1]-n.values[0];if(s.isRange){let o=c(s.values[0],t,e),u=c(s.values[s.values.length-1],t,e);return `${e.every} ${i} ${e.minutes}, ${e.between} ${o} ${e.and} ${u}`}return `${e.every} ${i} ${e.minutes}`}}}return K(r,e,t)}function U(r,e,t){let{dayOfMonth:n,month:s,dayOfWeek:a}=r;if(n.isWildcard&&a.isWildcard&&s.isWildcard)return e.everyDay;let i=[];if(!a.isWildcard){let o=H(a.values,e,t);o&&i.push(o);}if(!n.isWildcard&&a.isWildcard){let o=J(n.values,e,t);o&&i.push(o);}if(!s.isWildcard){let o=z(s.values,e,t);o&&i.push(o);}return i.join(", ")}function v(r,e){return `${r.toString().padStart(2,"0")}:${e.toString().padStart(2,"0")}`}function y(r,e,t){let n=r<12?t.am:t.pm;return `${r===0?12:r>12?r-12:r}:${e.toString().padStart(2,"0")} ${n}`}function c(r,e,t){return e?`${r.toString().padStart(2,"0")}:00`:y(r,0,t)}function K(r,e,t){let n=[];for(let s of r.hour.values)for(let a of r.minute.values){let i=t?v(s,a):y(s,a,e);n.push(i);}return n.length<=3?`${e.at} ${n.join(", ")}`:`${e.at} ${n.slice(0,2).join(", ")}... (${n.length} times)`}function H(r,e,t){let n=[e.sunday,e.monday,e.tuesday,e.wednesday,e.thursday,e.friday,e.saturday];if(r.length===5&&r.includes(1)&&r.includes(2)&&r.includes(3)&&r.includes(4)&&r.includes(5))return e.weekday+"s";if(r.length===2&&r.includes(0)&&r.includes(6))return e.weekend+"s";if(r.length===1)return e.on+" "+n[r[0]];if(r.length===7)return e.everyDay;let s=r.map(a=>n[a]);return t||r.length<=3?F(s,e):`${s[0]} ${e.through} ${s[s.length-1]}`}function J(r,e,t){return r.length===1?`${e.on} ${e.day} ${r[0]}`:r.length===31?e.everyDay:t||r.length<=3?`${e.on} ${e.days} ${r.join(", ")}`:`${e.on} ${e.days} ${r[0]} ${e.through} ${r[r.length-1]}`}function z(r,e,t){let n=[e.january,e.february,e.march,e.april,e.may,e.june,e.july,e.august,e.september,e.october,e.november,e.december];if(r.length===1)return `${e.in} ${n[r[0]-1]}`;if(r.length===12)return "";let s=r.map(a=>n[a-1]);return t||r.length<=3?`${e.in} ${F(s,e)}`:`${e.in} ${s[0]} ${e.through} ${s[s.length-1]}`}function F(r,e){if(r.length===0)return "";if(r.length===1)return r[0];if(r.length===2)return `${r[0]} ${e.and} ${r[1]}`;let t=r[r.length-1];return `${r.slice(0,-1).join(", ")}, ${e.and} ${t}`}exports.formatCron=ie;//# sourceMappingURL=formatter.cjs.map
2
+ //# sourceMappingURL=formatter.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/types.ts","../../src/core/validator.ts","../../src/core/parser.ts","../../src/i18n/es.ts","../../src/i18n/en.ts","../../src/core/formatter.ts"],"names":["SPECIAL_KEYWORDS","FIELD_CONSTRAINTS","MONTH_NAMES","DAY_NAMES","validateCron","expression","allowSeconds","trimmed","fields","expectedFields","fieldNames","fieldName","fieldValue","constraints","result","validateField","value","validateStepField","validateListField","validateRangeField","validateSingleValue","parts","range","step","stepNum","startStr","endStr","start","parseFieldValue","end","values","val","num","monthNum","dayNum","parseCron","validation","actualExpression","parseStandardCron","second","minute","hour","dayOfMonth","month","dayOfWeek","parseField","raw","isWildcard","isStep","isRange","isList","generateRange","parseStepField","parseListField","parseRangeField","v","a","b","stepStr","baseValues","i","_constraints","part","rangeValues","es","en","isConsecutiveRange","formatCron","options","locale","use24HourFormat","includeSeconds","verbose","i18n","parsed","formatSpecialKeyword","formatStandardCron","keyword","timePart","formatTime","datePart","formatDate","formattedHour","formatHour","time","formatTime24Hour","formatted","formatTime12Hour","startTime","endTime","formatTimeList","dayPart","formatDaysOfWeek","formatDaysOfMonth","monthPart","formatMonths","period","times","days","dayNames","names","d","formatList","months","monthNames","m","items","last"],"mappings":"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","file":"formatter.cjs","sourcesContent":["/**\n * Represents a parsed cron expression field with its values\n */\nexport interface CronField {\n /**\n * Raw value from the cron expression (e.g., \"*\", \"0-5\", step values)\n */\n raw: string;\n\n /**\n * Parsed values as an array of numbers\n * For \"*\", this will be all valid values for the field\n * For ranges like \"0-5\", this will be [0, 1, 2, 3, 4, 5]\n * For steps, this will be [0, 15, 30, 45] (example)\n */\n values: number[];\n\n /**\n * Whether this field uses the wildcard \"*\"\n */\n isWildcard: boolean;\n\n /**\n * Whether this field uses a range (e.g., \"0-5\")\n */\n isRange: boolean;\n\n /**\n * Whether this field uses a step value\n */\n isStep: boolean;\n\n /**\n * Whether this field is a list of values (e.g., \"1,3,5\")\n */\n isList: boolean;\n}\n\n/**\n * Represents a fully parsed cron expression\n */\nexport interface ParsedCron {\n /**\n * The original cron expression string\n */\n expression: string;\n\n /**\n * Minute field (0-59)\n */\n minute: CronField;\n\n /**\n * Hour field (0-23)\n */\n hour: CronField;\n\n /**\n * Day of month field (1-31)\n */\n dayOfMonth: CronField;\n\n /**\n * Month field (1-12)\n */\n month: CronField;\n\n /**\n * Day of week field (0-7, where 0 and 7 are Sunday)\n */\n dayOfWeek: CronField;\n\n /**\n * Optional second field (0-59) for 6-field cron expressions\n */\n second?: CronField;\n\n /**\n * Whether this is a special expression like @daily, @hourly, etc.\n */\n isSpecial: boolean;\n\n /**\n * The special keyword if applicable\n */\n specialKeyword?: string;\n}\n\n/**\n * Locale options for formatting\n */\nexport type Locale = 'es' | 'en';\n\n/**\n * Options for formatting cron expressions\n */\nexport interface FormatterOptions {\n /**\n * Locale for the output text\n * @default 'en'\n */\n locale?: Locale;\n\n /**\n * Whether to use 24-hour format for times\n * @default true\n */\n use24HourFormat?: boolean;\n\n /**\n * Whether to include seconds in the output (for 6-field cron)\n * @default false\n */\n includeSeconds?: boolean;\n\n /**\n * Whether to use verbose descriptions\n * @default false\n */\n verbose?: boolean;\n}\n\n/**\n * Validation result for cron expressions\n */\nexport interface ValidationResult {\n /**\n * Whether the cron expression is valid\n */\n isValid: boolean;\n\n /**\n * Error message if validation failed\n */\n error?: string;\n\n /**\n * The field that caused the error (if applicable)\n */\n field?: 'minute' | 'hour' | 'dayOfMonth' | 'month' | 'dayOfWeek' | 'second';\n}\n\n/**\n * Special cron keywords and their equivalents\n */\nexport const SPECIAL_KEYWORDS: Record<string, string> = {\n '@yearly': '0 0 1 1 *',\n '@annually': '0 0 1 1 *',\n '@monthly': '0 0 1 * *',\n '@weekly': '0 0 * * 0',\n '@daily': '0 0 * * *',\n '@midnight': '0 0 * * *',\n '@hourly': '0 * * * *',\n};\n\n/**\n * Field constraints for validation\n */\nexport interface FieldConstraints {\n min: number;\n max: number;\n name: string;\n}\n\nexport const FIELD_CONSTRAINTS: Record<string, FieldConstraints> = {\n minute: { min: 0, max: 59, name: 'minute' },\n hour: { min: 0, max: 23, name: 'hour' },\n dayOfMonth: { min: 1, max: 31, name: 'day of month' },\n month: { min: 1, max: 12, name: 'month' },\n dayOfWeek: { min: 0, max: 7, name: 'day of week' },\n second: { min: 0, max: 59, name: 'second' },\n};\n\n/**\n * Month names mapping (1-12)\n */\nexport const MONTH_NAMES: Record<string, number> = {\n JAN: 1,\n FEB: 2,\n MAR: 3,\n APR: 4,\n MAY: 5,\n JUN: 6,\n JUL: 7,\n AUG: 8,\n SEP: 9,\n OCT: 10,\n NOV: 11,\n DEC: 12,\n};\n\n/**\n * Day of week names mapping (0-7)\n */\nexport const DAY_NAMES: Record<string, number> = {\n SUN: 0,\n MON: 1,\n TUE: 2,\n WED: 3,\n THU: 4,\n FRI: 5,\n SAT: 6,\n};\n","import type { ValidationResult, FieldConstraints } from './types.js';\nimport { FIELD_CONSTRAINTS, SPECIAL_KEYWORDS, MONTH_NAMES, DAY_NAMES } from './types.js';\n\n/**\n * Validates a cron expression\n * Supports both 5-field and 6-field (with seconds) cron expressions\n * Also supports special keywords like @daily, @hourly, etc.\n *\n * @param expression - The cron expression to validate\n * @param allowSeconds - Whether to allow 6-field cron expressions with seconds\n * @returns ValidationResult object with isValid flag and optional error message\n *\n * @example\n * validateCron('0 2 * * *') // { isValid: true }\n * validateCron('invalid') // { isValid: false, error: '...' }\n * validateCron('0 0 2 * * *', true) // { isValid: true } (with seconds)\n */\nexport function validateCron(expression: string, allowSeconds = false): ValidationResult {\n if (!expression || typeof expression !== 'string') {\n return {\n isValid: false,\n error: 'Cron expression must be a non-empty string',\n };\n }\n\n const trimmed = expression.trim();\n\n // Check for special keywords\n if (trimmed.startsWith('@')) {\n if (SPECIAL_KEYWORDS[trimmed]) {\n return { isValid: true };\n }\n return {\n isValid: false,\n error: `Unknown special keyword: ${trimmed}`,\n };\n }\n\n // Split into fields\n const fields = trimmed.split(/\\s+/);\n const expectedFields = allowSeconds ? 6 : 5;\n\n if (fields.length !== expectedFields) {\n return {\n isValid: false,\n error: `Expected ${expectedFields} fields, got ${fields.length}`,\n };\n }\n\n // Field order: [second] minute hour dayOfMonth month dayOfWeek\n const fieldNames = allowSeconds\n ? ['second', 'minute', 'hour', 'dayOfMonth', 'month', 'dayOfWeek']\n : ['minute', 'hour', 'dayOfMonth', 'month', 'dayOfWeek'];\n\n // Validate each field\n for (let i = 0; i < fields.length; i++) {\n const fieldName = fieldNames[i];\n const fieldValue = fields[i];\n const constraints = FIELD_CONSTRAINTS[fieldName];\n\n const result = validateField(fieldValue, constraints, fieldName);\n if (!result.isValid) {\n return {\n isValid: false,\n error: result.error,\n field: fieldName as ValidationResult['field'],\n };\n }\n }\n\n return { isValid: true };\n}\n\n/**\n * Validates a single cron field\n */\nfunction validateField(\n value: string,\n constraints: FieldConstraints,\n fieldName: string\n): ValidationResult {\n if (!value) {\n return {\n isValid: false,\n error: `${constraints.name} field cannot be empty`,\n };\n }\n\n // Wildcard is always valid\n if (value === '*') {\n return { isValid: true };\n }\n\n // Question mark (for day fields only)\n if (value === '?') {\n if (fieldName === 'dayOfMonth' || fieldName === 'dayOfWeek') {\n return { isValid: true };\n }\n return {\n isValid: false,\n error: `Question mark (?) is only valid for day fields, not ${constraints.name}`,\n };\n }\n\n // Handle step values (e.g., */15, 0-10/2)\n if (value.includes('/')) {\n return validateStepField(value, constraints, fieldName);\n }\n\n // Handle lists (e.g., 1,3,5 or 1-3,5-7)\n // Check lists before ranges because lists can contain ranges\n if (value.includes(',')) {\n return validateListField(value, constraints, fieldName);\n }\n\n // Handle ranges (e.g., 0-5)\n if (value.includes('-')) {\n return validateRangeField(value, constraints, fieldName);\n }\n\n // Single value\n return validateSingleValue(value, constraints, fieldName);\n}\n\n/**\n * Validates a step field with step syntax\n */\nfunction validateStepField(\n value: string,\n constraints: FieldConstraints,\n fieldName: string\n): ValidationResult {\n const parts = value.split('/');\n if (parts.length !== 2) {\n return {\n isValid: false,\n error: `Invalid step syntax in ${constraints.name}: ${value}`,\n };\n }\n\n const [range, step] = parts;\n\n // Validate step value\n const stepNum = parseInt(step, 10);\n if (isNaN(stepNum) || stepNum <= 0) {\n return {\n isValid: false,\n error: `Invalid step value in ${constraints.name}: ${step}`,\n };\n }\n\n // If range is *, it's valid\n if (range === '*') {\n return { isValid: true };\n }\n\n // If range is a number or range, validate it\n if (range.includes('-')) {\n return validateRangeField(range, constraints, fieldName);\n }\n\n return validateSingleValue(range, constraints, fieldName);\n}\n\n/**\n * Validates a range field (e.g., 0-5)\n */\nfunction validateRangeField(\n value: string,\n constraints: FieldConstraints,\n fieldName: string\n): ValidationResult {\n const parts = value.split('-');\n if (parts.length !== 2) {\n return {\n isValid: false,\n error: `Invalid range syntax in ${constraints.name}: ${value}`,\n };\n }\n\n const [startStr, endStr] = parts;\n const start = parseFieldValue(startStr, fieldName);\n const end = parseFieldValue(endStr, fieldName);\n\n if (start === null) {\n return {\n isValid: false,\n error: `Invalid start value in ${constraints.name} range: ${startStr}`,\n };\n }\n\n if (end === null) {\n return {\n isValid: false,\n error: `Invalid end value in ${constraints.name} range: ${endStr}`,\n };\n }\n\n if (start < constraints.min || start > constraints.max) {\n return {\n isValid: false,\n error: `Start value ${start} is out of range for ${constraints.name} (${constraints.min}-${constraints.max})`,\n };\n }\n\n if (end < constraints.min || end > constraints.max) {\n return {\n isValid: false,\n error: `End value ${end} is out of range for ${constraints.name} (${constraints.min}-${constraints.max})`,\n };\n }\n\n if (start > end) {\n return {\n isValid: false,\n error: `Start value ${start} cannot be greater than end value ${end} in ${constraints.name}`,\n };\n }\n\n return { isValid: true };\n}\n\n/**\n * Validates a list field (e.g., 1,3,5)\n */\nfunction validateListField(\n value: string,\n constraints: FieldConstraints,\n fieldName: string\n): ValidationResult {\n const values = value.split(',');\n\n for (const val of values) {\n const trimmed = val.trim();\n if (!trimmed) {\n return {\n isValid: false,\n error: `Empty value in ${constraints.name} list`,\n };\n }\n\n // Each item can be a single value or a range\n if (trimmed.includes('-')) {\n const result = validateRangeField(trimmed, constraints, fieldName);\n if (!result.isValid) {\n return result;\n }\n } else {\n const result = validateSingleValue(trimmed, constraints, fieldName);\n if (!result.isValid) {\n return result;\n }\n }\n }\n\n return { isValid: true };\n}\n\n/**\n * Validates a single numeric value\n */\nfunction validateSingleValue(\n value: string,\n constraints: FieldConstraints,\n fieldName: string\n): ValidationResult {\n const num = parseFieldValue(value, fieldName);\n\n if (num === null) {\n return {\n isValid: false,\n error: `Invalid value in ${constraints.name}: ${value}`,\n };\n }\n\n if (num < constraints.min || num > constraints.max) {\n return {\n isValid: false,\n error: `Value ${num} is out of range for ${constraints.name} (${constraints.min}-${constraints.max})`,\n };\n }\n\n return { isValid: true };\n}\n\n/**\n * Parses a field value, handling numeric values and named values (MON, JAN, etc.)\n */\nfunction parseFieldValue(value: string, fieldName: string): number | null {\n // Try parsing as number first\n const num = parseInt(value, 10);\n if (!isNaN(num)) {\n return num;\n }\n\n // Try parsing as month name\n if (fieldName === 'month') {\n const monthNum = MONTH_NAMES[value.toUpperCase()];\n if (monthNum !== undefined) {\n return monthNum;\n }\n }\n\n // Try parsing as day name\n if (fieldName === 'dayOfWeek') {\n const dayNum = DAY_NAMES[value.toUpperCase()];\n if (dayNum !== undefined) {\n return dayNum;\n }\n }\n\n return null;\n}\n","import type { ParsedCron, CronField, FieldConstraints } from './types.js';\nimport { FIELD_CONSTRAINTS, SPECIAL_KEYWORDS, MONTH_NAMES, DAY_NAMES } from './types.js';\nimport { validateCron } from './validator.js';\n\n/**\n * Parses a cron expression into a structured format\n *\n * @param expression - The cron expression to parse\n * @param allowSeconds - Whether to allow 6-field cron expressions with seconds\n * @returns ParsedCron object with structured field information\n * @throws Error if the cron expression is invalid\n *\n * @example\n * parseCron('0 2 * * *')\n * // Returns: { minute: { raw: '0', values: [0], ... }, hour: { raw: '2', values: [2], ... }, ... }\n *\n * parseCron('* /15 9-17 * * 1-5')\n * // Returns parsed structure for \"every 15 minutes between 9 AM and 5 PM, Monday to Friday\"\n */\nexport function parseCron(expression: string, allowSeconds = false): ParsedCron {\n // Validate first\n const validation = validateCron(expression, allowSeconds);\n if (!validation.isValid) {\n throw new Error(validation.error || 'Invalid cron expression');\n }\n\n const trimmed = expression.trim();\n\n // Handle special keywords\n if (trimmed.startsWith('@')) {\n const actualExpression = SPECIAL_KEYWORDS[trimmed];\n return {\n expression: trimmed,\n ...parseStandardCron(actualExpression, false),\n isSpecial: true,\n specialKeyword: trimmed,\n };\n }\n\n return {\n expression: trimmed,\n ...parseStandardCron(trimmed, allowSeconds),\n isSpecial: false,\n };\n}\n\n/**\n * Parses a standard cron expression (non-special)\n */\nfunction parseStandardCron(\n expression: string,\n allowSeconds: boolean\n): Omit<ParsedCron, 'expression' | 'isSpecial'> {\n const fields = expression.split(/\\s+/);\n\n if (allowSeconds && fields.length === 6) {\n const [second, minute, hour, dayOfMonth, month, dayOfWeek] = fields;\n return {\n second: parseField(second, FIELD_CONSTRAINTS.second, 'second'),\n minute: parseField(minute, FIELD_CONSTRAINTS.minute, 'minute'),\n hour: parseField(hour, FIELD_CONSTRAINTS.hour, 'hour'),\n dayOfMonth: parseField(dayOfMonth, FIELD_CONSTRAINTS.dayOfMonth, 'dayOfMonth'),\n month: parseField(month, FIELD_CONSTRAINTS.month, 'month'),\n dayOfWeek: parseField(dayOfWeek, FIELD_CONSTRAINTS.dayOfWeek, 'dayOfWeek'),\n };\n }\n\n const [minute, hour, dayOfMonth, month, dayOfWeek] = fields;\n return {\n minute: parseField(minute, FIELD_CONSTRAINTS.minute, 'minute'),\n hour: parseField(hour, FIELD_CONSTRAINTS.hour, 'hour'),\n dayOfMonth: parseField(dayOfMonth, FIELD_CONSTRAINTS.dayOfMonth, 'dayOfMonth'),\n month: parseField(month, FIELD_CONSTRAINTS.month, 'month'),\n dayOfWeek: parseField(dayOfWeek, FIELD_CONSTRAINTS.dayOfWeek, 'dayOfWeek'),\n };\n}\n\n/**\n * Parses a single cron field\n */\nfunction parseField(value: string, constraints: FieldConstraints, fieldName: string): CronField {\n const raw = value;\n const isWildcard = value === '*' || value === '?';\n const isStep = value.includes('/');\n const isRange = value.includes('-') && !isStep;\n const isList = value.includes(',');\n\n let values: number[];\n\n if (isWildcard) {\n // Generate all possible values\n values = generateRange(constraints.min, constraints.max);\n } else if (isStep) {\n values = parseStepField(value, constraints, fieldName);\n } else if (isList) {\n values = parseListField(value, constraints, fieldName);\n } else if (isRange) {\n values = parseRangeField(value, constraints, fieldName);\n } else {\n // Single value\n const num = parseFieldValue(value, fieldName);\n values = num !== null ? [num] : [];\n }\n\n // Normalize day of week (both 0 and 7 are Sunday)\n if (fieldName === 'dayOfWeek') {\n values = values.map((v) => (v === 7 ? 0 : v));\n // Remove duplicates\n values = [...new Set(values)];\n }\n\n // Sort values\n values.sort((a, b) => a - b);\n\n return {\n raw,\n values,\n isWildcard,\n isRange,\n isStep,\n isList,\n };\n}\n\n/**\n * Parses a step field with step syntax\n */\nfunction parseStepField(value: string, constraints: FieldConstraints, fieldName: string): number[] {\n const [range, stepStr] = value.split('/');\n const step = parseInt(stepStr, 10);\n\n let baseValues: number[];\n\n if (range === '*') {\n baseValues = generateRange(constraints.min, constraints.max);\n } else if (range.includes('-')) {\n baseValues = parseRangeField(range, constraints, fieldName);\n } else {\n const num = parseFieldValue(range, fieldName);\n baseValues = num !== null ? [num] : [];\n }\n\n // Apply step\n const result: number[] = [];\n for (let i = 0; i < baseValues.length; i += step) {\n result.push(baseValues[i]);\n }\n\n return result;\n}\n\n/**\n * Parses a range field (e.g., 0-5)\n */\nfunction parseRangeField(\n value: string,\n _constraints: FieldConstraints,\n fieldName: string\n): number[] {\n const [startStr, endStr] = value.split('-');\n const start = parseFieldValue(startStr, fieldName);\n const end = parseFieldValue(endStr, fieldName);\n\n if (start === null || end === null) {\n return [];\n }\n\n return generateRange(start, end);\n}\n\n/**\n * Parses a list field (e.g., 1,3,5)\n */\nfunction parseListField(\n value: string,\n _constraints: FieldConstraints,\n fieldName: string\n): number[] {\n const parts = value.split(',');\n const result: number[] = [];\n\n for (const part of parts) {\n const trimmed = part.trim();\n if (trimmed.includes('-')) {\n const rangeValues = parseRangeField(trimmed, _constraints, fieldName);\n result.push(...rangeValues);\n } else {\n const num = parseFieldValue(trimmed, fieldName);\n if (num !== null) {\n result.push(num);\n }\n }\n }\n\n return result;\n}\n\n/**\n * Parses a field value, handling numeric values and named values (MON, JAN, etc.)\n */\nfunction parseFieldValue(value: string, fieldName: string): number | null {\n // Try parsing as number first\n const num = parseInt(value, 10);\n if (!isNaN(num)) {\n return num;\n }\n\n // Try parsing as month name\n if (fieldName === 'month') {\n const monthNum = MONTH_NAMES[value.toUpperCase()];\n if (monthNum !== undefined) {\n return monthNum;\n }\n }\n\n // Try parsing as day name\n if (fieldName === 'dayOfWeek') {\n const dayNum = DAY_NAMES[value.toUpperCase()];\n if (dayNum !== undefined) {\n return dayNum;\n }\n }\n\n return null;\n}\n\n/**\n * Generates a range of numbers from start to end (inclusive)\n */\nfunction generateRange(start: number, end: number): number[] {\n const result: number[] = [];\n for (let i = start; i <= end; i++) {\n result.push(i);\n }\n return result;\n}\n","/**\n * Internationalization strings for Spanish\n */\nexport interface I18nStrings {\n at: string;\n every: string;\n everyMinute: string;\n everyHour: string;\n everyDay: string;\n everyWeek: string;\n everyMonth: string;\n everyYear: string;\n minute: string;\n minutes: string;\n hour: string;\n hours: string;\n day: string;\n days: string;\n week: string;\n weeks: string;\n month: string;\n months: string;\n year: string;\n years: string;\n on: string;\n in: string;\n and: string;\n between: string;\n through: string;\n of: string;\n second: string;\n seconds: string;\n\n // Day names\n sunday: string;\n monday: string;\n tuesday: string;\n wednesday: string;\n thursday: string;\n friday: string;\n saturday: string;\n\n // Month names\n january: string;\n february: string;\n march: string;\n april: string;\n may: string;\n june: string;\n july: string;\n august: string;\n september: string;\n october: string;\n november: string;\n december: string;\n\n // Time periods\n am: string;\n pm: string;\n midnight: string;\n noon: string;\n\n // Special\n weekday: string;\n weekend: string;\n}\n\nexport const es: I18nStrings = {\n at: 'a las',\n every: 'cada',\n everyMinute: 'cada minuto',\n everyHour: 'cada hora',\n everyDay: 'todos los días',\n everyWeek: 'cada semana',\n everyMonth: 'cada mes',\n everyYear: 'cada año',\n minute: 'minuto',\n minutes: 'minutos',\n hour: 'hora',\n hours: 'horas',\n day: 'día',\n days: 'días',\n week: 'semana',\n weeks: 'semanas',\n month: 'mes',\n months: 'meses',\n year: 'año',\n years: 'años',\n on: 'el',\n in: 'en',\n and: 'y',\n between: 'entre',\n through: 'hasta',\n of: 'de',\n second: 'segundo',\n seconds: 'segundos',\n\n // Day names\n sunday: 'domingo',\n monday: 'lunes',\n tuesday: 'martes',\n wednesday: 'miércoles',\n thursday: 'jueves',\n friday: 'viernes',\n saturday: 'sábado',\n\n // Month names\n january: 'enero',\n february: 'febrero',\n march: 'marzo',\n april: 'abril',\n may: 'mayo',\n june: 'junio',\n july: 'julio',\n august: 'agosto',\n september: 'septiembre',\n october: 'octubre',\n november: 'noviembre',\n december: 'diciembre',\n\n // Time periods\n am: 'AM',\n pm: 'PM',\n midnight: 'medianoche',\n noon: 'mediodía',\n\n // Special\n weekday: 'día de semana',\n weekend: 'fin de semana',\n};\n","import type { I18nStrings } from './es.js';\n\nexport const en: I18nStrings = {\n at: 'at',\n every: 'every',\n everyMinute: 'every minute',\n everyHour: 'every hour',\n everyDay: 'every day',\n everyWeek: 'every week',\n everyMonth: 'every month',\n everyYear: 'every year',\n minute: 'minute',\n minutes: 'minutes',\n hour: 'hour',\n hours: 'hours',\n day: 'day',\n days: 'days',\n week: 'week',\n weeks: 'weeks',\n month: 'month',\n months: 'months',\n year: 'year',\n years: 'years',\n on: 'on',\n in: 'in',\n and: 'and',\n between: 'between',\n through: 'through',\n of: 'of',\n second: 'second',\n seconds: 'seconds',\n\n // Day names\n sunday: 'Sunday',\n monday: 'Monday',\n tuesday: 'Tuesday',\n wednesday: 'Wednesday',\n thursday: 'Thursday',\n friday: 'Friday',\n saturday: 'Saturday',\n\n // Month names\n january: 'January',\n february: 'February',\n march: 'March',\n april: 'April',\n may: 'May',\n june: 'June',\n july: 'July',\n august: 'August',\n september: 'September',\n october: 'October',\n november: 'November',\n december: 'December',\n\n // Time periods\n am: 'AM',\n pm: 'PM',\n midnight: 'midnight',\n noon: 'noon',\n\n // Special\n weekday: 'weekday',\n weekend: 'weekend',\n};\n","import type { ParsedCron, FormatterOptions } from './types.js';\nimport type { I18nStrings } from '../i18n/es.js';\nimport { parseCron } from './parser.js';\nimport { es } from '../i18n/es.js';\nimport { en } from '../i18n/en.js';\n\n/**\n * Helper function to check if an array of numbers is a consecutive range\n */\nfunction isConsecutiveRange(values: number[]): boolean {\n if (values.length < 2) return false;\n for (let i = 1; i < values.length; i++) {\n if (values[i] !== values[i - 1] + 1) {\n return false;\n }\n }\n return true;\n}\n\n/**\n * Formats a cron expression into human-readable text\n *\n * @param expression - The cron expression to format\n * @param options - Formatting options (locale, format preferences)\n * @returns Human-readable description of the cron expression\n *\n * @example\n * formatCron('0 2 * * *', { locale: 'es' })\n * // Returns: \"A las 2:00 AM, todos los días\"\n *\n * formatCron('* /15 9-17 * * 1-5', { locale: 'en' })\n * // Returns: \"Every 15 minutes, between 9:00 AM and 5:00 PM, Monday through Friday\"\n */\nexport function formatCron(expression: string, options: FormatterOptions = {}): string {\n const {\n locale = 'en',\n use24HourFormat = true,\n includeSeconds = false,\n verbose = false,\n } = options;\n\n const i18n = locale === 'es' ? es : en;\n const parsed = parseCron(expression, includeSeconds);\n\n // Handle special keywords\n if (parsed.isSpecial && parsed.specialKeyword) {\n return formatSpecialKeyword(parsed.specialKeyword, i18n);\n }\n\n return formatStandardCron(parsed, i18n, use24HourFormat, verbose);\n}\n\n/**\n * Formats special cron keywords\n */\nfunction formatSpecialKeyword(keyword: string, i18n: I18nStrings): string {\n const map: Record<string, string> = {\n '@yearly': i18n.everyYear,\n '@annually': i18n.everyYear,\n '@monthly': i18n.everyMonth,\n '@weekly': i18n.everyWeek,\n '@daily': i18n.everyDay,\n '@midnight': `${i18n.at} ${i18n.midnight}`,\n '@hourly': i18n.everyHour,\n };\n\n return map[keyword] || keyword;\n}\n\n/**\n * Formats a standard cron expression\n */\nfunction formatStandardCron(\n parsed: ParsedCron,\n i18n: I18nStrings,\n use24HourFormat: boolean,\n verbose: boolean\n): string {\n const parts: string[] = [];\n\n // Time part (seconds, minutes, hours)\n const timePart = formatTime(parsed, i18n, use24HourFormat);\n if (timePart) {\n parts.push(timePart);\n }\n\n // Day/Month part\n const datePart = formatDate(parsed, i18n, verbose);\n if (datePart) {\n parts.push(datePart);\n }\n\n return parts.join(', ');\n}\n\n/**\n * Formats the time portion of a cron expression\n */\nfunction formatTime(parsed: ParsedCron, i18n: I18nStrings, use24HourFormat: boolean): string {\n const { minute, hour, second } = parsed;\n\n // Check for special patterns\n if (minute.isWildcard && hour.isWildcard) {\n if (second && !second.isWildcard) {\n return `${i18n.at} ${i18n.second} ${second.values.join(', ')}`;\n }\n return i18n.everyMinute;\n }\n\n if (minute.isWildcard) {\n // Every minute of specific hours\n if (hour.values.length === 1) {\n const formattedHour = formatHour(hour.values[0], use24HourFormat, i18n);\n return `${i18n.everyMinute} ${i18n.at} ${formattedHour}`;\n }\n if (hour.values.length > 1 && hour.isRange) {\n const start = formatHour(hour.values[0], use24HourFormat, i18n);\n const end = formatHour(hour.values[hour.values.length - 1], use24HourFormat, i18n);\n return `${i18n.everyMinute}, ${i18n.between} ${start} ${i18n.and} ${end}`;\n }\n }\n\n if (hour.isWildcard && !minute.isWildcard) {\n // Every hour at specific minutes\n if (minute.values.length === 1) {\n return `${i18n.at} ${i18n.minute} ${minute.values[0]}`;\n }\n if (minute.isStep) {\n const step = minute.values[1] - minute.values[0];\n return `${i18n.every} ${step} ${i18n.minutes}`;\n }\n }\n\n // Specific time\n if (!minute.isWildcard && !hour.isWildcard) {\n if (minute.values.length === 1 && hour.values.length === 1) {\n const time = formatTime24Hour(hour.values[0], minute.values[0]);\n const formatted = use24HourFormat\n ? time\n : formatTime12Hour(hour.values[0], minute.values[0], i18n);\n return `${i18n.at} ${formatted}`;\n }\n\n // Multiple specific times\n if (minute.values.length > 1 || hour.values.length > 1) {\n // Check if it's a range pattern (consecutive hours with same minute)\n if (\n minute.values.length === 1 &&\n hour.isRange &&\n hour.values.length > 1 &&\n isConsecutiveRange(hour.values)\n ) {\n const startTime = use24HourFormat\n ? formatTime24Hour(hour.values[0], minute.values[0])\n : formatTime12Hour(hour.values[0], minute.values[0], i18n);\n const endTime = use24HourFormat\n ? formatTime24Hour(hour.values[hour.values.length - 1], minute.values[0])\n : formatTime12Hour(hour.values[hour.values.length - 1], minute.values[0], i18n);\n return `${i18n.between} ${startTime} ${i18n.and} ${endTime}`;\n }\n\n if (minute.isStep) {\n const step = minute.values[1] - minute.values[0];\n if (hour.isRange) {\n const start = formatHour(hour.values[0], use24HourFormat, i18n);\n const end = formatHour(hour.values[hour.values.length - 1], use24HourFormat, i18n);\n return `${i18n.every} ${step} ${i18n.minutes}, ${i18n.between} ${start} ${i18n.and} ${end}`;\n }\n return `${i18n.every} ${step} ${i18n.minutes}`;\n }\n }\n }\n\n // Default: list all combinations\n return formatTimeList(parsed, i18n, use24HourFormat);\n}\n\n/**\n * Formats the date portion of a cron expression\n */\nfunction formatDate(parsed: ParsedCron, i18n: I18nStrings, verbose: boolean): string {\n const { dayOfMonth, month, dayOfWeek } = parsed;\n\n // Every day\n if (dayOfMonth.isWildcard && dayOfWeek.isWildcard && month.isWildcard) {\n return i18n.everyDay;\n }\n\n const parts: string[] = [];\n\n // Day of week\n if (!dayOfWeek.isWildcard) {\n const dayPart = formatDaysOfWeek(dayOfWeek.values, i18n, verbose);\n if (dayPart) {\n parts.push(dayPart);\n }\n }\n\n // Day of month\n if (!dayOfMonth.isWildcard && dayOfWeek.isWildcard) {\n const dayPart = formatDaysOfMonth(dayOfMonth.values, i18n, verbose);\n if (dayPart) {\n parts.push(dayPart);\n }\n }\n\n // Month\n if (!month.isWildcard) {\n const monthPart = formatMonths(month.values, i18n, verbose);\n if (monthPart) {\n parts.push(monthPart);\n }\n }\n\n return parts.join(', ');\n}\n\n/**\n * Formats hour in 24-hour format\n */\nfunction formatTime24Hour(hour: number, minute: number): string {\n return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;\n}\n\n/**\n * Formats hour in 12-hour format\n */\nfunction formatTime12Hour(hour: number, minute: number, i18n: I18nStrings): string {\n const period = hour < 12 ? i18n.am : i18n.pm;\n const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;\n return `${hour12}:${minute.toString().padStart(2, '0')} ${period}`;\n}\n\n/**\n * Formats a single hour\n */\nfunction formatHour(hour: number, use24HourFormat: boolean, i18n: I18nStrings): string {\n if (use24HourFormat) {\n return `${hour.toString().padStart(2, '0')}:00`;\n }\n return formatTime12Hour(hour, 0, i18n);\n}\n\n/**\n * Formats a list of times\n */\nfunction formatTimeList(parsed: ParsedCron, i18n: I18nStrings, use24HourFormat: boolean): string {\n const times: string[] = [];\n\n for (const hour of parsed.hour.values) {\n for (const minute of parsed.minute.values) {\n const time = use24HourFormat\n ? formatTime24Hour(hour, minute)\n : formatTime12Hour(hour, minute, i18n);\n times.push(time);\n }\n }\n\n if (times.length <= 3) {\n return `${i18n.at} ${times.join(`, `)}`;\n }\n\n return `${i18n.at} ${times.slice(0, 2).join(', ')}... (${times.length} times)`;\n}\n\n/**\n * Formats days of the week\n */\nfunction formatDaysOfWeek(days: number[], i18n: I18nStrings, verbose: boolean): string {\n const dayNames = [\n i18n.sunday,\n i18n.monday,\n i18n.tuesday,\n i18n.wednesday,\n i18n.thursday,\n i18n.friday,\n i18n.saturday,\n ];\n\n // Check for weekdays (Mon-Fri)\n if (\n days.length === 5 &&\n days.includes(1) &&\n days.includes(2) &&\n days.includes(3) &&\n days.includes(4) &&\n days.includes(5)\n ) {\n return i18n.weekday + 's';\n }\n\n // Check for weekend\n if (days.length === 2 && days.includes(0) && days.includes(6)) {\n return i18n.weekend + 's';\n }\n\n if (days.length === 1) {\n return i18n.on + ' ' + dayNames[days[0]];\n }\n\n if (days.length === 7) {\n return i18n.everyDay;\n }\n\n // List days\n const names = days.map((d) => dayNames[d]);\n if (verbose || days.length <= 3) {\n return formatList(names, i18n);\n }\n\n return `${names[0]} ${i18n.through} ${names[names.length - 1]}`;\n}\n\n/**\n * Formats days of the month\n */\nfunction formatDaysOfMonth(days: number[], i18n: I18nStrings, verbose: boolean): string {\n if (days.length === 1) {\n return `${i18n.on} ${i18n.day} ${days[0]}`;\n }\n\n if (days.length === 31) {\n return i18n.everyDay;\n }\n\n if (verbose || days.length <= 3) {\n return `${i18n.on} ${i18n.days} ${days.join(', ')}`;\n }\n\n return `${i18n.on} ${i18n.days} ${days[0]} ${i18n.through} ${days[days.length - 1]}`;\n}\n\n/**\n * Formats months\n */\nfunction formatMonths(months: number[], i18n: I18nStrings, verbose: boolean): string {\n const monthNames = [\n i18n.january,\n i18n.february,\n i18n.march,\n i18n.april,\n i18n.may,\n i18n.june,\n i18n.july,\n i18n.august,\n i18n.september,\n i18n.october,\n i18n.november,\n i18n.december,\n ];\n\n if (months.length === 1) {\n return `${i18n.in} ${monthNames[months[0] - 1]}`;\n }\n\n if (months.length === 12) {\n return '';\n }\n\n const names = months.map((m) => monthNames[m - 1]);\n if (verbose || months.length <= 3) {\n return `${i18n.in} ${formatList(names, i18n)}`;\n }\n\n return `${i18n.in} ${names[0]} ${i18n.through} ${names[names.length - 1]}`;\n}\n\n/**\n * Formats a list of items with proper grammar\n */\nfunction formatList(items: string[], i18n: I18nStrings): string {\n if (items.length === 0) return '';\n if (items.length === 1) return items[0];\n if (items.length === 2) return `${items[0]} ${i18n.and} ${items[1]}`;\n\n const last = items[items.length - 1];\n const rest = items.slice(0, -1);\n return `${rest.join(', ')}, ${i18n.and} ${last}`;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ import { FormatterOptions } from './types.cjs';
2
+
3
+ /**
4
+ * Formats a cron expression into human-readable text
5
+ *
6
+ * @param expression - The cron expression to format
7
+ * @param options - Formatting options (locale, format preferences)
8
+ * @returns Human-readable description of the cron expression
9
+ *
10
+ * @example
11
+ * formatCron('0 2 * * *', { locale: 'es' })
12
+ * // Returns: "A las 2:00 AM, todos los días"
13
+ *
14
+ * formatCron('* /15 9-17 * * 1-5', { locale: 'en' })
15
+ * // Returns: "Every 15 minutes, between 9:00 AM and 5:00 PM, Monday through Friday"
16
+ */
17
+ declare function formatCron(expression: string, options?: FormatterOptions): string;
18
+
19
+ export { formatCron };
@@ -0,0 +1,19 @@
1
+ import { FormatterOptions } from './types.js';
2
+
3
+ /**
4
+ * Formats a cron expression into human-readable text
5
+ *
6
+ * @param expression - The cron expression to format
7
+ * @param options - Formatting options (locale, format preferences)
8
+ * @returns Human-readable description of the cron expression
9
+ *
10
+ * @example
11
+ * formatCron('0 2 * * *', { locale: 'es' })
12
+ * // Returns: "A las 2:00 AM, todos los días"
13
+ *
14
+ * formatCron('* /15 9-17 * * 1-5', { locale: 'en' })
15
+ * // Returns: "Every 15 minutes, between 9:00 AM and 5:00 PM, Monday through Friday"
16
+ */
17
+ declare function formatCron(expression: string, options?: FormatterOptions): string;
18
+
19
+ export { formatCron };
@@ -0,0 +1,2 @@
1
+ var h={"@yearly":"0 0 1 1 *","@annually":"0 0 1 1 *","@monthly":"0 0 1 * *","@weekly":"0 0 * * 0","@daily":"0 0 * * *","@midnight":"0 0 * * *","@hourly":"0 * * * *"},l={minute:{min:0,max:59,name:"minute"},hour:{min:0,max:23,name:"hour"},dayOfMonth:{min:1,max:31,name:"day of month"},month:{min:1,max:12,name:"month"},dayOfWeek:{min:0,max:7,name:"day of week"},second:{min:0,max:59,name:"second"}},p={JAN:1,FEB:2,MAR:3,APR:4,MAY:5,JUN:6,JUL:7,AUG:8,SEP:9,OCT:10,NOV:11,DEC:12},$={SUN:0,MON:1,TUE:2,WED:3,THU:4,FRI:5,SAT:6};function V(r,e=false){if(!r||typeof r!="string")return {isValid:false,error:"Cron expression must be a non-empty string"};let t=r.trim();if(t.startsWith("@"))return h[t]?{isValid:true}:{isValid:false,error:`Unknown special keyword: ${t}`};let n=t.split(/\s+/),s=e?6:5;if(n.length!==s)return {isValid:false,error:`Expected ${s} fields, got ${n.length}`};let a=e?["second","minute","hour","dayOfMonth","month","dayOfWeek"]:["minute","hour","dayOfMonth","month","dayOfWeek"];for(let i=0;i<n.length;i++){let o=a[i],u=n[i],d=l[o],f=A(u,d,o);if(!f.isValid)return {isValid:false,error:f.error,field:o}}return {isValid:true}}function A(r,e,t){return r?r==="*"?{isValid:true}:r==="?"?t==="dayOfMonth"||t==="dayOfWeek"?{isValid:true}:{isValid:false,error:`Question mark (?) is only valid for day fields, not ${e.name}`}:r.includes("/")?E(r,e,t):r.includes(",")?D(r,e,t):r.includes("-")?S(r,e,t):C(r,e,t):{isValid:false,error:`${e.name} field cannot be empty`}}function E(r,e,t){let n=r.split("/");if(n.length!==2)return {isValid:false,error:`Invalid step syntax in ${e.name}: ${r}`};let[s,a]=n,i=parseInt(a,10);return isNaN(i)||i<=0?{isValid:false,error:`Invalid step value in ${e.name}: ${a}`}:s==="*"?{isValid:true}:s.includes("-")?S(s,e,t):C(s,e,t)}function S(r,e,t){let n=r.split("-");if(n.length!==2)return {isValid:false,error:`Invalid range syntax in ${e.name}: ${r}`};let[s,a]=n,i=b(s,t),o=b(a,t);return i===null?{isValid:false,error:`Invalid start value in ${e.name} range: ${s}`}:o===null?{isValid:false,error:`Invalid end value in ${e.name} range: ${a}`}:i<e.min||i>e.max?{isValid:false,error:`Start value ${i} is out of range for ${e.name} (${e.min}-${e.max})`}:o<e.min||o>e.max?{isValid:false,error:`End value ${o} is out of range for ${e.name} (${e.min}-${e.max})`}:i>o?{isValid:false,error:`Start value ${i} cannot be greater than end value ${o} in ${e.name}`}:{isValid:true}}function D(r,e,t){let n=r.split(",");for(let s of n){let a=s.trim();if(!a)return {isValid:false,error:`Empty value in ${e.name} list`};if(a.includes("-")){let i=S(a,e,t);if(!i.isValid)return i}else {let i=C(a,e,t);if(!i.isValid)return i}}return {isValid:true}}function C(r,e,t){let n=b(r,t);return n===null?{isValid:false,error:`Invalid value in ${e.name}: ${r}`}:n<e.min||n>e.max?{isValid:false,error:`Value ${n} is out of range for ${e.name} (${e.min}-${e.max})`}:{isValid:true}}function b(r,e){let t=parseInt(r,10);if(!isNaN(t))return t;if(e==="month"){let n=p[r.toUpperCase()];if(n!==void 0)return n}if(e==="dayOfWeek"){let n=$[r.toUpperCase()];if(n!==void 0)return n}return null}function M(r,e=false){let t=V(r,e);if(!t.isValid)throw new Error(t.error||"Invalid cron expression");let n=r.trim();if(n.startsWith("@")){let s=h[n];return {expression:n,...W(s,false),isSpecial:true,specialKeyword:n}}return {expression:n,...W(n,e),isSpecial:false}}function W(r,e){let t=r.split(/\s+/);if(e&&t.length===6){let[u,d,f,I,R,j]=t;return {second:m(u,l.second,"second"),minute:m(d,l.minute,"minute"),hour:m(f,l.hour,"hour"),dayOfMonth:m(I,l.dayOfMonth,"dayOfMonth"),month:m(R,l.month,"month"),dayOfWeek:m(j,l.dayOfWeek,"dayOfWeek")}}let[n,s,a,i,o]=t;return {minute:m(n,l.minute,"minute"),hour:m(s,l.hour,"hour"),dayOfMonth:m(a,l.dayOfMonth,"dayOfMonth"),month:m(i,l.month,"month"),dayOfWeek:m(o,l.dayOfWeek,"dayOfWeek")}}function m(r,e,t){let n=r,s=r==="*"||r==="?",a=r.includes("/"),i=r.includes("-")&&!a,o=r.includes(","),u;if(s)u=k(e.min,e.max);else if(a)u=P(r,e,t);else if(o)u=T(r,e,t);else if(i)u=O(r,e,t);else {let d=g(r,t);u=d!==null?[d]:[];}return t==="dayOfWeek"&&(u=u.map(d=>d===7?0:d),u=[...new Set(u)]),u.sort((d,f)=>d-f),{raw:n,values:u,isWildcard:s,isRange:i,isStep:a,isList:o}}function P(r,e,t){let[n,s]=r.split("/"),a=parseInt(s,10),i;if(n==="*")i=k(e.min,e.max);else if(n.includes("-"))i=O(n,e,t);else {let u=g(n,t);i=u!==null?[u]:[];}let o=[];for(let u=0;u<i.length;u+=a)o.push(i[u]);return o}function O(r,e,t){let[n,s]=r.split("-"),a=g(n,t),i=g(s,t);return a===null||i===null?[]:k(a,i)}function T(r,e,t){let n=r.split(","),s=[];for(let a of n){let i=a.trim();if(i.includes("-")){let o=O(i,e,t);s.push(...o);}else {let o=g(i,t);o!==null&&s.push(o);}}return s}function g(r,e){let t=parseInt(r,10);if(!isNaN(t))return t;if(e==="month"){let n=p[r.toUpperCase()];if(n!==void 0)return n}if(e==="dayOfWeek"){let n=$[r.toUpperCase()];if(n!==void 0)return n}return null}function k(r,e){let t=[];for(let n=r;n<=e;n++)t.push(n);return t}var w={at:"a las",every:"cada",everyMinute:"cada minuto",everyHour:"cada hora",everyDay:"todos los d\xEDas",everyWeek:"cada semana",everyMonth:"cada mes",everyYear:"cada a\xF1o",minute:"minuto",minutes:"minutos",day:"d\xEDa",days:"d\xEDas",on:"el",in:"en",and:"y",between:"entre",through:"hasta",second:"segundo",sunday:"domingo",monday:"lunes",tuesday:"martes",wednesday:"mi\xE9rcoles",thursday:"jueves",friday:"viernes",saturday:"s\xE1bado",january:"enero",february:"febrero",march:"marzo",april:"abril",may:"mayo",june:"junio",july:"julio",august:"agosto",september:"septiembre",october:"octubre",november:"noviembre",december:"diciembre",am:"AM",pm:"PM",midnight:"medianoche",weekday:"d\xEDa de semana",weekend:"fin de semana"};var x={at:"at",every:"every",everyMinute:"every minute",everyHour:"every hour",everyDay:"every day",everyWeek:"every week",everyMonth:"every month",everyYear:"every year",minute:"minute",minutes:"minutes",day:"day",days:"days",on:"on",in:"in",and:"and",between:"between",through:"through",second:"second",sunday:"Sunday",monday:"Monday",tuesday:"Tuesday",wednesday:"Wednesday",thursday:"Thursday",friday:"Friday",saturday:"Saturday",january:"January",february:"February",march:"March",april:"April",may:"May",june:"June",july:"July",august:"August",september:"September",october:"October",november:"November",december:"December",am:"AM",pm:"PM",midnight:"midnight",weekday:"weekday",weekend:"weekend"};function N(r){if(r.length<2)return false;for(let e=1;e<r.length;e++)if(r[e]!==r[e-1]+1)return false;return true}function ie(r,e={}){let{locale:t="en",use24HourFormat:n=true,includeSeconds:s=false,verbose:a=false}=e,i=t==="es"?w:x,o=M(r,s);return o.isSpecial&&o.specialKeyword?L(o.specialKeyword,i):_(o,i,n,a)}function L(r,e){return {"@yearly":e.everyYear,"@annually":e.everyYear,"@monthly":e.everyMonth,"@weekly":e.everyWeek,"@daily":e.everyDay,"@midnight":`${e.at} ${e.midnight}`,"@hourly":e.everyHour}[r]||r}function _(r,e,t,n){let s=[],a=Y(r,e,t);a&&s.push(a);let i=U(r,e,n);return i&&s.push(i),s.join(", ")}function Y(r,e,t){let{minute:n,hour:s,second:a}=r;if(n.isWildcard&&s.isWildcard)return a&&!a.isWildcard?`${e.at} ${e.second} ${a.values.join(", ")}`:e.everyMinute;if(n.isWildcard){if(s.values.length===1){let i=c(s.values[0],t,e);return `${e.everyMinute} ${e.at} ${i}`}if(s.values.length>1&&s.isRange){let i=c(s.values[0],t,e),o=c(s.values[s.values.length-1],t,e);return `${e.everyMinute}, ${e.between} ${i} ${e.and} ${o}`}}if(s.isWildcard&&!n.isWildcard){if(n.values.length===1)return `${e.at} ${e.minute} ${n.values[0]}`;if(n.isStep){let i=n.values[1]-n.values[0];return `${e.every} ${i} ${e.minutes}`}}if(!n.isWildcard&&!s.isWildcard){if(n.values.length===1&&s.values.length===1){let i=v(s.values[0],n.values[0]),o=t?i:y(s.values[0],n.values[0],e);return `${e.at} ${o}`}if(n.values.length>1||s.values.length>1){if(n.values.length===1&&s.isRange&&s.values.length>1&&N(s.values)){let i=t?v(s.values[0],n.values[0]):y(s.values[0],n.values[0],e),o=t?v(s.values[s.values.length-1],n.values[0]):y(s.values[s.values.length-1],n.values[0],e);return `${e.between} ${i} ${e.and} ${o}`}if(n.isStep){let i=n.values[1]-n.values[0];if(s.isRange){let o=c(s.values[0],t,e),u=c(s.values[s.values.length-1],t,e);return `${e.every} ${i} ${e.minutes}, ${e.between} ${o} ${e.and} ${u}`}return `${e.every} ${i} ${e.minutes}`}}}return K(r,e,t)}function U(r,e,t){let{dayOfMonth:n,month:s,dayOfWeek:a}=r;if(n.isWildcard&&a.isWildcard&&s.isWildcard)return e.everyDay;let i=[];if(!a.isWildcard){let o=H(a.values,e,t);o&&i.push(o);}if(!n.isWildcard&&a.isWildcard){let o=J(n.values,e,t);o&&i.push(o);}if(!s.isWildcard){let o=z(s.values,e,t);o&&i.push(o);}return i.join(", ")}function v(r,e){return `${r.toString().padStart(2,"0")}:${e.toString().padStart(2,"0")}`}function y(r,e,t){let n=r<12?t.am:t.pm;return `${r===0?12:r>12?r-12:r}:${e.toString().padStart(2,"0")} ${n}`}function c(r,e,t){return e?`${r.toString().padStart(2,"0")}:00`:y(r,0,t)}function K(r,e,t){let n=[];for(let s of r.hour.values)for(let a of r.minute.values){let i=t?v(s,a):y(s,a,e);n.push(i);}return n.length<=3?`${e.at} ${n.join(", ")}`:`${e.at} ${n.slice(0,2).join(", ")}... (${n.length} times)`}function H(r,e,t){let n=[e.sunday,e.monday,e.tuesday,e.wednesday,e.thursday,e.friday,e.saturday];if(r.length===5&&r.includes(1)&&r.includes(2)&&r.includes(3)&&r.includes(4)&&r.includes(5))return e.weekday+"s";if(r.length===2&&r.includes(0)&&r.includes(6))return e.weekend+"s";if(r.length===1)return e.on+" "+n[r[0]];if(r.length===7)return e.everyDay;let s=r.map(a=>n[a]);return t||r.length<=3?F(s,e):`${s[0]} ${e.through} ${s[s.length-1]}`}function J(r,e,t){return r.length===1?`${e.on} ${e.day} ${r[0]}`:r.length===31?e.everyDay:t||r.length<=3?`${e.on} ${e.days} ${r.join(", ")}`:`${e.on} ${e.days} ${r[0]} ${e.through} ${r[r.length-1]}`}function z(r,e,t){let n=[e.january,e.february,e.march,e.april,e.may,e.june,e.july,e.august,e.september,e.october,e.november,e.december];if(r.length===1)return `${e.in} ${n[r[0]-1]}`;if(r.length===12)return "";let s=r.map(a=>n[a-1]);return t||r.length<=3?`${e.in} ${F(s,e)}`:`${e.in} ${s[0]} ${e.through} ${s[s.length-1]}`}function F(r,e){if(r.length===0)return "";if(r.length===1)return r[0];if(r.length===2)return `${r[0]} ${e.and} ${r[1]}`;let t=r[r.length-1];return `${r.slice(0,-1).join(", ")}, ${e.and} ${t}`}export{ie as formatCron};//# sourceMappingURL=formatter.js.map
2
+ //# sourceMappingURL=formatter.js.map