@sap/cds 6.0.4 → 6.1.2

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 (139) hide show
  1. package/CHANGELOG.md +180 -18
  2. package/apis/cds.d.ts +11 -7
  3. package/apis/log.d.ts +124 -0
  4. package/apis/ql.d.ts +72 -15
  5. package/apis/services.d.ts +13 -2
  6. package/bin/build/buildTaskHandler.js +5 -2
  7. package/bin/build/constants.js +4 -1
  8. package/bin/build/provider/buildTaskHandlerEdmx.js +11 -39
  9. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +14 -34
  10. package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
  11. package/bin/build/provider/buildTaskProviderInternal.js +22 -14
  12. package/bin/build/provider/hana/index.js +12 -9
  13. package/bin/build/provider/java/index.js +18 -8
  14. package/bin/build/provider/mtx/index.js +7 -4
  15. package/bin/build/provider/mtx/resourcesTarBuilder.js +60 -35
  16. package/bin/build/provider/mtx-extension/index.js +57 -0
  17. package/bin/build/provider/mtx-sidecar/index.js +46 -18
  18. package/bin/build/provider/nodejs/index.js +34 -13
  19. package/bin/deploy/to-hana/cfUtil.js +7 -2
  20. package/bin/deploy/to-hana/hana.js +20 -25
  21. package/bin/deploy/to-hana/hdiDeployUtil.js +13 -2
  22. package/bin/serve.js +7 -4
  23. package/lib/compile/{index.js → cds-compile.js} +0 -0
  24. package/lib/compile/extend.js +15 -5
  25. package/lib/compile/minify.js +1 -15
  26. package/lib/compile/parse.js +1 -1
  27. package/lib/compile/resolve.js +2 -2
  28. package/lib/compile/to/srvinfo.js +6 -4
  29. package/lib/{deploy.js → dbs/cds-deploy.js} +9 -8
  30. package/lib/env/{index.js → cds-env.js} +1 -17
  31. package/lib/env/{requires.js → cds-requires.js} +24 -3
  32. package/lib/env/defaults.js +7 -1
  33. package/lib/env/schemas/cds-package.json +11 -0
  34. package/lib/env/schemas/cds-rc.json +614 -0
  35. package/lib/index.js +19 -16
  36. package/lib/log/{errors.js → cds-error.js} +1 -1
  37. package/lib/log/{index.js → cds-log.js} +0 -0
  38. package/lib/log/format/kibana.js +19 -1
  39. package/lib/ql/Query.js +9 -3
  40. package/lib/ql/SELECT.js +2 -2
  41. package/lib/ql/UPDATE.js +2 -2
  42. package/lib/ql/{index.js → cds-ql.js} +4 -10
  43. package/lib/req/context.js +49 -17
  44. package/lib/req/locale.js +5 -1
  45. package/lib/{serve → srv}/adapters.js +23 -19
  46. package/lib/{connect → srv}/bindings.js +0 -0
  47. package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
  48. package/lib/{serve/index.js → srv/cds-serve.js} +0 -0
  49. package/lib/{serve → srv}/factory.js +1 -1
  50. package/lib/{serve/Service-api.js → srv/srv-api.js} +22 -6
  51. package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +13 -8
  52. package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
  53. package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
  54. package/lib/srv/srv-models.js +207 -0
  55. package/lib/{serve/Transaction.js → srv/srv-tx.js} +57 -40
  56. package/lib/utils/{tests.js → cds-test.js} +2 -2
  57. package/lib/utils/cds-utils.js +146 -0
  58. package/lib/utils/index.js +2 -145
  59. package/lib/utils/jest.js +43 -0
  60. package/lib/utils/resources/index.js +15 -25
  61. package/lib/utils/resources/tar.js +18 -41
  62. package/libx/_runtime/auth/index.js +14 -11
  63. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +7 -19
  64. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
  65. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -4
  66. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -4
  67. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
  68. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
  69. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
  70. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +3 -5
  71. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
  72. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -4
  73. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +0 -2
  74. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +3 -1
  75. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
  76. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -3
  77. package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
  78. package/libx/_runtime/cds-services/util/errors.js +1 -29
  79. package/libx/_runtime/common/i18n/messages.properties +2 -1
  80. package/libx/_runtime/common/perf/index.js +10 -15
  81. package/libx/_runtime/common/utils/binary.js +3 -4
  82. package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
  83. package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
  84. package/libx/_runtime/common/utils/keys.js +14 -6
  85. package/libx/_runtime/common/utils/resolveView.js +1 -1
  86. package/libx/_runtime/common/utils/template.js +1 -1
  87. package/libx/_runtime/db/Service.js +2 -14
  88. package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
  89. package/libx/_runtime/db/expand/rawToExpanded.js +7 -6
  90. package/libx/_runtime/db/generic/input.js +8 -1
  91. package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -1
  92. package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
  93. package/libx/_runtime/extensibility/activate.js +47 -47
  94. package/libx/_runtime/extensibility/add.js +22 -13
  95. package/libx/_runtime/extensibility/addExtension.js +17 -13
  96. package/libx/_runtime/extensibility/defaults.js +25 -30
  97. package/libx/_runtime/extensibility/handler/transformREAD.js +20 -18
  98. package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
  99. package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
  100. package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
  101. package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
  102. package/libx/_runtime/extensibility/linter.js +32 -0
  103. package/libx/_runtime/extensibility/push.js +77 -20
  104. package/libx/_runtime/extensibility/service.js +29 -12
  105. package/libx/_runtime/extensibility/token.js +57 -0
  106. package/libx/_runtime/extensibility/utils.js +8 -6
  107. package/libx/_runtime/extensibility/validation.js +6 -9
  108. package/libx/_runtime/fiori/generic/new.js +0 -11
  109. package/libx/_runtime/fiori/utils/where.js +1 -1
  110. package/libx/_runtime/hana/Service.js +0 -1
  111. package/libx/_runtime/hana/conversion.js +12 -1
  112. package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
  113. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
  114. package/libx/_runtime/hana/pool.js +6 -10
  115. package/libx/_runtime/hana/search2Contains.js +0 -5
  116. package/libx/_runtime/hana/search2cqn4sql.js +1 -0
  117. package/libx/_runtime/messaging/common-utils/authorizedRequest.js +1 -1
  118. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +1 -2
  119. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  120. package/libx/_runtime/messaging/service.js +11 -6
  121. package/libx/_runtime/remote/utils/data.js +5 -0
  122. package/libx/_runtime/sqlite/Service.js +7 -6
  123. package/libx/_runtime/sqlite/execute.js +41 -28
  124. package/libx/odata/afterburner.js +79 -2
  125. package/libx/odata/cqn2odata.js +15 -9
  126. package/libx/odata/grammar.pegjs +157 -76
  127. package/libx/odata/index.js +9 -3
  128. package/libx/odata/parser.js +1 -1
  129. package/libx/odata/utils.js +39 -5
  130. package/libx/rest/RestAdapter.js +3 -7
  131. package/libx/rest/middleware/delete.js +4 -5
  132. package/libx/rest/middleware/parse.js +3 -2
  133. package/package.json +3 -3
  134. package/server.js +1 -1
  135. package/srv/extensibility-service.cds +6 -3
  136. package/srv/model-provider.cds +3 -1
  137. package/srv/model-provider.js +86 -106
  138. package/srv/mtx.js +7 -1
  139. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +0 -240
