@object-ui/core 5.4.0 → 5.4.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @object-ui/core
2
2
 
3
+ ## 5.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @object-ui/types@5.4.1
8
+
3
9
  ## 5.4.0
4
10
 
5
11
  ### Patch Changes
@@ -11,16 +11,26 @@
11
11
  * ISO date string instead of a literal `{current_quarter_start}`.
12
12
  *
13
13
  * Supported tokens (case-sensitive, both `{token}` and `${token}` forms):
14
- * - today → start of today (YYYY-MM-DD)
14
+ * - today / yesterday / tomorrow
15
15
  * - now → current timestamp (full ISO)
16
- * - current_week_start → Monday 00:00 of this week
17
- * - current_month_start → 1st 00:00 of this month
18
- * - current_quarter_start → 1st 00:00 of this quarter
19
- * - current_year_start → Jan 1 00:00 of this year
20
- * - last_week_start → Monday 00:00 of previous week
21
- * - last_month_start → 1st 00:00 of previous month
22
- * - last_quarter_start → 1st 00:00 of previous quarter
23
- * - last_year_start → Jan 1 00:00 of previous year
16
+ * - current_week_start / current_week_end
17
+ * - current_month_start / current_month_end
18
+ * - current_quarter_start / current_quarter_end
19
+ * - current_year_start / current_year_end
20
+ * - week_start / week_end / month_start / month_end /
21
+ * quarter_start / quarter_end / year_start / year_end
22
+ * (aliases for the matching `current_*` tokens)
23
+ * - last_week_start / last_week_end
24
+ * - last_month_start / last_month_end
25
+ * - last_quarter_start / last_quarter_end
26
+ * - last_year_start / last_year_end
27
+ * - next_week_start / next_month_start / next_quarter_start / next_year_start
28
+ *
29
+ * Parameterised tokens (match `N` as any positive integer):
30
+ * - {N_days_ago} / {N_days_from_now}
31
+ * - {N_weeks_ago} / {N_weeks_from_now}
32
+ * - {N_months_ago} / {N_months_from_now}
33
+ * - {N_years_ago} / {N_years_from_now}
24
34
  *
25
35
  * Walks any plain-object / array structure recursively. Non-string values
26
36
  * (and unknown tokens) are passed through untouched.
@@ -11,16 +11,26 @@
11
11
  * ISO date string instead of a literal `{current_quarter_start}`.
12
12
  *
13
13
  * Supported tokens (case-sensitive, both `{token}` and `${token}` forms):
14
- * - today → start of today (YYYY-MM-DD)
14
+ * - today / yesterday / tomorrow
15
15
  * - now → current timestamp (full ISO)
16
- * - current_week_start → Monday 00:00 of this week
17
- * - current_month_start → 1st 00:00 of this month
18
- * - current_quarter_start → 1st 00:00 of this quarter
19
- * - current_year_start → Jan 1 00:00 of this year
20
- * - last_week_start → Monday 00:00 of previous week
21
- * - last_month_start → 1st 00:00 of previous month
22
- * - last_quarter_start → 1st 00:00 of previous quarter
23
- * - last_year_start → Jan 1 00:00 of previous year
16
+ * - current_week_start / current_week_end
17
+ * - current_month_start / current_month_end
18
+ * - current_quarter_start / current_quarter_end
19
+ * - current_year_start / current_year_end
20
+ * - week_start / week_end / month_start / month_end /
21
+ * quarter_start / quarter_end / year_start / year_end
22
+ * (aliases for the matching `current_*` tokens)
23
+ * - last_week_start / last_week_end
24
+ * - last_month_start / last_month_end
25
+ * - last_quarter_start / last_quarter_end
26
+ * - last_year_start / last_year_end
27
+ * - next_week_start / next_month_start / next_quarter_start / next_year_start
28
+ *
29
+ * Parameterised tokens (match `N` as any positive integer):
30
+ * - {N_days_ago} / {N_days_from_now}
31
+ * - {N_weeks_ago} / {N_weeks_from_now}
32
+ * - {N_months_ago} / {N_months_from_now}
33
+ * - {N_years_ago} / {N_years_from_now}
24
34
  *
25
35
  * Walks any plain-object / array structure recursively. Non-string values
26
36
  * (and unknown tokens) are passed through untouched.
@@ -54,36 +64,105 @@ export function resolveDateMacros(filter, now = new Date()) {
54
64
  };
55
65
  const startOfYear = (d) => new Date(d.getFullYear(), 0, 1);
56
66
  const addMonths = (d, n) => new Date(d.getFullYear(), d.getMonth() + n, 1);
