Skip to content

Commit 5655ca8

Browse files
added jq like queries to sjs (#19)
* added ebaReader to sjs with query method * added test to npm
1 parent 8adfbe0 commit 5655ca8

File tree

8 files changed

+86
-5
lines changed

8 files changed

+86
-5
lines changed
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,28 @@
11
package izumi.sick.eba.cursor
22

3-
import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
3+
import izumi.sick.model.Ref
44

5+
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
56
import scala.scalajs.js
67
import scala.scalajs.js.JSConverters.*
78

89
@JSExportTopLevel("TopCursor")
9-
@JSExportAll
1010
class TopCursorJs(cursor: TopCursor) extends SickCursorJs(cursor.asInstanceOf[SickCursor]) {
11+
12+
@JSExport
1113
def query(request: String): ObjectCursorJs = {
1214
new ObjectCursorJs(cursor.query(request))
1315
}
1416

17+
@JSExport
1518
def getValues: js.Map[String, ObjectCursorJs] = {
1619
cursor.getValues.view.mapValues(new ObjectCursorJs(_)).toMap.toJSMap
1720
}
1821

22+
@JSExport
1923
def readKey(index: Int): ObjectCursorJs = {
2024
new ObjectCursorJs(cursor.readKey(index))
2125
}
26+
27+
protected[eba] def ref: Ref = cursor.ref
2228
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package izumi.sick.eba.reader
2+
3+
import izumi.sick.eba.cursor.{ObjectCursorJs, TopCursorJs}
4+
import izumi.sick.model.RefKind
5+
6+
import scala.scalajs.js
7+
import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
8+
9+
@JSExportTopLevel("EBAReader")
10+
@JSExportAll
11+
class EBAReaderJs(reader: IncrementalEBAReader, rootId: String) {
12+
def query(request: String): js.Any = {
13+
val cursor = new TopCursorJs(reader.getCursor(rootId)).query(request)
14+
resolveCursorRef(cursor)
15+
}
16+
17+
private def resolveCursorRef(cursor: ObjectCursorJs): js.Any = {
18+
cursor.ref.kind match {
19+
case RefKind.TNul => cursor.asNul
20+
case RefKind.TBit => cursor.asBool
21+
case RefKind.TByte => cursor.asByte
22+
case RefKind.TShort => cursor.asShort
23+
case RefKind.TInt => cursor.asInt
24+
case RefKind.TLng => cursor.asDouble
25+
case RefKind.TBigInt => cursor.asBigInt
26+
case RefKind.TFlt => cursor.asFloat
27+
case RefKind.TDbl => cursor.asDouble
28+
case RefKind.TStr => cursor.asString
29+
case _ => js.undefined
30+
}
31+
}
32+
33+
}

json-sick-scala/json-sick/.js/src/main/scala/izumi/sick/jsapi/SickJsAPI.scala

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import io.circe.Json
44
import izumi.sick.SICK
55
import izumi.sick.eba.SICKSettings
66
import izumi.sick.eba.cursor.TopCursorJs
7-
import izumi.sick.eba.reader.{EagerEBAReader, IncrementalEBAReader}
7+
import izumi.sick.eba.reader.{EBAReaderJs, EagerEBAReader, IncrementalEBAReader}
88
import izumi.sick.eba.writer.EBAWriter
99
import izumi.sick.model.{SICKWriterParameters, TableWriteStrategy}
1010
import izumi.sick.sickcirce.CirceTraverser.*
@@ -98,4 +98,17 @@ object SickJsAPI {
9898
val ebaReader = IncrementalEBAReader.openBytes(uint8ArrayToBytes(uint8Array), eagerOffsets = false)
9999
new TopCursorJs(ebaReader.getCursor(rootId))
100100
}
101+
102+
/**
103+
* Alternative method for navigating the sick structure, which has query method with jq like requests
104+
*
105+
* `{ data: { a: 2, b: { c: [1, 2, 3] } } }`
106+
* `const reader = ebaReaderFromUint8Array(uint8Array, "data")`
107+
* `reader.query("b.c.[1]")`
108+
*/
109+
@JSExportTopLevel("ebaReaderFromUint8Array")
110+
def ebaReaderFromUint8Array(uint8Array: Uint8Array, rootId: String): EBAReaderJs = {
111+
val ebaReader = IncrementalEBAReader.openBytes(uint8ArrayToBytes(uint8Array), eagerOffsets = false)
112+
new EBAReaderJs(ebaReader, rootId)
113+
}
101114
}

json-sick-scala/json-sick/.js/src/test/scala/io/izumi/sick/JsApiTest.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ class JsApiTest extends AnyWordSpec {
3939
assert(cursor.downField("b").asInt.toOption.contains(2))
4040
assert(cursor.downField("c").asInt.toOption.contains(3))
4141
}
42+
43+
locally {
44+
val uint8Array = SickJsAPI.encodeJSONStringsToSickUint8Array(js.Dictionary("data" -> """{ "a": 1 , "b": { "c": 2, "d": [3, 4, 5] } }"""))
45+
val reader = SickJsAPI.ebaReaderFromUint8Array(uint8Array, "data")
46+
assert(reader.query("a").asInstanceOf[Int] == 1)
47+
assert(reader.query("b.c").asInstanceOf[Int] == 2)
48+
assert(reader.query("b.d.[1]").asInstanceOf[Int] == 4)
49+
}
4250
}
4351