@@ -27,6 +27,7 @@
27
27
  //
28
28
  // ---------- JavaScript Helpers -------------
29
29
  {
30
+
30
31
  const $ = Object.assign
31
32
  const { strict, minimal } = options
32
33
  const stack = []
@@ -243,7 +244,7 @@
243
244
 
244
245
  ODataRelativeURI // Note: case-sensitive!
245
246
  = '/'? (p:path { SELECT = p })
246
- ( o"?"o QueryOption ( o'&'o QueryOption )* )? o "?"? o {
247
+ ( o"?"o (QueryOption ( o'&'o QueryOption )*)? )? o {
247
248
  if (count) {
248
249
  // columns set because of $count: ignore $select, $expand, $top, $skip, $orderby
249
250
  // REVISIT: don't ignore query options but throw bad request (as okra did)?
@@ -334,46 +335,39 @@
334
335
  QueryOption = option:ExpandOption { if(option && option.apply) SELECT.apply = option.apply} /
335
336
  "$skiptoken=" o skiptoken /
336
337
  format /
337
- custom
338
+ custom /
339
+ aliasedParamEqualsVal
338
340
  // @OData spec for $expand:
339
341
  // "Allowed system query options are $filter, $select, $orderby, $skip, $top, $count, $search, $expand and $apply (http://docs.oasis-open.org/odata/odata-data-aggregation-ext/v4.0/cs02/odata-data-aggregation-ext-v4.0-cs02.html#_The_expand_Transformation)."
340
342
  ExpandOption =
341
343
  "$select=" o select ( COMMA select )* /
342
- "$expand=" o expand ( COMMA expand )* /
343
- "$filter=" o f:filter{SELECT.where = f} /
344
+ "$expand=" o expand ( COMMA expand )* expandCount? /
345
+ "$filter=" o f:filter { SELECT.where = f } /
344
346
  "$orderby=" o o:orderby ( COMMA o2:orderby{_setOrderBy(o2)} )* {_setOrderBy(o,true)} /
345
- "$top=" o val:top{(SELECT.limit || (SELECT.limit={})).rows = {val}} /
346
- "$skip=" o val:skip{_setLimitOffset(val)} /
347
- "$search=" o s:search {if (s) SELECT.search = s} /
347
+ "$top=" o val:top { (SELECT.limit || (SELECT.limit={})).rows = {val} } /
348
+ "$skip=" o val:skip { _setLimitOffset(val) } /
349
+ "$search=" o s:search { if (s) SELECT.search = s } /
348
350
  "$count=" o count /
349
- "$apply=" o trafos:transformations {return trafos}
351
+ "$apply=" o trafos:transformations { return trafos }
350
352
 
351
353
 
352
354
  select
353
- = col:('*'/ref) {
355
+ = col:('*' / ref) {
354
356
  SELECT.columns = Array.isArray(SELECT.columns) ? SELECT.columns : []
355
357
  if (!SELECT.columns.find(_compareRefs(col))) SELECT.columns.push(col)
356
358
  return col
357
359
  }
358
360
 
359
- //REVISIT: per OData spec $apply should be also supported inside of $expand
360
- expand =
361
- (
362
- c:('*'/ref) {
363
- const col = c === '*' ? {} : c
364
- col.expand = '*'
365
- if (!Array.isArray(SELECT.expand)) SELECT.expand = []
366
- if (!SELECT.expand.find(_compareRefs(col))) SELECT.expand.push(col)
367
- return col
368
- }
369
- )
370
- ( // --- nested query options, if any
371
- (OPEN {
372
- stack.push (SELECT)
373
- SELECT = SELECT.expand[SELECT.expand.length-1]
374
- SELECT.expand = '*' // by default expand everything
375
- })(
376
- expandOptions:( o ";"? o option:ExpandOption{return option})*
361
+ expandCount
362
+ = "/$count" {
363
+ const err = new Error("EXPAND_COUNT_UNSUPPORTED");
364
+ err.statusCode=501;
365
+ throw err;
366
+ }
367
+
368
+ expandQueryOptions
369
+ = (
370
+ expandOptions:(option:ExpandOption o ";"? { return option })*
377
371
  {
378
372
  if (expandOptions.find(option => option && option.apply !== undefined)) {
379
373
  const err = new Error("EXPAND_APPLY_UNSUPPORTED");
@@ -390,29 +384,50 @@
390
384
  if (Array.isArray(SELECT.expand) && SELECT.expand.indexOf('*') === -1) SELECT.expand.unshift('*')
391
385
  }
392
386
  }
393
- )(CLOSE {
387
+ )
388
+
389
+ expandQueryOption
390
+ = (OPEN {
391
+ stack.push (SELECT)
392
+ SELECT = SELECT.expand[SELECT.expand.length-1]
393
+ SELECT.expand = '*' // by default expand everything
394
+ })
395
+ expandQueryOptions?
396
+ (CLOSE {
394
397
  SELECT = stack.pop()
395
398
  })
396
- )? // --- end of nested query options
397
- ( COMMA expand )?
398
- ("/$count" {
399
- const err = new Error("EXPAND_COUNT_UNSUPPORTED");
400
- err.statusCode=501;
401
- throw err;
402
- })?
399
+
400
+
401
+ //REVISIT: per OData spec $apply should be also supported inside of $expand
402
+ expand
403
+ = (
404
+ c:('*' / ref) {
405
+ const col = c === '*' ? {} : c
406
+ col.expand = '*'
407
+ if (!Array.isArray(SELECT.expand)) SELECT.expand = []
408
+ if (!SELECT.expand.find(_compareRefs(col))) SELECT.expand.push(col)
409
+ return col
410
+ }
411
+ )
412
+ expandQueryOption?
413
+
403
414
  top
404
- = val:integer {return val}
415
+ = val:integer { return val }
416
+
405
417
  skiptoken
406
418
  = val:integer? skiptoken:skiptokenChars? {
407
419
  // REVISIT ignore non-numeric $skiptoken as not supported by CQN
408
420
  if (skiptoken) return
409
421
  _setLimitOffset(val)
410
422
  }
423
+
411
424
  skip
412
- = val:integer {return val}
425
+ = val:integer { return val }
426
+
413
427
  search
414
428
  = p:search_clause {return p}
415
429
  / o // Do not add search property for space only
430
+
416
431
  search_clause
417
432
  = p:( n:NOT? {return n?[n]:[]} )(
418
433
  OPEN xpr:search_clause CLOSE {p.push({xpr})}
@@ -422,9 +437,11 @@
422
437
  val:word {p.push({val})}
423
438
  )
424
439
  )( ao:(AND/OR/AND_SPACE) more:search_clause {p.push(ao,...more)} )*
425
- {return p}
440
+ { return p }
441
+
426
442
  filter
427
443
  = p:where_clause { return p }
444
+
428
445
  where_clause = p:( n:NOT? {return n?[n]:[]} )(
429
446
  OPEN xpr:where_clause CLOSE {p.push({xpr})}
430
447
  / comp:comparison {p.push(...comp)}
@@ -437,8 +454,10 @@
437
454
  }
438
455
  / func:boolish {p.push(func)}
439
456
  / val:bool {p.push({val})}
457
+ / list:listFilter {p.push(...list)}
440
458
  )( ao:(AND/OR) more:where_clause {p.push(ao,...more)} )*
441
- {return p}
459
+ { return p }
460
+
442
461
  lambda =
443
462
  nav:( n:identifier {return[n]} ) '/' ( n:identifier '/' {nav.push(n)} )*
444
463
  xpr:(
@@ -467,28 +486,48 @@
467
486
  }
468
487
  )
469
488
  { return xpr }
489
+
470
490
  inner_lambda =
471
491
  p:( n:NOT? { return n ? [n] : [] } )(
472
492
  OPEN xpr:inner_lambda CLOSE { p.push('(', ...xpr, ')') }
473
493
  / comp:comparison { p.push(...comp) }
474
494
  / func:function { p.push(func) }
475
495
  / lambda:lambda { p.push(...lambda)}
496
+ / list:listFilter {p.push(...list)}
476
497
  )
477
498
  ( ao:(AND/OR) more:inner_lambda { p.push(ao, ...more) } )*
478
499
  { return p }
479
- lambda_clause = prefix:identifier ":" inner:inner_lambda {
480
- return _removeLambdaPrefix(prefix, inner)
481
- }
482
- any = "any" OPEN p:lambda_clause? CLOSE { return p }
483
- all = "all" OPEN p:lambda_clause CLOSE { return p }
500
+
501
+ lambda_clause =
502
+ prefix:identifier ":" inner:inner_lambda {
503
+ return _removeLambdaPrefix(prefix, inner)
504
+ }
505
+
506
+ any =
507
+ "any" OPEN p:lambda_clause? CLOSE { return p }
508
+
509
+ all =
510
+ "all" OPEN p:lambda_clause CLOSE { return p }
511
+
484
512
  orderby
485
- = ref:(lambda{const err = new Error("ORDERBY_LAMBDA_UNSUPPORTED");err.statusCode=501;throw err;}/function/ref) sort:( _ s:$("asc"/"desc") {return s})? {
513
+ = ref:(
514
+ lambda {
515
+ const err = new Error("ORDERBY_LAMBDA_UNSUPPORTED");
516
+ err.statusCode=501;
517
+ throw err;
518
+ } /
519
+ function /
520
+ ref
521
+ )
522
+ sort:( _ s:$("asc" / "desc") { return s })? {
486
523
  // TODO: Lambda support
487
524
  const appendObj = $(ref, sort && {sort});
488
525
  return appendObj;
489
526
  }
527
+
490
528
  count
491
529
  = val:bool { if(val) SELECT.count = true }
530
+
492
531
  transformations
493
532
  = mainTransformation:trafo additionalTransformation:("/" t2:trafo {
494
533
  return t2
@@ -523,6 +562,8 @@
523
562
 
524
563
  custom
525
564
  = [a-zA-Z0-9-_.~]+ "=" [^&]*
565
+ aliasedParam "an aliased parameter (@param)" = "@" i:identifier { return "@" + i }
566
+ aliasedParamEqualsVal "@alias=value" = a:aliasedParam "=" v:([^&]*) {return a + "=" + v}
526
567
 
527
568
  format = "$format=" f:$([^&]*) {
528
569
  if (f.toLowerCase() !== "json") {
@@ -531,17 +572,25 @@
531
572
  throw err;
532
573
  }
533
574
  }
575
+
534
576
  //
535
577
  // ---------- Expressions ------------
536
- comparison "a comparison"
537
- = a:operand _ o:$("eq"/"ne"/"lt"/"gt"/"le"/"ge") _ b:operand {
538
- const op = { eq:'=', ne:'!=', lt:'<', gt:'>', le:'<=', ge:'>=' }[o]||o
578
+ comparison
579
+ = a:operand _ o:$("eq" / "ne" / "lt" / "gt" / "le" / "ge") _ b:operand {
580
+ const op = { eq:'=', ne:'!=', lt:'<', gt:'>', le:'<=', ge:'>=' }[o] || o
539
581
  return [ a, op, b ]
540
582
  }
583
+
584
+ listFilter
585
+ = a:operand _ "in" _ b:listRoundBrackets {
586
+ return [ a, "in", b ]
587
+ }
541
588
  mathCalc
542
589
  = operand (_ ("add" / "sub" / "mul" / "div" / "mod") _ operand)*
543
- operand "an operand"
590
+
591
+ operand
544
592
  = navigationCount / function / val / ref / jsonObject / jsonArray / list
593
+
545
594
  navigationCount "navigation with $count"
546
595
  = navigationPath:(head:identifier key:(OPEN keyArgs:args CLOSE {return keyArgs;})? '/' {
547
596
  if (key) {
@@ -551,6 +600,7 @@
551
600
  return head;
552
601
  })+ count: '$count'
553
602
  { return {func: 'count', as: '$count', args: [{ref: navigationPath}]} }
603
+
554
604
  ref "a reference"
555
605
  = head:identifier tail:( '/' n:identifier {return n})*
556
606
  {
@@ -559,34 +609,56 @@
559
609
  }
560
610
  return { ref:[ head, ...tail ] }
561
611
  }
612
+
562
613
  val
563
614
  = val:(bool / date) {return {val}}
564
615
  / val:guid {return {val}}
565
616
  / val:number {return typeof val === 'number' ? {val} : { val, literal:'number' }}
566
617
  / val:string {return {val}}
567
618
  / val:binary {return {val}}
568
- jsonObject = val:$("{" (jsonObject / [^}])* "}") {return {val}}
569
- jsonArray = val:$("[" o "]" / "[" o "{" (jsonArray / [^\]])* "]") {return {val}}
570
-
571
- list
619
+ / val:aliasedParam {return {val}}
620
+ / null
621
+
622
+ null "null" = "null" {return {val: null }}
623
+
624
+ jsonObject "a json object"
625
+ = val:$("{" (jsonObject / [^}])* "}") {return {val}}
626
+
627
+ jsonArray "a json array"
628
+ = val:$("[" o "]" / "[" o "{" (jsonArray / [^\]])* "]") {return {val}}
629
+
630
+ list "a list"
572
631
  = "[" any:$([^\]])* "]" // > needs improvment
573
632
  { return { list: any.replace(/"/g,'').split(',').map(ele => ({ val: ele })) } }
574
633
 
575
- function "a function call"
576
- = func:$[a-zA-Z]+ OPEN a:operand more:( COMMA o:operand {return o} )* CLOSE {
634
+ listRoundBrackets "a list"
635
+ = OPEN list:(val1:val val2:("," v:val { return v })* { return [val1, ...val2] }) CLOSE // > needs improvment
636
+ {
637
+ return { list }
638
+ }
639
+
640
+
641
+ functionName "a function name"
642
+ = $[a-zA-Z]+
643
+
644
+ function
645
+ = func:functionName OPEN fnArgs:functionArgs CLOSE {
577
646
  if (strict && !(func.toLowerCase() in strict.functions)) {
578
647
  throw Object.assign(new Error(`"${func}" is an unknown function in OData URL spec (strict mode)`), { statusCode: 400 })
579
648
  }
580
- return { func: func.toLowerCase(), args:[a,...more] }
649
+ return { func: func.toLowerCase(), args:[fnArgs.a,...fnArgs.more] }
581
650
  }
582
651
 
583
- boolish "a boolean function"
652
+ functionArgs
653
+ = a:operand more:( COMMA o:operand {return o} )* {return { a, more }}
654
+
655
+ boolish
584
656
  = func:("contains"i/"endswith"i/"startswith"i) OPEN a:operand COMMA b:operand CLOSE
585
657
  { return { func: func.toLowerCase(), args:[a,b] }}
586
658
 
587
659
  NOT = o "NOT"i _ {return 'not'}
588
660
  AND = _ "AND"i _ {return 'and'}
589
- AND_SPACE = _ {return 'and'}
661
+ AND_SPACE = _ {return 'and'}
590
662
  OR = _ "OR"i _ {return 'or'}
591
663
 
592
664
 
@@ -622,7 +694,7 @@
622
694
  }
623
695
  return {aggregate: [{ func, args }]}
624
696
  } /
625
- identity: identityTrafo{return identity}
697
+ identity: identityTrafo {return identity}
626
698
  // customFunction
627
699
  )
628
700
 
@@ -663,7 +735,11 @@
663
735
  groupByElem
664
736
  = c:(rollupSpec / ref) { return c }
665
737
  rollupSpec // TODO fix this + add CAP support
666
- = rollup:("rollup" OPEN o ('$all' / ref) (o COMMA ref)+ o CLOSE) {const err = new Error("Rollup in groupby is not supported yet.");err.statusCode=501;throw err;}
738
+ = rollup:("rollup" OPEN o ('$all' / ref) (o COMMA ref)+ o CLOSE) {
739
+ const err = new Error("Rollup in groupby is not supported yet.");
740
+ err.statusCode=501;
741
+ throw err;
742
+ }
667
743
 
668
744
  filterTrafo = OPEN o where:(where:filter{
669
745
  return where
@@ -707,20 +783,21 @@
707
783
  //
708
784
  // ---------- Literals -----------
709
785
 
710
- bool = b:("true" / "false") { return b === 'true'}
786
+ bool "a boolean"
787
+ = b:("true" / "false") { return b === 'true'}
711
788
 
712
- string "Edm.String"
713
- = "'" s:$("''"/[^'])* "'"
789
+ string "a single quoted string" // "Edm.String"
790
+ = "'" s:$("''" / [^'])* "'" // 'A user''s story'
714
791
  {return s.replace(/''/g,"'")}
715
792
 
716
- doubleQuotedString
793
+ doubleQuotedString "a doubled quoted string"
717
794
  = '"' s:$('\\"'/[^"])* '"'
718
795
  {return s.replace(/\\\\/g,"\\").replace(/\\"/g,'"')}
719
796
 
720
- word
797
+ word "a string"
721
798
  = $([^ \t\n()"&;]+)
722
799
 
723
- date
800
+ date "a date"
724
801
  = s:$( [0-9]+"-"[0-9][0-9]"-"[0-9][0-9] // date
725
802
  ( "T"[0-9][0-9]":"[0-9][0-9](":"[0-9][0-9]("."[0-9]+)?)? // time
726
803
  ( "Z" / (("+" / "-")[0-9][0-9]":"[0-9][0-9]) )? // timezone (Z or +-hh:mm)
@@ -730,19 +807,23 @@
730
807
  return s
731
808
  }
732
809
 
733
- number
734
- = s:$( [+-]? [0-9]+ ("."[0-9]+)? ("e"[0-9]+)? ) { return safeNumber(s) }
810
+ // to avoid 123-123-123 being matched as number and showing error for "-123-123"
811
+ endsWithMinus
812
+ = [0-9]+ "-"
813
+
814
+ number "a number"
815
+ = !endsWithMinus s:$( [+-]? [0-9]+ ("."[0-9]+)? ("e"[0-9]+)? ) { return safeNumber(s) }
735
816
 
736
- integer
817
+ integer "an integer"
737
818
  = s:$( [+-]? [0-9]+ ) { return parseInt(s) }
738
819
 
739
- identifier
820
+ identifier "an identifier"
740
821
  = !bool !guid s:$([_a-zA-Z][_a-zA-Z0-9"."]*) { return s }
741
822
 
742
- guid
823
+ guid "a guid"
743
824
  = $( hex16 hex16 "-"? hex16 "-"? hex16 "-"? hex16 "-"? hex16 hex16 hex16 )
744
825
 
745
- hex16
826
+ hex16 "a hex value"
746
827
  = $( [0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F] )
747
828
 
748
829
  segment // > everything except / and ?
@@ -751,7 +832,7 @@
751
832
  skiptokenChars
752
833
  = $( [a-zA-Z0-9-"."_~!$'()*+,;=:@"/""?"]+ )
753
834
 
754
- binary // > url-safe base64
835
+ binary "a binary" // > url-safe base64
755
836
  = "binary'" s:$([a-zA-Z0-9-_]+ ("=="/"=")?) "'" { return standardBase64(s) }
756
837
 
757
838
  //
@@ -766,8 +847,8 @@
766
847
  //
767
848
  // ---------- Whitespaces -----------
768
849
 
769
- o "optional whitespaces" = $[ \t\n]*
770
- _ "mandatory whitespaces" = $[ \t\n]+
850
+ o "an optional whitespace" = $[ \t\n]*
851
+ _ "a whitespace" = $[ \t\n]+
771
852
 
772
853
  //
773
- // ------------------------------------
854
+ // ------------------------------------
@@ -74,12 +74,18 @@ module.exports = {
74
74
  try {
75
75
  cqn = odata2cqn(url, options)
76
76
  } catch (err) {
77
- if (err.message === 'EXPAND_COUNT_UNSUPPORTED' || err.message === 'ORDERBY_LAMBDA_UNSUPPORTED') {
78
- throw getError(err.statusCode || 400, err.message)
77
+ if (err.statusCode === 501) {
78
+ throw getError(err.statusCode, err.message)
79
+ }
80
+
81
+ let offset = err.location && err.location.start.offset
82
+ if (options.baseUrl) {
83
+ // we need to add the number of chars from base url to the offset
84
+ offset += options.baseUrl.length
79
85
  }
80
86
 
81
87
  // TODO adjust this to behave like above
82
- err.message = 'Parsing URL failed with error: ' + err.message
88
+ err.message = `Parsing URL failed at position ${offset}: ${err.message}`
83
89
  err.statusCode = err.statusCode || 400
84
90
  throw err
85
91
  }