@statezero/core 0.1.78 → 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;
@@ -231,7 +234,7 @@ function createOperatorFromLookup(field, lookup, value, isRelationship, ModelCla
231
234
  }
232
235
  }
233
236
  // Handle date-related lookups
234
- if (['year', 'month', 'day', 'week_day', 'hour', 'minute', 'second'].includes(lookup)) {
237
+ if (['year', 'month', 'day', 'week_day', 'hour', 'minute', 'second', 'date', 'time'].includes(lookup)) {
235
238
  // For date part lookups, we'll use a custom operation
236
239
  return {
237
240
  field,
@@ -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)
@@ -408,11 +418,26 @@ function createDateOperations(timezone = 'UTC') {
408
418
  return false;
409
419
  // Convert to timezone
410
420
  const luxonDate = DateTime.fromJSDate(dateValue).setZone(timezone);
411
- const paramDate = DateTime.fromJSDate(new Date(params)).setZone(timezone);
421
+ // Parse the time string (format: "HH:MM:SS" or a Date object)
422
+ let paramHour, paramMinute, paramSecond;
423
+ if (typeof params === 'string') {
424
+ // Parse time string like "10:30:45"
425
+ const timeParts = params.split(':');
426
+ paramHour = parseInt(timeParts[0], 10);
427
+ paramMinute = parseInt(timeParts[1], 10);
428
+ paramSecond = parseInt(timeParts[2], 10);
429
+ }
430
+ else {
431
+ // If it's a Date object, extract time parts
432
+ const paramDate = DateTime.fromJSDate(new Date(params)).setZone(timezone);
433
+ paramHour = paramDate.hour;
434
+ paramMinute = paramDate.minute;
435
+ paramSecond = paramDate.second;
436
+ }
412
437
  // Compare hour, minute, and second
413
- return luxonDate.hour === paramDate.hour &&
414
- luxonDate.minute === paramDate.minute &&
415
- luxonDate.second === paramDate.second;
438
+ return luxonDate.hour === paramHour &&
439
+ luxonDate.minute === paramMinute &&
440
+ luxonDate.second === paramSecond;
416
441
  }, ownerQuery, options);
417
442
  }
418
443
  };
@@ -424,7 +449,9 @@ function createDateOperations(timezone = 'UTC') {
424
449
  'week_day': (dt) => dt.weekday === 7 ? 1 : dt.weekday + 1, // Convert to Django's format
425
450
  'hour': (dt) => dt.hour,
426
451
  'minute': (dt) => dt.minute,
427
- 'second': (dt) => dt.second
452
+ 'second': (dt) => dt.second,
453
+ 'date': (dt) => dt.toISODate(),
454
+ 'time': (dt) => dt.hour * 3600 + dt.minute * 60 + dt.second
428
455
  };
429
456
  // Generate comparison operations for each date part (year_gt, month_lt, etc.)
430
457
  const datePartComparisons = ['gt', 'gte', 'lt', 'lte', 'exact'];
@@ -443,13 +470,16 @@ function createDateOperations(timezone = 'UTC') {
443
470
  // Convert to timezone and extract part
444
471
  const luxonDate = DateTime.fromJSDate(dateValue).setZone(timezone);
445
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);
446
476
  // Apply the appropriate comparison
447
477
  switch (op) {
448
- case 'gt': return partValue > params;
449
- case 'gte': return partValue >= params;
450
- case 'lt': return partValue < params;
451
- case 'lte': return partValue <= params;
452
- 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;
453
483
  default: return false;
454
484
  }
455
485
  }, ownerQuery, options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statezero/core",
3
- "version": "0.1.78",
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",