4452
}

json-sick-scala/json-sick/src/main/scala/izumi/sick/eba/reader/IncrementalEBAReader.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ class IncrementalEBAReader(
173173
case currentQuery0 :: next0 =>
174174
val (currentQuery, next) = handleBracketsWithoutDot(currentQuery0, next0)
175175
if (currentQuery.startsWith("[") && currentQuery.endsWith("]")) {
176-
val index = currentQuery.substring(1, currentQuery.length - 2)
176+
val index = currentQuery.substring(1, currentQuery.length - 1)
177177
val iindex = index.toInt
178178

179179
val resolvedArr = readArrayElementRef(ref, iindex)

json-sick-scala/json-sick/src/test/scala/io/izumi/sick/SickCursorTest.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,5 +183,7 @@ class SickCursorTest extends AnyWordSpec {
183183
assert(cursor.query("data.person").getValues.get("name").exists(_.asString.contains("Alice")))
184184

185185
assert(cursor.query("data.person").readKey(1).asInt.contains(30))
186+
187+
assert(cursor.query("data.numbers.[1]").asString.contains("two"))
186188
}
187189
}

json-sick-scala/npm-template/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ Accepts dictionary where keys are root names and values are Uint8Arrays containi
7171

7272
Accepts an instance of `Uint8Array` and the rootId, returns a cursor to navigate through the structure.
7373

74+
### `ebaReaderFromUint8Array(uint8Array: Uint8Array, rootId: string): EBAReader`
75+
76+
Accepts an instance of `Uint8Array` and the rootId, returns a reader, which has query method, with jq like requests.
77+
7478
## License
7579

7680
BSD-2-Clause

json-sick-scala/npm-template/test.js

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
encodeObjsToSickUint8Array,
77
encodeJSONStringsToSickUint8Array,
88
encodeJSONBytesToSickUint8Array,
9-
sickCursorFromUint8Array
9+
sickCursorFromUint8Array,
10+
ebaReaderFromUint8Array
1011
} from "./json-sick-2.13-fullOpt.js";
1112

1213
test("Encode/Decode obj test", t => {
@@ -63,4 +64,18 @@ test("Sick Cursors test", t => {
6364

6465
t.is(cursor.downField("arr").downArray.right.value.asString, "b");
6566
t.is(cursor.downField("arr").downArray.downIndex(2).asString, "c");
67+
})
68+
69+
test("EBAReader test", t => {
70+
const encoded = encodeObjToSickUint8Array("data",
71+
{
72+
object: {
73+
life: 42,
74+
array: ["a", "b", "c", "d", "e"]
75+
}
76+
});
77+
const reader = ebaReaderFromUint8Array(encoded, "data");
78+
79+
t.is(reader.query("object.life"), 42);
80+
t.is(reader.query("object.array.[2]"), "c");
6681
})

0 commit comments

Comments
 (0)