67
+ const addDays = (d, n) => {
68
+ const x = startOfDay(d);
69
+ x.setDate(x.getDate() + n);
70
+ return x;
71
+ };
72
+ const endOfMonth = (d) => addDays(addMonths(startOfMonth(d), 1), -1);
73
+ const endOfWeek = (d) => addDays(startOfWeek(d), 6);
74
+ const endOfQuarter = (d) => addDays(addMonths(startOfQuarter(d), 3), -1);
75
+ const endOfYear = (d) => new Date(d.getFullYear(), 11, 31);
57
76
  const macros = {
58
77
  today: () => isoDate(now),
78
+ yesterday: () => isoDate(addDays(now, -1)),
79
+ tomorrow: () => isoDate(addDays(now, 1)),
59
80
  now: () => now.toISOString(),
60
81
  current_week_start: () => isoDate(startOfWeek(now)),
82
+ current_week_end: () => isoDate(endOfWeek(now)),
61
83
  current_month_start: () => isoDate(startOfMonth(now)),
84
+ current_month_end: () => isoDate(endOfMonth(now)),
62
85
  current_quarter_start: () => isoDate(startOfQuarter(now)),
86
+ current_quarter_end: () => isoDate(endOfQuarter(now)),
63
87
  current_year_start: () => isoDate(startOfYear(now)),
64
- last_week_start: () => {
65
- const w = startOfWeek(now);
66
- w.setDate(w.getDate() - 7);
67
- return isoDate(w);
68
- },
88
+ current_year_end: () => isoDate(endOfYear(now)),
89
+ last_week_start: () => isoDate(addDays(startOfWeek(now), -7)),
90
+ last_week_end: () => isoDate(addDays(startOfWeek(now), -1)),
69
91
  last_month_start: () => isoDate(addMonths(startOfMonth(now), -1)),
92
+ last_month_end: () => isoDate(addDays(startOfMonth(now), -1)),
70
93
  last_quarter_start: () => isoDate(addMonths(startOfQuarter(now), -3)),
94
+ last_quarter_end: () => isoDate(addDays(startOfQuarter(now), -1)),
71
95
  last_year_start: () => isoDate(new Date(now.getFullYear() - 1, 0, 1)),
96
+ last_year_end: () => isoDate(new Date(now.getFullYear() - 1, 11, 31)),
97
+ next_week_start: () => isoDate(addDays(startOfWeek(now), 7)),
98
+ next_month_start: () => isoDate(addMonths(startOfMonth(now), 1)),
99
+ next_quarter_start: () => isoDate(addMonths(startOfQuarter(now), 3)),
100
+ next_year_start: () => isoDate(new Date(now.getFullYear() + 1, 0, 1)),
101
+ };
102
+ // Aliases: bare {week_start} etc. mean the current period.
103
+ const aliases = {
104
+ week_start: 'current_week_start',
105
+ week_end: 'current_week_end',
106
+ month_start: 'current_month_start',
107
+ month_end: 'current_month_end',
108
+ quarter_start: 'current_quarter_start',
109
+ quarter_end: 'current_quarter_end',
110
+ year_start: 'current_year_start',
111
+ year_end: 'current_year_end',
72
112
  };
73
- const tokenRe = /\$?\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
113
+ for (const [from, to] of Object.entries(aliases)) {
114
+ macros[from] = macros[to];
115
+ }
116
+ // Parameterised tokens: {N_days_ago}, {N_weeks_from_now}, ...
117
+ const paramRe = /^(\d+)_(days?|weeks?|months?|years?)_(ago|from_now)$/;
118
+ const resolveParam = (tok) => {
119
+ const m = tok.match(paramRe);
120
+ if (!m)
121
+ return null;
122
+ const n = parseInt(m[1], 10);
123
+ if (!Number.isFinite(n))
124
+ return null;
125
+ const sign = m[3] === 'ago' ? -1 : 1;
126
+ const unit = m[2].replace(/s$/, '');
127
+ if (unit === 'day')
128
+ return isoDate(addDays(now, sign * n));
129
+ if (unit === 'week')
130
+ return isoDate(addDays(now, sign * n * 7));
131
+ if (unit === 'month') {
132
+ const x = new Date(now.getFullYear(), now.getMonth() + sign * n, now.getDate());
133
+ return isoDate(x);
134
+ }
135
+ if (unit === 'year') {
136
+ const x = new Date(now.getFullYear() + sign * n, now.getMonth(), now.getDate());
137
+ return isoDate(x);
138
+ }
139
+ return null;
140
+ };
141
+ const tokenRe = /\$?\{([a-zA-Z0-9_]+)\}/g;
74
142
  const walk = (value) => {
75
143
  if (value == null)
76
144
  return value;
77
145
  if (typeof value === 'string') {
78
- const wholeMatch = value.match(/^\$?\{([a-zA-Z_][a-zA-Z0-9_]*)\}$/);
79
- if (wholeMatch && macros[wholeMatch[1]])
80
- return macros[wholeMatch[1]]();
146
+ const wholeMatch = value.match(/^\$?\{([a-zA-Z0-9_]+)\}$/);
147
+ if (wholeMatch) {
148
+ const tok = wholeMatch[1];
149
+ if (macros[tok])
150
+ return macros[tok]();
151
+ const param = resolveParam(tok);
152
+ if (param != null)
153
+ return param;
154
+ }
81
155
  let touched = false;
82
156
  const replaced = value.replace(tokenRe, (m, tok) => {
83
157
  if (macros[tok]) {
84
158
  touched = true;
85
159
  return macros[tok]();
86
160
  }
161
+ const param = resolveParam(tok);
162
+ if (param != null) {
163
+ touched = true;
164
+ return param;
165
+ }
87
166
  return m;
88
167
  });
89
168
  return touched ? replaced : value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/core",
3
- "version": "5.4.0",
3
+ "version": "5.4.1",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "license": "MIT",
@@ -28,7 +28,7 @@
28
28
  "@objectstack/spec": "^5.2.0",
29
29
  "lodash": "^4.18.1",
30
30
  "zod": "^4.4.3",
31
- "@object-ui/types": "5.4.0"
31
+ "@object-ui/types": "5.4.1"
32
32
  },
33
33
  "devDependencies": {
34
34
  "typescript": "^6.0.3",