@rip-lang/api 0.8.0 → 0.8.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 (2) hide show
  1. package/api.rip +65 -75
  2. package/package.json +1 -1
package/api.rip CHANGED
@@ -508,91 +508,81 @@ export getValidator = (name) -> validators[name]
508
508
  # read() — Sinatra-style Parameter Reading
509
509
  # ==============================================================================
510
510
 
511
- export read = (keyOrTag = null, tagOrMiss = null, missOrNil = null) ->
512
- store = requestContext.getStore()
513
- unless store?
514
- throw new Error 'read() called outside request context'
511
+ export read = (name = null, type = null, miss = null) ->
512
+ store = requestContext.getStore() or throw new Error 'no context for read()'
515
513
 
516
- data = store.data or {}
517
- key = null
518
- tag = null
519
- miss = null
514
+ # missing value helper
515
+ done = (must = false) ->
516
+ return miss() if typeof miss is 'function'
517
+ throw new Error "Missing required field: #{name}" if must
518
+ return miss ?? null
520
519
 
521
- [key, tag, miss] = typeof keyOrTag is 'string' \
522
- ? [keyOrTag, tagOrMiss, missOrNil] \
523
- : [null , keyOrTag , tagOrMiss]
520
+ # get value from store
521
+ v = store.data or {}
522
+ v = v[name] if name?
523
+ v = v.trim() if typeof v is 'string'
524
524
 
525
- raw = if key? then data[key] else data
526
- unless tag?
527
- return raw if raw?
528
- return miss() if typeof miss is 'function'
529
- return if miss? and miss isnt '' then miss else null
525
+ # value only, no validator
526
+ if !type?
527
+ return v if v?
528
+ return done()
530
529
 
531
- required = false
532
- if typeof tag is 'string' and tag.endsWith('!')
533
- required = true
534
- tag = tag.slice(0, -1)
530
+ # String: apply validator function
531
+ else if typeof type is 'string'
535
532
 
536
- v = raw
537
- v = v.trim() if typeof v is 'string'
533
+ # detect required value (trailing '!')
534
+ if type.endsWith '!'
535
+ must = true
536
+ type = type.slice(0, -1)
537
+
538
+ # apply validator function
539
+ f = getValidator(type)
540
+ v = String(v ?? '') unless type in ['array', 'hash', 'json']
541
+ v = if f then f(v) else null
538
542
 
539
- # Named validator
540
- if typeof tag is 'string'
541
- fn = getValidator(tag)
542
- v = if fn then fn(String(v or '')) else null
543
+ # Regex: apply regex pattern
544
+ else if type instanceof RegExp
545
+ s = String(v ?? '')
546
+ v = s.match(type)?[0] or null
543
547
 
544
548
  # Array: [min, max] constraint or enumeration
545
- else if Array.isArray(tag)
546
- if typeof tag[0] is 'number'
547
- minVal = tag[0]
548
- maxVal = tag[1]
549
- if typeof v is 'number' or (String(v) =~ /^[-+]?\d+$/)
550
- n = if typeof v is 'number' then v else parseInt(String(v))
551
- ok = not isNaN(n)
552
- ok = false if minVal? and n < minVal
553
- ok = false if maxVal? and n > maxVal
554
- v = if ok then n else null
549
+ else if Array.isArray(type)
550
+ s = String(v ?? '')
551
+ y = true
552
+ if typeof type[0] is 'number'
553
+ [min, max] = type
554
+ if typeof v is 'number' or (s =~ /^[-+]?\d+$/)
555
+ n = if typeof v is 'number' then v else +s
556
+ y = false if min? and n < min
557
+ y = false if max? and n > max
558
+ v = if y then n else null
555
559
  else
556
- s = String(v or '')
557
- ok = true
558
- ok = false if minVal? and s.length < minVal
559
- ok = false if maxVal? and s.length > maxVal
560
- v = if ok then s else null
560
+ y = false if min? and s.length < min
561
+ y = false if max? and s.length > max
562
+ v = if y then s else null
561
563
  else
562
- v = if tag.includes(String(v)) then String(v) else null
563
-
564
- # Regex
565
- else if tag instanceof RegExp
566
- v = String(v or '').match(tag)?[0] or null
567
-
568
- # Object constraints
569
- else if typeof tag is 'object'
570
- if tag.start? or tag.end?
571
- n = parseInt(v)
572
- v = if not isNaN(n) and (not tag.start? or n >= tag.start) and (not tag.end? or n <= tag.end) then n else null
573
- else if tag.min? or tag.max?
574
- if typeof v is 'number' or (String(v or '') =~ /^[-+]?\d+$/)
575
- n = if typeof v is 'number' then v else parseInt(String(v))
576
- ok = not isNaN(n)
577
- ok = false if tag.min? and n < tag.min
578
- ok = false if tag.max? and n > tag.max
579
- v = if ok then n else null
564
+ v = if type.includes(s) then s else null
565
+
566
+ # Object: start/end, min/max
567
+ else if type? and typeof type is 'object'
568
+ s = String(v ?? '')
569
+ if type.start? or type.end?
570
+ n = if s =~ /^[-+]?\d+$/ then +s else NaN
571
+ v = if not isNaN(n) and (not type.start? or n >= type.start) and (not type.end? or n <= type.end) then n else null
572
+ else if type.min? or type.max?
573
+ y = true
574
+ if typeof v is 'number' or (s =~ /^[-+]?\d+$/)
575
+ n = if typeof v is 'number' then v else +s
576
+ y = false if type.min? and n < type.min
577
+ y = false if type.max? and n > type.max
578
+ v = if y then n else null
580
579
  else
581
- s = String(v or '')
582
- ok = true
583
- ok = false if tag.min? and s.length < tag.min
584
- ok = false if tag.max? and s.length > tag.max
585
- v = if ok then s else null
586
-
587
- blank = v is null or v is undefined or (typeof v is 'string' and v.trim() is '')
588
-
589
- if blank
590
- if required
591
- return miss?() if typeof miss is 'function'
592
- throw new Error "Missing required field: #{key}"
593
- else
594
- return miss?() if typeof miss is 'function'
595
- return null if miss is '' or not miss? # Empty string or null/undefined → null
596
- return miss # Return 0, false, etc. as-is
580
+ y = false if type.min? and s.length < type.min
581
+ y = false if type.max? and s.length > type.max
582
+ v = if y then s else null
583
+
584
+ # blank / missing value handling
585
+ if not v? or (typeof v is 'string' and v.trim() is '')
586
+ return done(must)
597
587
 
598
588
  v
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/api",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "description": "Pure Rip API framework — elegant, fast, zero dependencies",
5
5
  "type": "module",
6
6
  "main": "api.rip",