@statezero/core 0.1.79 → 0.1.80

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.
@@ -150,8 +150,11 @@ function processFieldPath(fieldPath, value, ModelClass, options = {}) {
150
150
  }
151
151
  // Join the processed path parts, using dot notation for sift
152
152
  const finalPath = processedPath.join('.');
153
- // Normalize the value based on the field schema
154
- const normalizedValue = normalizeFilterValue(finalFieldName, value, currentModel);
153
+ // For date part lookups, don't normalize the value - keep it as-is for numeric/string comparison
154
+ // Date parts like 'year', 'month', etc. expect numeric values, not Date objects
155
+ const isDatePartLookup = dateParts.includes(lookup) || (lookupChain.length === 2 && dateParts.includes(lookupChain[0]));
156
+ // Normalize the value based on the field schema (skip for date part lookups)
157
+ const normalizedValue = isDatePartLookup ? value : normalizeFilterValue(finalFieldName, value, currentModel);
155
158
  // Handle the date part + comparison chain if present
156
159
  if (lookupChain.length === 2) {
157
160
  const [datePart, comparisonOperator] = lookupChain;
@@ -333,52 +336,59 @@ function createDateOperations(timezone = 'UTC') {
333
336
  const operations = {
334
337
  // Year - same in both
335
338
  $year(params, ownerQuery, options) {
339
+ const compareValue = typeof params === 'string' ? Number(params) : params;
336
340
  return createEqualsOperation((value) => {
337
341
  const year = getDatePart(value, dt => dt.year);
338
- return year !== null && year === params;
342
+ return year !== null && year === compareValue;
339
343
  }, ownerQuery, options);
340
344
  },
341
- // Month - Luxon is 1-indexed like Django
345
+ // Month - Luxon is 1-indexed like Django
342
346
  $month(params, ownerQuery, options) {
347
+ const compareValue = typeof params === 'string' ? Number(params) : params;
343
348
  return createEqualsOperation((value) => {
344
349
  const month = getDatePart(value, dt => dt.month); // Already 1-indexed
345
- return month !== null && month === params;
350
+ return month !== null && month === compareValue;
346
351
  }, ownerQuery, options);
347
352
  },
348
353
  // Day of month - same in both
349
354
  $day(params, ownerQuery, options) {
355
+ const compareValue = typeof params === 'string' ? Number(params) : params;
350
356
  return createEqualsOperation((value) => {
351
357
  const day = getDatePart(value, dt => dt.day);
352
- return day !== null && day === params;
358
+ return day !== null && day === compareValue;
353
359
  }, ownerQuery, options);
354
360
  },
355
361
  // Day of week - convert to Django's 1=Sunday format
356
362
  $week_day(params, ownerQuery, options) {
363
+ const compareValue = typeof params === 'string' ? Number(params) : params;
357
364
  return createEqualsOperation((value) => {
358
365
  // Convert from Luxon (1=Monday, 7=Sunday) to Django (1=Sunday, 7=Saturday)
359
366
  const weekDay = getDatePart(value, dt => dt.weekday === 7 ? 1 : dt.weekday + 1);
360
- return weekDay !== null && weekDay === params;
367
+ return weekDay !== null && weekDay === compareValue;
361
368
  }, ownerQuery, options);
362
369
  },
363
370
  // Hour - same in both
364
371
  $hour(params, ownerQuery, options) {
372
+ const compareValue = typeof params === 'string' ? Number(params) : params;
365
373
  return createEqualsOperation((value) => {
366
374
  const hour = getDatePart(value, dt => dt.hour);
367
- return hour !== null && hour === params;
375
+ return hour !== null && hour === compareValue;
368
376
  }, ownerQuery, options);
369
377
  },
370
378
  // Minute - same in both
371
379
  $minute(params, ownerQuery, options) {
380
+ const compareValue = typeof params === 'string' ? Number(params) : params;
372
381
  return createEqualsOperation((value) => {
373
382
  const minute = getDatePart(value, dt => dt.minute);
374
- return minute !== null && minute === params;
383
+ return minute !== null && minute === compareValue;
375
384
  }, ownerQuery, options);
376
385
  },
377
386
  // Second - same in both
378
387
  $second(params, ownerQuery, options) {
388
+ const compareValue = typeof params === 'string' ? Number(params) : params;
379
389
  return createEqualsOperation((value) => {
380
390
  const second = getDatePart(value, dt => dt.second);
381
- return second !== null && second === params;
391
+ return second !== null && second === compareValue;
382
392
  }, ownerQuery, options);
383
393
  },
384
394
  // Date - extract date portion (ignore time)
@@ -460,13 +470,16 @@ function createDateOperations(timezone = 'UTC') {
460
470
  // Convert to timezone and extract part
461
471
  const luxonDate = DateTime.fromJSDate(dateValue).setZone(timezone);
462
472
  const partValue = extractor(luxonDate);
473
+ // Coerce params to number for numeric comparisons (all parts except 'date' which is a string)
474
+ // date part returns ISO date string like "2022-03-15", time returns number (seconds)
475
+ const compareValue = part === 'date' ? params : (typeof params === 'string' ? Number(params) : params);
463
476
  // Apply the appropriate comparison
464
477
  switch (op) {
465
- case 'gt': return partValue > params;
466
- case 'gte': return partValue >= params;
467
- case 'lt': return partValue < params;
468
- case 'lte': return partValue <= params;
469
- case 'exact': return partValue === params;
478
+ case 'gt': return partValue > compareValue;
479
+ case 'gte': return partValue >= compareValue;
480
+ case 'lt': return partValue < compareValue;
481
+ case 'lte': return partValue <= compareValue;
482
+ case 'exact': return partValue === compareValue;
470
483
  default: return false;
471
484
  }
472
485
  }, ownerQuery, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statezero/core",
3
- "version": "0.1.79",
3
+ "version": "0.1.80",
4
4
  "type": "module",
5
5
  "module": "ESNext",
6
6
  "description": "The type-safe frontend client for StateZero - connect directly to your backend models with zero boilerplate",