Initial commit, can read and write a JSON tree in log style and append to a log
authorNick Downing <nick@ndcode.org>
Tue, 4 Jan 2022 04:15:24 +0000 (15:15 +1100)
committerNick Downing <nick@ndcode.org>
Tue, 4 Jan 2022 04:15:48 +0000 (15:15 +1100)
.gitignore [new file with mode: 0644]
a.mjs [new file with mode: 0755]
b.mjs [new file with mode: 0755]
logjson.mjs [new file with mode: 0644]
random.json [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..e5566e3
--- /dev/null
@@ -0,0 +1 @@
+/a.logjson
diff --git a/a.mjs b/a.mjs
new file mode 100755 (executable)
index 0000000..8cc3797
--- /dev/null
+++ b/a.mjs
@@ -0,0 +1,9 @@
+#!/usr/bin/env node
+
+import logjson from './logjson.mjs'
+import fsPromises from 'fs/promises'
+
+let {log, eof, value} = await logjson.open_log(
+  'a.logjson',
+  JSON.parse(await fsPromises.readFile('random.json', 'utf-8'))
+)
diff --git a/b.mjs b/b.mjs
new file mode 100755 (executable)
index 0000000..ef146d2
--- /dev/null
+++ b/b.mjs
@@ -0,0 +1,7 @@
+#!/usr/bin/env node
+
+import logjson from './logjson.mjs'
+import fsPromises from 'fs/promises'
+
+let {log, eof, value} = await logjson.open_log('a.logjson', {})
+console.log('value', value)
diff --git a/logjson.mjs b/logjson.mjs
new file mode 100644 (file)
index 0000000..a2c3934
--- /dev/null
@@ -0,0 +1,133 @@
+import assert from 'assert'
+import fsPromises from 'fs/promises'
+
+let open_angle = Buffer.from('\n<', 'utf-8')
+let close_angle = Buffer.from('>\n', 'utf-8')
+let find_root = async (log, eof) => {
+  let ptr = eof & ~0xfff
+  let count = eof & 0xfff
+  let buffer = Buffer.alloc(0x1001)
+  assert((await log.read(buffer, 0, count, ptr)).bytesRead === count)
+  while (true) {
+    let i = count
+    if (i && (i = buffer.lastIndexOf(close_angle, i - 2)) != -1) {
+      let end = i + ptr
+      while (true) {
+        if (i && (i = buffer.lastIndexOf(open_angle, i - 2)) != -1) {
+          let start = i + ptr + 2
+          return {ptr: start, len: end - start}
+        }
+
+        if (ptr == 0)
+          break
+        ptr -= 0x1000
+        buffer[0x1000] = buffer[0]
+        assert((await log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000)
+        count = 0x1001
+      }
+
+      // special case for < at start of file
+      if (count && buffer[0] === 0x3c) {
+        let start = 1
+        return {ptr: start, len: end - start}
+      }
+
+      throw new Error('can\'t find logjson start marker') 
+    }
+
+    if (ptr == 0)
+      break
+    ptr -= 0x1000
+    buffer[0x1000] = buffer[0]
+    assert((await log.read(buffer, 0, 0x1000, ptr)).bytesRead === 0x1000)
+    count = 0x1001
+  } while (ptr >= 0)
+  throw new Error('can\'t find logjson end marker') 
+}
+
+let open_log = async (path, default_value) => {
+  let log
+  try {
+    log = await fsPromises.open(path, 'r+')
+  }
+  catch (error) {
+    if (error.code !== 'ENOENT')
+      throw error
+    log = await fsPromises.open(path, 'w+')
+    let {eof} = await write_log(log, 0, default_value, true)
+    return {log, eof, value: default_value}
+  }
+
+  let eof = (await log.stat()).size
+  let {ptr, len} = await find_root(log, eof)
+  let value = await read_log(log, ptr, len)
+
+  eof = ptr + len + 2
+  await log.truncate(eof)
+
+  return {log, eof, value}
+}
+
+let read_log = async (log, ptr, len) => {
+  let buffer = Buffer.alloc(len)
+  assert((await log.read(buffer, 0, len, ptr)).bytesRead === len)
+  let value = JSON.parse(buffer.toString('utf-8'))
+  if (typeof value === 'object' && value !== null)
+    if (value instanceof Array) {
+      for (let i = 0; i < value.length; ++i) {
+        let item = value[i]
+        if (item instanceof Array)
+          value[i] = await read_log(log, item[0], item[1])
+      }
+    }
+    else
+      for (let i in value) {
+        let item = value[i]
+        if (item instanceof Array)
+          value[i] = await read_log(log, item[0], item[1])
+      }
+  return value
+}
+
+let write_log = async (log, eof, value, is_root) => {
+  if (typeof value === 'object' && value !== null)
+    if (value instanceof Array) {
+      let value1 = []
+      for (let i = 0; i < value.length; ++i) {
+        let item = value[i]
+        if (typeof item === 'object' && item !== null) {
+          let {ptr, len, eof: eof1} = await write_log(log, eof, item, false)
+          item = [ptr, len]
+          eof = eof1
+        }
+        value1.push(item)
+      }
+      value = value1
+    }
+    else {
+      let value1 = {}
+      for (let i in value) {
+        let item = value[i]
+        if (typeof item === 'object' && item !== null) {
+          let {ptr, len, eof: eof1} = await write_log(log, eof, item, false)
+          item = [ptr, len]
+          eof = eof1
+        }
+        value1[i] = item
+      }
+      value = value1
+    }
+  let data = JSON.stringify(value, null, 2)
+  if (is_root) {
+    let buffer = Buffer.from(`<${data}>\n`)
+    let len = buffer.length
+    assert((await log.write(buffer, 0, len, eof)).bytesWritten === len)
+    return {ptr: eof + 1, len: len - 2, eof: eof + len}
+  }
+  let buffer = Buffer.from(`${data}\n`)
+  let len = buffer.length
+  assert((await log.write(buffer, 0, len, eof)).bytesWritten === len)
+  return {ptr: eof, len: len - 1, eof: eof + len}
+}
+
+export default {open_log, read_log, write_log}
diff --git a/random.json b/random.json
new file mode 100644 (file)
index 0000000..448a98a
--- /dev/null
@@ -0,0 +1,572 @@
+[
+  {
+    "_id": "5a5ce2cdbfca34a203af5d00",
+    "index": 0,
+    "guid": "1a11807a-a8fc-4ab9-8ae3-8ff867e66bb6",
+    "isActive": true,
+    "balance": "$2,067.65",
+    "picture": "http://placehold.it/32x32",
+    "age": 25,
+    "eyeColor": "blue",
+    "name": {
+      "first": "Petersen",
+      "last": "Mcgowan"
+    },
+    "company": "QUILTIGEN",
+    "email": "petersen.mcgowan@quiltigen.io",
+    "phone": "+1 (926) 464-3912",
+    "address": "343 Berriman Street, Clayville, Arizona, 8444",
+    "about": "Do exercitation amet labore est sit incididunt nisi do culpa deserunt tempor. Excepteur commodo deserunt pariatur voluptate duis nisi ipsum ullamco reprehenderit. Reprehenderit velit ex deserunt magna sunt nulla nulla. Commodo sit do aliquip non eu amet id minim eu consequat sint. Excepteur ad cupidatat Lorem proident laborum. Sit et duis est ullamco anim aute tempor.",
+    "registered": "Wednesday, April 2, 2014 11:07 PM",
+    "latitude": "84.731218",
+    "longitude": "163.582712",
+    "tags": [
+      "sint",
+      "ex",
+      "ipsum",
+      "pariatur",
+      "qui"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Mckay Lara"
+      },
+      {
+        "id": 1,
+        "name": "Larsen Hernandez"
+      },
+      {
+        "id": 2,
+        "name": "Owens Moses"
+      }
+    ],
+    "greeting": "Hello, Petersen! You have 9 unread messages.",
+    "favoriteFruit": "banana"
+  },
+  {
+    "_id": "5a5ce2cde07974dd92c2e32a",
+    "index": 1,
+    "guid": "1a946572-54de-436b-8af6-41e4c9ad1ce8",
+    "isActive": false,
+    "balance": "$3,328.27",
+    "picture": "http://placehold.it/32x32",
+    "age": 26,
+    "eyeColor": "brown",
+    "name": {
+      "first": "Rhea",
+      "last": "Hess"
+    },
+    "company": "AMTAP",
+    "email": "rhea.hess@amtap.org",
+    "phone": "+1 (907) 600-3328",
+    "address": "264 Ditmas Avenue, Keller, Federated States Of Micronesia, 1575",
+    "about": "Lorem eu cupidatat excepteur sit mollit incididunt. Laboris non do minim amet incididunt deserunt exercitation nostrud nisi occaecat pariatur esse sit. Ut anim ad minim deserunt pariatur aliquip. Minim qui commodo ut dolore ad tempor. Duis ex eiusmod anim sit velit magna sunt aliqua non consequat fugiat.",
+    "registered": "Thursday, December 8, 2016 4:21 AM",
+    "latitude": "-80.99902",
+    "longitude": "147.004691",
+    "tags": [
+      "cillum",
+      "magna",
+      "dolor",
+      "nisi",
+      "tempor"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Bright Freeman"
+      },
+      {
+        "id": 1,
+        "name": "Erickson Carpenter"
+      },
+      {
+        "id": 2,
+        "name": "Cora Farley"
+      }
+    ],
+    "greeting": "Hello, Rhea! You have 7 unread messages.",
+    "favoriteFruit": "strawberry"
+  },
+  {
+    "_id": "5a5ce2cd102dde37ebd13894",
+    "index": 2,
+    "guid": "7e2be225-7c05-463c-b344-65bffc1088ec",
+    "isActive": true,
+    "balance": "$1,701.42",
+    "picture": "http://placehold.it/32x32",
+    "age": 27,
+    "eyeColor": "green",
+    "name": {
+      "first": "Cardenas",
+      "last": "Shields"
+    },
+    "company": "ORBALIX",
+    "email": "cardenas.shields@orbalix.me",
+    "phone": "+1 (938) 582-3132",
+    "address": "639 Prospect Avenue, Allamuchy, Minnesota, 7076",
+    "about": "Fugiat aute incididunt anim tempor culpa id dolore laborum laborum. Ipsum officia ea duis laboris esse labore laborum voluptate elit. Id laborum excepteur nostrud ea excepteur reprehenderit excepteur do culpa culpa voluptate. Ad ut sint sit veniam. Proident culpa cillum amet cupidatat minim dolor eiusmod fugiat eiusmod pariatur dolor officia nisi. Laborum elit reprehenderit commodo mollit esse occaecat. Irure aliquip proident sint minim dolore et amet.",
+    "registered": "Monday, July 24, 2017 10:44 AM",
+    "latitude": "27.572881",
+    "longitude": "28.632266",
+    "tags": [
+      "tempor",
+      "occaecat",
+      "ad",
+      "exercitation",
+      "voluptate"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Garner Campbell"
+      },
+      {
+        "id": 1,
+        "name": "Goldie Decker"
+      },
+      {
+        "id": 2,
+        "name": "Marietta Blackwell"
+      }
+    ],
+    "greeting": "Hello, Cardenas! You have 8 unread messages.",
+    "favoriteFruit": "apple"
+  },
+  {
+    "_id": "5a5ce2ce7cfb648d85e3525a",
+    "index": 3,
+    "guid": "83ca625d-3479-47b2-ba0f-f51d7da2ead4",
+    "isActive": true,
+    "balance": "$2,187.71",
+    "picture": "http://placehold.it/32x32",
+    "age": 26,
+    "eyeColor": "blue",
+    "name": {
+      "first": "Margarita",
+      "last": "Schmidt"
+    },
+    "company": "ZYPLE",
+    "email": "margarita.schmidt@zyple.biz",
+    "phone": "+1 (922) 424-2606",
+    "address": "795 Livingston Street, Gerton, Marshall Islands, 796",
+    "about": "Adipisicing aute in deserunt nulla non et consectetur. Ullamco eu ullamco pariatur reprehenderit reprehenderit ullamco velit eiusmod velit duis. Eiusmod occaecat id nostrud ex sunt deserunt laboris reprehenderit exercitation tempor consequat id eu laborum. Id culpa Lorem culpa esse pariatur. Cupidatat proident voluptate proident esse nisi aliqua pariatur magna incididunt veniam adipisicing adipisicing ullamco aliquip.",
+    "registered": "Saturday, April 19, 2014 12:02 PM",
+    "latitude": "-20.129573",
+    "longitude": "-172.625186",
+    "tags": [
+      "duis",
+      "dolore",
+      "in",
+      "quis",
+      "sit"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Rollins Cote"
+      },
+      {
+        "id": 1,
+        "name": "Norton Sampson"
+      },
+      {
+        "id": 2,
+        "name": "Doreen Rodriguez"
+      }
+    ],
+    "greeting": "Hello, Margarita! You have 6 unread messages.",
+    "favoriteFruit": "banana"
+  },
+  {
+    "_id": "5a5ce2ce18c85fa340fae3d3",
+    "index": 4,
+    "guid": "15f739f5-5bf4-431f-9aed-27cd96f40a4e",
+    "isActive": true,
+    "balance": "$1,302.51",
+    "picture": "http://placehold.it/32x32",
+    "age": 33,
+    "eyeColor": "green",
+    "name": {
+      "first": "Howell",
+      "last": "Stuart"
+    },
+    "company": "GEEKOSIS",
+    "email": "howell.stuart@geekosis.name",
+    "phone": "+1 (852) 591-3510",
+    "address": "315 Graham Avenue, Madaket, Kentucky, 522",
+    "about": "Anim deserunt et ex cillum mollit proident veniam elit deserunt nisi. Ea voluptate irure in sit elit est velit do deserunt mollit est elit enim proident. Incididunt mollit ullamco eu ad elit laboris incididunt commodo laborum eu. Ea amet Lorem irure deserunt qui amet ipsum adipisicing consectetur et exercitation id. Voluptate qui fugiat elit non veniam mollit occaecat duis amet quis consectetur nostrud cupidatat aute. Enim pariatur enim aliqua nulla pariatur sit culpa occaecat adipisicing cupidatat mollit exercitation. In proident excepteur qui officia ex.",
+    "registered": "Sunday, May 3, 2015 11:58 PM",
+    "latitude": "1.946901",
+    "longitude": "179.814874",
+    "tags": [
+      "mollit",
+      "ea",
+      "consectetur",
+      "in",
+      "ad"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Marina Stanton"
+      },
+      {
+        "id": 1,
+        "name": "Love Phelps"
+      },
+      {
+        "id": 2,
+        "name": "Burris Walton"
+      }
+    ],
+    "greeting": "Hello, Howell! You have 6 unread messages.",
+    "favoriteFruit": "strawberry"
+  },
+  {
+    "_id": "5a5ce2ce367b46adf273fd7c",
+    "index": 5,
+    "guid": "cb496b37-60d7-4d59-8dc8-4ed2242b8777",
+    "isActive": true,
+    "balance": "$2,596.21",
+    "picture": "http://placehold.it/32x32",
+    "age": 31,
+    "eyeColor": "blue",
+    "name": {
+      "first": "Elisabeth",
+      "last": "Stevenson"
+    },
+    "company": "EXOSTREAM",
+    "email": "elisabeth.stevenson@exostream.net",
+    "phone": "+1 (870) 484-2682",
+    "address": "907 Lorraine Street, Tonopah, New Hampshire, 1579",
+    "about": "Laboris sint eiusmod quis magna qui nostrud irure proident dolore commodo excepteur adipisicing cupidatat. Aliqua exercitation sint reprehenderit ipsum. Cillum duis consequat id in irure et. Non est consequat sint sunt deserunt sint ut. Duis esse laboris magna eu.",
+    "registered": "Tuesday, December 9, 2014 2:39 AM",
+    "latitude": "-89.110272",
+    "longitude": "-135.089766",
+    "tags": [
+      "est",
+      "commodo",
+      "est",
+      "nisi",
+      "tempor"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Price Rollins"
+      },
+      {
+        "id": 1,
+        "name": "Elba Knowles"
+      },
+      {
+        "id": 2,
+        "name": "Jennifer Mcfarland"
+      }
+    ],
+    "greeting": "Hello, Elisabeth! You have 9 unread messages.",
+    "favoriteFruit": "strawberry"
+  },
+  {
+    "_id": "5a5ce2cee401379a32153f99",
+    "index": 6,
+    "guid": "52bf2d2e-bf79-4711-96da-855828d1b29f",
+    "isActive": true,
+    "balance": "$2,762.48",
+    "picture": "http://placehold.it/32x32",
+    "age": 25,
+    "eyeColor": "green",
+    "name": {
+      "first": "Flossie",
+      "last": "Hester"
+    },
+    "company": "CALCULA",
+    "email": "flossie.hester@calcula.biz",
+    "phone": "+1 (982) 535-3187",
+    "address": "449 Boulevard Court, Tibbie, Missouri, 7737",
+    "about": "Nulla nulla commodo fugiat cillum minim sit sint Lorem ut exercitation. Adipisicing do nulla aute aliquip ad deserunt dolor eiusmod. Magna est exercitation eu irure exercitation qui velit Lorem commodo nulla. Ad consequat ea magna sint. Excepteur labore ipsum eiusmod laborum pariatur. Nisi amet esse aliquip irure voluptate occaecat pariatur culpa culpa enim occaecat anim.",
+    "registered": "Friday, December 18, 2015 5:19 AM",
+    "latitude": "13.766587",
+    "longitude": "-143.830063",
+    "tags": [
+      "ut",
+      "id",
+      "laborum",
+      "laboris",
+      "qui"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Ramirez Bass"
+      },
+      {
+        "id": 1,
+        "name": "Glenn Finch"
+      },
+      {
+        "id": 2,
+        "name": "Suarez Haney"
+      }
+    ],
+    "greeting": "Hello, Flossie! You have 9 unread messages.",
+    "favoriteFruit": "banana"
+  },
+  {
+    "_id": "5a5ce2ce744a8d7d016dc997",
+    "index": 7,
+    "guid": "50576b0b-4eba-46ab-8d20-d22d4aabeb36",
+    "isActive": true,
+    "balance": "$2,067.61",
+    "picture": "http://placehold.it/32x32",
+    "age": 40,
+    "eyeColor": "brown",
+    "name": {
+      "first": "Letha",
+      "last": "Mason"
+    },
+    "company": "ENORMO",
+    "email": "letha.mason@enormo.us",
+    "phone": "+1 (873) 475-3531",
+    "address": "356 Albemarle Road, Finderne, Utah, 7234",
+    "about": "Sit ea reprehenderit consequat consectetur incididunt aute irure esse. Est nisi officia cupidatat laborum ullamco consequat quis adipisicing fugiat cillum mollit exercitation. Velit sint adipisicing ullamco dolore laboris deserunt veniam quis voluptate occaecat ad id. Nisi aliqua sunt labore proident dolor elit elit irure nostrud deserunt in ad labore ea. Duis ut nisi nostrud labore anim amet. Eiusmod magna exercitation exercitation laborum Lorem est reprehenderit incididunt non dolor sint in Lorem.",
+    "registered": "Saturday, February 8, 2014 11:56 PM",
+    "latitude": "57.291623",
+    "longitude": "-2.123351",
+    "tags": [
+      "quis",
+      "magna",
+      "labore",
+      "sit",
+      "do"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Cochran Sherman"
+      },
+      {
+        "id": 1,
+        "name": "Robyn Pickett"
+      },
+      {
+        "id": 2,
+        "name": "Bernard Wynn"
+      }
+    ],
+    "greeting": "Hello, Letha! You have 9 unread messages.",
+    "favoriteFruit": "strawberry"
+  },
+  {
+    "_id": "5a5ce2cee6339ae2cda7fb42",
+    "index": 8,
+    "guid": "3659a7ce-9e1a-429b-843e-5c189a1964a1",
+    "isActive": true,
+    "balance": "$1,708.64",
+    "picture": "http://placehold.it/32x32",
+    "age": 27,
+    "eyeColor": "brown",
+    "name": {
+      "first": "Maricela",
+      "last": "Erickson"
+    },
+    "company": "ARTIQ",
+    "email": "maricela.erickson@artiq.tv",
+    "phone": "+1 (814) 469-3562",
+    "address": "181 Lott Street, Sehili, Massachusetts, 3999",
+    "about": "Ex esse proident qui eiusmod mollit aliqua elit esse excepteur labore. Commodo excepteur consectetur reprehenderit officia officia deserunt. Duis veniam adipisicing excepteur eu occaecat consectetur nisi mollit.",
+    "registered": "Saturday, September 19, 2015 10:08 AM",
+    "latitude": "51.659867",
+    "longitude": "85.456825",
+    "tags": [
+      "aute",
+      "duis",
+      "non",
+      "elit",
+      "culpa"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Byers Avila"
+      },
+      {
+        "id": 1,
+        "name": "Alexis Logan"
+      },
+      {
+        "id": 2,
+        "name": "May Hudson"
+      }
+    ],
+    "greeting": "Hello, Maricela! You have 7 unread messages.",
+    "favoriteFruit": "apple"
+  },
+  {
+    "_id": "5a5ce2ce035f9c3d854695ad",
+    "index": 9,
+    "guid": "1eb96c85-88b0-4f3e-a6d8-025250c6e627",
+    "isActive": true,
+    "balance": "$2,536.13",
+    "picture": "http://placehold.it/32x32",
+    "age": 34,
+    "eyeColor": "green",
+    "name": {
+      "first": "Vance",
+      "last": "Snow"
+    },
+    "company": "MEDIOT",
+    "email": "vance.snow@mediot.com",
+    "phone": "+1 (851) 528-3906",
+    "address": "236 Monument Walk, Malo, Indiana, 152",
+    "about": "Reprehenderit qui commodo et deserunt cillum nisi veniam proident et. Est dolor veniam amet est. Exercitation ad nisi ut tempor laborum excepteur id ex nostrud quis reprehenderit. Aliqua in cillum exercitation velit. In nisi Lorem adipisicing aute ipsum sint excepteur voluptate aliquip consequat eiusmod culpa elit. Duis laborum pariatur eiusmod eu fugiat in velit aliquip aliqua excepteur.",
+    "registered": "Tuesday, February 21, 2017 6:12 PM",
+    "latitude": "-80.255226",
+    "longitude": "-106.172443",
+    "tags": [
+      "cillum",
+      "excepteur",
+      "sit",
+      "qui",
+      "tempor"
+    ],
+    "range": [
+      0,
+      1,
+      2,
+      3,
+      4,
+      5,
+      6,
+      7,
+      8,
+      9
+    ],
+    "friends": [
+      {
+        "id": 0,
+        "name": "Leon Best"
+      },
+      {
+        "id": 1,
+        "name": "Eleanor Villarreal"
+      },
+      {
+        "id": 2,
+        "name": "Lily Mccoy"
+      }
+    ],
+    "greeting": "Hello, Vance! You have 8 unread messages.",
+    "favoriteFruit": "apple"
+  }
+]