feelin 4.3.1 → 7.0.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 (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -1
  3. data/CHANGELOG.md +30 -0
  4. data/README.md +91 -0
  5. data/feelin.gemspec +5 -1
  6. data/lib/feelin/js/dist/feelin.js +13703 -0
  7. data/lib/feelin/js/entry.js +93 -0
  8. data/lib/feelin/js/package-lock.json +526 -31
  9. data/lib/feelin/js/package.json +8 -1
  10. data/lib/feelin/version.rb +1 -1
  11. data/lib/feelin.rb +87 -43
  12. data/spec/feelin/feelin_spec.rb +140 -0
  13. metadata +11 -108
  14. data/lib/feelin/js/node_modules/.package-lock.json +0 -67
  15. data/lib/feelin/js/node_modules/@lezer/common/LICENSE +0 -21
  16. data/lib/feelin/js/node_modules/@lezer/common/README.md +0 -14
  17. data/lib/feelin/js/node_modules/@lezer/common/dist/index.cjs +0 -2181
  18. data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.cts +0 -1137
  19. data/lib/feelin/js/node_modules/@lezer/common/dist/index.d.ts +0 -1137
  20. data/lib/feelin/js/node_modules/@lezer/common/dist/index.js +0 -2168
  21. data/lib/feelin/js/node_modules/@lezer/common/package.json +0 -32
  22. data/lib/feelin/js/node_modules/@lezer/highlight/LICENSE +0 -21
  23. data/lib/feelin/js/node_modules/@lezer/highlight/README.md +0 -14
  24. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.cjs +0 -915
  25. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.cts +0 -621
  26. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.d.ts +0 -623
  27. data/lib/feelin/js/node_modules/@lezer/highlight/dist/index.js +0 -904
  28. data/lib/feelin/js/node_modules/@lezer/highlight/package.json +0 -31
  29. data/lib/feelin/js/node_modules/@lezer/lr/LICENSE +0 -21
  30. data/lib/feelin/js/node_modules/@lezer/lr/README.md +0 -25
  31. data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.d.ts +0 -45
  32. data/lib/feelin/js/node_modules/@lezer/lr/dist/constants.js +0 -5
  33. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.cjs +0 -1890
  34. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.cts +0 -303
  35. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.d.ts +0 -303
  36. data/lib/feelin/js/node_modules/@lezer/lr/dist/index.js +0 -1883
  37. data/lib/feelin/js/node_modules/@lezer/lr/package.json +0 -32
  38. data/lib/feelin/js/node_modules/feelin/LICENSE +0 -21
  39. data/lib/feelin/js/node_modules/feelin/README.md +0 -65
  40. data/lib/feelin/js/node_modules/feelin/dist/builtins.d.ts +0 -355
  41. data/lib/feelin/js/node_modules/feelin/dist/index.cjs +0 -2072
  42. data/lib/feelin/js/node_modules/feelin/dist/index.cjs.map +0 -1
  43. data/lib/feelin/js/node_modules/feelin/dist/index.d.ts +0 -3
  44. data/lib/feelin/js/node_modules/feelin/dist/index.esm.js +0 -2063
  45. data/lib/feelin/js/node_modules/feelin/dist/index.esm.js.map +0 -1
  46. data/lib/feelin/js/node_modules/feelin/dist/interpreter.d.ts +0 -26
  47. data/lib/feelin/js/node_modules/feelin/dist/parser.d.ts +0 -4
  48. data/lib/feelin/js/node_modules/feelin/dist/temporal.d.ts +0 -6
  49. data/lib/feelin/js/node_modules/feelin/dist/types.d.ts +0 -35
  50. data/lib/feelin/js/node_modules/feelin/dist/utils.d.ts +0 -12
  51. data/lib/feelin/js/node_modules/feelin/package.json +0 -63
  52. data/lib/feelin/js/node_modules/lezer-feel/LICENSE +0 -21
  53. data/lib/feelin/js/node_modules/lezer-feel/README.md +0 -94
  54. data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs +0 -1328
  55. data/lib/feelin/js/node_modules/lezer-feel/dist/index.cjs.map +0 -1
  56. data/lib/feelin/js/node_modules/lezer-feel/dist/index.d.ts +0 -32
  57. data/lib/feelin/js/node_modules/lezer-feel/dist/index.js +0 -1323
  58. data/lib/feelin/js/node_modules/lezer-feel/dist/index.js.map +0 -1
  59. data/lib/feelin/js/node_modules/lezer-feel/package.json +0 -61
  60. data/lib/feelin/js/node_modules/luxon/LICENSE.md +0 -7
  61. data/lib/feelin/js/node_modules/luxon/README.md +0 -55
  62. data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js +0 -8623
  63. data/lib/feelin/js/node_modules/luxon/build/amd/luxon.js.map +0 -1
  64. data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js +0 -8621
  65. data/lib/feelin/js/node_modules/luxon/build/cjs-browser/luxon.js.map +0 -1
  66. data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js +0 -8011
  67. data/lib/feelin/js/node_modules/luxon/build/es6/luxon.js.map +0 -1
  68. data/lib/feelin/js/node_modules/luxon/build/global/luxon.js +0 -8626
  69. data/lib/feelin/js/node_modules/luxon/build/global/luxon.js.map +0 -1
  70. data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js +0 -1
  71. data/lib/feelin/js/node_modules/luxon/build/global/luxon.min.js.map +0 -1
  72. data/lib/feelin/js/node_modules/luxon/build/node/luxon.js +0 -7679
  73. data/lib/feelin/js/node_modules/luxon/build/node/luxon.js.map +0 -1
  74. data/lib/feelin/js/node_modules/luxon/package.json +0 -87
  75. data/lib/feelin/js/node_modules/luxon/src/datetime.js +0 -2566
  76. data/lib/feelin/js/node_modules/luxon/src/duration.js +0 -990
  77. data/lib/feelin/js/node_modules/luxon/src/errors.js +0 -61
  78. data/lib/feelin/js/node_modules/luxon/src/impl/conversions.js +0 -206
  79. data/lib/feelin/js/node_modules/luxon/src/impl/diff.js +0 -95
  80. data/lib/feelin/js/node_modules/luxon/src/impl/digits.js +0 -90
  81. data/lib/feelin/js/node_modules/luxon/src/impl/english.js +0 -233
  82. data/lib/feelin/js/node_modules/luxon/src/impl/formats.js +0 -176
  83. data/lib/feelin/js/node_modules/luxon/src/impl/formatter.js +0 -409
  84. data/lib/feelin/js/node_modules/luxon/src/impl/invalid.js +0 -14
  85. data/lib/feelin/js/node_modules/luxon/src/impl/locale.js +0 -554
  86. data/lib/feelin/js/node_modules/luxon/src/impl/regexParser.js +0 -335
  87. data/lib/feelin/js/node_modules/luxon/src/impl/tokenParser.js +0 -505
  88. data/lib/feelin/js/node_modules/luxon/src/impl/util.js +0 -316
  89. data/lib/feelin/js/node_modules/luxon/src/impl/zoneUtil.js +0 -34
  90. data/lib/feelin/js/node_modules/luxon/src/info.js +0 -205
  91. data/lib/feelin/js/node_modules/luxon/src/interval.js +0 -665
  92. data/lib/feelin/js/node_modules/luxon/src/luxon.js +0 -26
  93. data/lib/feelin/js/node_modules/luxon/src/package.json +0 -4
  94. data/lib/feelin/js/node_modules/luxon/src/settings.js +0 -180
  95. data/lib/feelin/js/node_modules/luxon/src/zone.js +0 -97
  96. data/lib/feelin/js/node_modules/luxon/src/zones/IANAZone.js +0 -231
  97. data/lib/feelin/js/node_modules/luxon/src/zones/fixedOffsetZone.js +0 -150
  98. data/lib/feelin/js/node_modules/luxon/src/zones/invalidZone.js +0 -53
  99. data/lib/feelin/js/node_modules/luxon/src/zones/systemZone.js +0 -61
  100. data/lib/feelin/js/node_modules/min-dash/LICENSE +0 -21
  101. data/lib/feelin/js/node_modules/min-dash/README.md +0 -38
  102. data/lib/feelin/js/node_modules/min-dash/dist/array.d.ts +0 -12
  103. data/lib/feelin/js/node_modules/min-dash/dist/collection.d.ts +0 -174
  104. data/lib/feelin/js/node_modules/min-dash/dist/fn.d.ts +0 -37
  105. data/lib/feelin/js/node_modules/min-dash/dist/index.cjs +0 -910
  106. data/lib/feelin/js/node_modules/min-dash/dist/index.d.ts +0 -5
  107. data/lib/feelin/js/node_modules/min-dash/dist/index.esm.js +0 -872
  108. data/lib/feelin/js/node_modules/min-dash/dist/lang.d.ts +0 -29
  109. data/lib/feelin/js/node_modules/min-dash/dist/min-dash.js +0 -916
  110. data/lib/feelin/js/node_modules/min-dash/dist/min-dash.min.js +0 -1
  111. data/lib/feelin/js/node_modules/min-dash/dist/object.d.ts +0 -112
  112. data/lib/feelin/js/node_modules/min-dash/package.json +0 -72
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7a4fbc790ded4b8ab96b849b340e47ca9caf6e823a81ed6d089ffefe8f2681f1
4
- data.tar.gz: fdd926deebf949cdb3ff1c30bf9e6973127505172ec97a823326de72392c6783
3
+ metadata.gz: 3a2aab7f50ce55a02f7c45876a113972cf952c23ab505a2a95f527c213015591
4
+ data.tar.gz: 68ffbc5239c2f1387ea5982e6af9b7c9fc619a93ab43e42c2750a981cfb6813c
5
5
  SHA512:
6
- metadata.gz: 6f52af2eff46b10aef4a0d0c241643bcd2ab76df7adefe78ebff16cd68b626573001b1da1e3458308a6d864eba4f6f55bce7823059483811a52c2654bbaf4150
7
- data.tar.gz: af1942c3a6f320a189068a2d788a230b465c6c0ffffc7b5e1b83e38b928a7d2f9102980e20088de7c98c1ce4bfaac665df839a10f2ca4f7e0b80a9d9f433cd5b
6
+ metadata.gz: da2fea8b67b029c34710ee51f1c0e3f491eb974e2270a83eaed1ac6d88935148882e56bbde7a7709e4543ffada442181f3b02ed14d407b9c0671087d59e46f95
7
+ data.tar.gz: 3cf684bb66042782c7415b16d2cca27608ed45f2dc9eb2a83b6e25a4cfab1806cbd1c4c04148417651060164137491d654e67e21361ba79e4ca5ba47ff7d608c
data/.gitignore CHANGED
@@ -3,4 +3,8 @@ log/*.log
3
3
  .byebug_history
4
4
  *.gem
5
5
  Gemfile.lock
6
- .idea
6
+ .idea
7
+
8
+ # JS dependencies — only needed to (re)build lib/feelin/js/dist/feelin.js,
9
+ # which is committed. Run `npm install` in lib/feelin/js to restore.
10
+ node_modules/
data/CHANGELOG.md CHANGED
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [7.0.2] - 2026-10-05
9
+
10
+ ### Added
11
+
12
+ * `FEELIN.parse` and `FEELIN.parse_unary_tests` answer the syntax tree of an expression as nested hashes (`type`, `from`, `to`, `text`, `children`), without evaluating it. A syntax error raises with the message `evaluate` gives.
13
+ * `FEELIN::Context` — a V8 context of one's own, with the same methods as the module, optional `timeout` and `max_memory` limits, and custom functions of its own. All contexts start from one snapshot of the bundle.
14
+
15
+ ### Changed
16
+
17
+ * Updated the bundled `feelin` JavaScript library to 7.0.2 (prototype access from FEEL expressions is prevented).
18
+ * **Breaking:** a result is JSON-compatible. A date, a time and a duration are now the ISO 8601 strings FEEL's `string()` gives them (`"2020-01-02"`, `"10:00:00+03:00"`, `"2020-01-02T03:04:05Z"`, `"P1DT2H"`) instead of a hash of the internal fields of the JavaScript object. A function is a hash of its `parameterNames`.
19
+ * The context is passed to V8 as an argument rather than written into the evaluated script, so V8 no longer compiles and keeps a script per distinct context. Measured speed is the same as before.
20
+
21
+ ### Not updated
22
+
23
+ * `feelin` 8.2.0 was tried and held back: evaluating an expression that names a variable takes about twice as long there (8.2.0 looks every variable name up among the built-ins on each `evaluate`), and it produces enough garbage to run a context with `max_memory: 64_000_000` out of memory after ~10 000 evaluations.
24
+
25
+ ## [7.0.1] - 2026-06-22
26
+
27
+ ### Changed
28
+
29
+ * Updated the bundled `feelin` JavaScript library to 7.0.1.
30
+ * Rebuilt the JavaScript bundle with [esbuild](https://esbuild.github.io/). `feelin` is now distributed as an ES module, so it is pre-bundled into a single IIFE file (`lib/feelin/js/dist/feelin.js`) instead of being assembled from CommonJS at load time.
31
+ * `evaluate` / `unary_test` unwrap feelin 7's `EvaluationResult { value, warnings }` envelope, so callers keep receiving the bare value.
32
+
33
+ ### Fixed
34
+
35
+ * `serialize_context` built invalid JavaScript (a leading comma, `{,…}`) for an empty context once a custom function was registered.
36
+ * `serialize_context` built invalid JavaScript for custom function names containing spaces (e.g. `string join`); function names are now emitted as quoted keys forwarding to the attached global.
37
+
8
38
  ## [4.3.1] - 2025-03-26
9
39
 
10
40
  * Initial release
data/README.md CHANGED
@@ -21,6 +21,16 @@ FEELIN.evaluate('for a in [1, 2, 3] return a * 2') # [ 2, 4, 6 ]
21
21
  FEELIN.evaluate("Mike's daughter.name", { 'Mike\'s daughter.name' => 'Lisa' }) # Lisa
22
22
  ```
23
23
 
24
+ A result is JSON-compatible. A date, a time and a duration come back as ISO 8601 strings, in the form
25
+ FEEL's own `string()` gives them:
26
+
27
+ ```ruby
28
+ FEELIN.evaluate('date("2020-01-02") + duration("P1D")') # "2020-01-03"
29
+ FEELIN.evaluate('date and time("2020-01-02T03:04:05Z")') # "2020-01-02T03:04:05Z"
30
+ FEELIN.evaluate('time("10:00:00+03:00")') # "10:00:00+03:00"
31
+ FEELIN.evaluate('duration("P1DT2H")') # "P1DT2H"
32
+ ```
33
+
24
34
  ### Unary tests
25
35
 
26
36
  ```ruby
@@ -31,6 +41,38 @@ FEELIN.unary_test('1', 1) # true
31
41
  FEELIN.unary_test('[1..end]', 1, { 'end' => 10 }) # true
32
42
  ```
33
43
 
44
+ ### Syntax tree
45
+
46
+ `parse` and `parse_unary_tests` answer the syntax tree of an expression without evaluating it — for
47
+ translating FEEL into something else (SQL, for one) or inspecting what an expression refers to.
48
+
49
+ ```ruby
50
+ FEELIN.parse('price > 10')
51
+ # { "type" => "Expression", "from" => 0, "to" => 10, "text" => "price > 10", "children" => [
52
+ # { "type" => "Comparison", "from" => 0, "to" => 10, "text" => "price > 10", "children" => [
53
+ # { "type" => "VariableName", "from" => 0, "to" => 5, "text" => "price", "children" => [
54
+ # { "type" => "Identifier", "from" => 0, "to" => 5, "text" => "price", "children" => [] } ] },
55
+ # { "type" => "CompareOp", "from" => 6, "to" => 7, "text" => ">", "children" => [] },
56
+ # { "type" => "NumericLiteral", "from" => 8, "to" => 10, "text" => "10", "children" => [] } ] } ] }
57
+
58
+ FEELIN.parse_unary_tests('[1..end], > 5')
59
+ ```
60
+
61
+ The tree is the one feelin's parser ([lezer-feel](https://github.com/nikku/lezer-feel)) builds, node for
62
+ node: `type` is the grammar's name of the node, and keywords and punctuation (`if`, `(`, `,`) are nodes as
63
+ well. `from` / `to` are the span in the expression, counted in UTF-16 code units as JavaScript counts —
64
+ for text outside the Basic Multilingual Plane that differs from Ruby's character index, so take `text`
65
+ rather than slicing the expression.
66
+
67
+ The optional second argument is a context, of which only the names matter: it is what lets a name with
68
+ spaces in it be read as one name.
69
+
70
+ ```ruby
71
+ FEELIN.parse("Mike's daughter.name + 1", { "Mike's daughter.name" => nil })
72
+ ```
73
+
74
+ An expression that does not parse raises `MiniRacer::RuntimeError`, with the same message `evaluate` gives.
75
+
34
76
  ### Custom functions
35
77
 
36
78
  ```ruby
@@ -38,6 +80,55 @@ FEELIN.add_function('rates', proc { [10, 20] })
38
80
  FEELIN.evaluate('every rate in rates() satisfies rate < 10') # false
39
81
  ```
40
82
 
83
+ ### A context of one's own
84
+
85
+ The methods above work on one shared V8 context, which has no limits. `FEELIN::Context` is a separate
86
+ one with the same methods — for an expression that is not trusted to end or to stay small, or for custom
87
+ functions the rest of the process should not see.
88
+
89
+ ```ruby
90
+ context = FEELIN::Context.new(timeout: 1_000, max_memory: 64_000_000) # ms, bytes; both optional
91
+
92
+ context.add_function('rate', proc { 0.2 })
93
+ context.evaluate('price * rate()', { 'price' => 100 }) # 20
94
+ context.parse('price * rate()')
95
+
96
+ context.dispose
97
+ ```
98
+
99
+ Past its timeout an evaluation raises `MiniRacer::ScriptTerminatedError`, past its memory
100
+ `MiniRacer::V8OutOfMemoryError`. Contexts are created from one snapshot of the bundle, so a new one does
101
+ not load feelin again.
102
+
103
+ ## Development
104
+
105
+ The gem embeds the [feelin](https://github.com/nikku/feelin) JavaScript library, pre-bundled into a single file that is loaded into the V8 context at runtime. The JavaScript sources live in `lib/feelin/js`.
106
+
107
+ ### Updating the JavaScript dependencies
108
+
109
+ ```bash
110
+ cd lib/feelin/js
111
+ npm install # install the pinned versions
112
+ npm install feelin@<version> # bump feelin to a specific version
113
+ ```
114
+
115
+ ### Building the bundle
116
+
117
+ `feelin` is distributed as an ES module, so it is bundled ahead of time with [esbuild](https://esbuild.github.io/) into `lib/feelin/js/dist/feelin.js` — an IIFE that exposes the feelin API on the global `feel`. The entry point is `lib/feelin/js/entry.js`.
118
+
119
+ ```bash
120
+ cd lib/feelin/js
121
+ npm run build
122
+ ```
123
+
124
+ Commit the regenerated `dist/feelin.js` together with the updated `package.json` / `package-lock.json`.
125
+
126
+ ### Running the tests
127
+
128
+ ```bash
129
+ bundle exec rspec
130
+ ```
131
+
41
132
  ## Versioning policy
42
133
 
43
134
  Because this library is a wrapper - it is released with the same major/minor version numbers as the underlying feelin library
data/feelin.gemspec CHANGED
@@ -12,10 +12,14 @@ Gem::Specification.new do |spec|
12
12
  spec.description = "This gem uses embed V8 JavaScript engine and feelin JavaScript library to parse and evaluate DMN FEEL expressions"
13
13
  spec.license = "MIT"
14
14
 
15
+ spec.metadata['homepage_uri'] = spec.homepage
16
+ spec.metadata['source_code_uri'] = spec.homepage
17
+ spec.metadata['changelog_uri'] = 'https://github.com/ekzo-dev/ruby-feelin/CHANGELOG.md'
18
+
15
19
  spec.files = `git ls-files -z`.split("\x0")
16
20
  spec.require_paths = ["lib"]
17
21
 
18
- spec.add_dependency "mini_racer", "~> 0.18"
22
+ spec.add_dependency "mini_racer", "~> 0.21"
19
23
 
20
24
  spec.add_development_dependency "rspec", "3.12.0"
21
25
  spec.add_development_dependency "byebug", "11.1.3"