{"id":16463327,"url":"https://github.com/dptole/js-bson","last_synced_at":"2025-06-30T08:36:52.032Z","repository":{"id":19848289,"uuid":"23110305","full_name":"dptole/js-bson","owner":"dptole","description":"JavaScript BSON implementation.","archived":false,"fork":false,"pushed_at":"2023-01-11T18:09:24.000Z","size":70,"stargazers_count":5,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-31T00:48:21.283Z","etag":null,"topics":["bson","decode","encode","mongo","mongodb"],"latest_commit_sha":null,"homepage":"http://bsonspec.org/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dptole.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-08-19T13:02:54.000Z","updated_at":"2023-01-11T18:09:29.000Z","dependencies_parsed_at":"2023-01-13T20:37:50.820Z","dependency_job_id":null,"html_url":"https://github.com/dptole/js-bson","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/dptole/js-bson","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dptole%2Fjs-bson","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dptole%2Fjs-bson/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dptole%2Fjs-bson/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dptole%2Fjs-bson/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dptole","download_url":"https://codeload.github.com/dptole/js-bson/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dptole%2Fjs-bson/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262739915,"owners_count":23356798,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bson","decode","encode","mongo","mongodb"],"created_at":"2024-10-11T11:14:08.771Z","updated_at":"2025-06-30T08:36:52.002Z","avatar_url":"https://github.com/dptole.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"js-bson\n=======\n\nJavaScript implementation of the [BSON](http://bsonspec.org/) specification.\n\n-\n\n## Supported types\n\nData type | Description\n--------- | -----------\nArray | A BSON embedded document number indexed.\nBinary | A `Binary` instance with a `subtype` property.\nBoolean | Standard boolean.\nDocument | A BSON embedded document.\nDouble | 64-bit IEEE 754 floating point.\nInt32 | Integer 32 bit signed value.\nInt64 | Integer 64 bit signed value. \u003ctable\u003e\u003cthead\u003e\u003cth\u003eWhen\u003c/th\u003e\u003cth\u003eInterpretation\u003c/th\u003e\u003c/thead\u003e\u003ctbody\u003e\u003ctr\u003e\u003ctd\u003eEncoding\u003c/td\u003e\u003ctd\u003eDouble.\u003c/td\u003e\u003ctr\u003e\u003ctd\u003eDecoding\u003c/td\u003e\u003ctd\u003eA `Int64` instance.\u003c/td\u003e\u003c/tbody\u003e\u003c/table\u003e\u003cblockquote\u003eInt64 is encoded and decoded differently because of the lack of support of the Int32+ numbers by the JavaScript language.\u003c/blockquote\u003e\nJS Code | JavaScript code.\nJS Code with scope | JavaScript code with variables.\nNull | Null JavaScript keyword.\nRegExp | Regular expression.\nString | Int32 length UTF-8 string.\nUndefined | Undefined JavaScript keyword. \u003cblockquote\u003eAccordingly to the BSON specification this type should be deprecated but, as long as JavaScript have a keyword specifically created to express this type of data, I will keep it.\u003c/blockquote\u003e\nUTC Datetime | Unix epoch datetime in milliseconds.\n\n## Not supported types\n\nData type | Description\n--------- | ---------\nDB Pointer | *Deprecated*.\nMax Key | MongoDB [Max Key](http://docs.mongodb.org/manual/reference/operator/query/type/) internal type used to compare higher than all other possible BSON element values.\nMin Key | MongoDB [Min Key](http://docs.mongodb.org/manual/reference/operator/query/type/) internal type used to compare lower than all other possible BSON element values.\nObject Id | MongoDB [ObjectId](http://docs.mongodb.org/manual/reference/object-id/) internal type used to uniquely\nTimestamp | MongoDB [Timestamp](http://docs.mongodb.org/manual/reference/method/ObjectId.getTimestamp/) internal type used for replication.\n\n## Basic\n\nTo create a BSON document using JavaScript types:\n\n```javascript\nvar encoded_bson = BSON.encode({\n  login: 'dptole',                  // String\n  id: 3951114,                      // Int32\n  gender: null,                     // Null\n  ready_profile: 12.34,             // Double\n  formats: /(jpe?g|mp[34]|html?)/,  // RegExp\n  site_admin: false,                // Boolean(false)\n  is_user: true,                    // Boolean(true)\n  limbs: {                          // BSON embedded document\n    arms: ['hands', 'fingers'],     // BSON embedded document number indexed\n  },\n  created_at: new Date(2013, 2, 23) // UTC Datetime\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.login         : 'dptole'\n  javascript_object.id            : 3951114\n  javascript_object.gender        : null\n  javascript_object.ready_profile : 12.34\n  javascript_object.formats       : /(jpe?g|mp[34]|html?)/\n  javascript_object.site_admin    : false\n  javascript_object.is_user       : true\n  javascript_object.limbs         : {arms: ['hands', 'fingers']}\n  javascript_object.limbs.arms    : ['hands', 'fingers']\n  javascript_object.limbs.arms[0] : 'hands'\n  javascript_object.limbs.arms[1] : 'fingers'\n  javascript_object.created_at    : 'Sat, 23 Mar 2013 00:00:00 GMT'\n*/\n\n```\n\n### Undefined and Int64\n\nAccordingly to the BSON specification the `undefined` type should be deprecated but, as long as JavaScript have a keyword specifically created to express this type of data, I will keep it.\n`Int64` is encoded as `Double` because of the lack of support of the Int32+ numbers by the JavaScript language.\n\n```javascript\nvar encoded_bson = BSON.encode({\n  website: undefined,               // Undefined\n  timestamp: +new Date              // Int64 encoded as Double\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.website   : undefined\n  javascript_object.timestamp : 1411179144221\n*/\n\n```\n\n### Encoding Binary data\n\nBinary data can be encoded by calling `BSON.binary(data, substype)` where `data` may be any string and `substype` may be between 0x00-0x05 or 0x80-0xFF. Some castings may occur during `subtype` interpretation.\n\nSubtype | Casting\n------- | -------\nBinary (0x02) | Generic (0x00)\nUUID Old (0x03) | UUID (0x04)\n\n```javascript\nvar encoded_bson = BSON.encode({\n  binary: BSON.binary('\\x64\\x70\\x74\\x6f\\x6c\\x65', 2)\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.binary\n    Binary {toString: function, subtype: 0}\n*/\n\n```\n\n### Encoding JS Code/JS Code with scope\n\nJS Code data can be encoded by calling `BSON.jsCode(code)` where `code` may be any string. The syntax is verified when decoding.\n\n```javascript\nvar encoded_bson = BSON.encode({\n  fun: BSON.jsCode('return +new Date')\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.fun\n    function anonymous() {\n    return +new Date\n    }\n*/\n\n```\n\nJS Code with scope data can be encoded by calling `BSON.jsCodeWithScope(code, scope)` where `code` may be any string and `scope` is an object. Each key in `scope` will be a variable name within the JavaScript code and the key value is interpreted as JavaScript code.\nThus in `{\"func\": \"Math.random\"}` we have a variable called `func` which refers to the `Math.random` function, while in `{\"func\": \"'Math.random'\"}` we have a variable called `func` which value is the string `\"Math.random\"`.\nThis behaviour may be desirable when one peer must call internal functions at the other peer's environment but don't want to duplicate the code nor worry about code update.\n\n```javascript\nvar encoded_bson = BSON.encode({\n  fun: BSON.jsCodeWithScope('return internal(origin, ts)', {\n    origin: '\"My nick\"',\n    internal: 'otherPeerFunction',\n    ts: +new Date\n  })\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.fun\n    function anonymous() {\n    var origin = \"My nick\"\n      , internal = otherPeerFunction\n      , ts = 1411177888866\n    ;\n    return internal(origin, ts)\n    }\n*/\n\n```\n\n### Encoding JS Code(functions) with arguments\n\nJS Code(functions) with arguments can be encoded by calling `BSON.jsFunction(lambda)` where `lambda` may be any user defined function.\n\n```javascript\nvar encoded_bson = BSON.encode({\n  fun: BSON.jsFunction(function(a, b) {\n    return a + b;\n  })\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.fun\n    function anonymous(a, b) {\n      return a + b;\n    }\n*/\n\n```\n\n### Encoding JS Code(functions) with arguments and scope\n\nJS Code(functions) with arguments and scope can be encoded by calling `BSON.jsFunction(lambda, variables)` where `lambda` may be any user defined function and `variables` works as `scope` in `BSON.jsCodeWithScope`.\n\n```javascript\nvar encoded_bson = BSON.encode({\n  fun: BSON.jsFunction(function(a, b) {\n    return a * Math.pow(x, 2) + b * x + c;\n  }, {x: 4, c: -16})\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.fun\n    function anonymous(a, b) {\n      var x = 4\n        , c = -16\n      ;\n      return a * Math.pow(x, 2) + b * x + c;\n    }\n*/\n\n```\n\n\u003e Attention! **JS Code** and **JS Code with scope** may not work across other implementations because not all of them may support it. Consider using these types just within the same implementation.\n\n# Advanced\n\n## Encoding\n\nYou can encode any element using a function as long as you understand the BSON specification, check the example:\n\n```javascript\nvar encoded_bson = BSON.encode({\n  true_key_custom: function( key ) {\n    // \\x08 - Boolean type\n    // key  - 'true_key_custom'\n    // \\x00 - Separator\n    // \\x01 - true\n    return '\\x08' + key + '\\x00\\x01';\n  },\n  true_key: true\n});\n\nvar javascript_object = BSON.decode(encoded_bson);\n/*\n  javascript_object.true_key_custom true\n  javascript_object.true_key        true\n*/\n\n```\n\nThis way you can encode any BSON type, even those without support.\n\n## Decoding\n\nWhen decoding a chunk of BSON data the interpreter may find unexpected types that it don't know how to handle and it breaks. To deal with such situations, and to expand the possibilities of this BSON implementation, you may send a second argument as a function to `BSON.decode()` to treat unknown types. This function receives three arguments `type`, `key` and `buffer` and must return an array with 3 indexes [`Number`, `String`, `Anything`]. The following code may give you a better explanation:\n\n```javascript\nBSON.decode(bson_data, function(type, key, buffer) {\n  // \n  // type -\u003e Number\n  //   The unknown type that you need to handle\n  //   It's just 1 octet length and it's a number representing the unknown BSON type\n  // \n  // key -\u003e String\n  //   Everything after \u003ctype\u003e and before the null character \u003c0x00\u003e\n  //   The captured value is interpreted as a string\n  // \n  // buffer -\u003e Array\n  //   Everything after the null character \u003c0x00\u003e to the end of the document\n  //   Notice that the last octet of a document is always \u003c0x00\u003e\n  //   \n  // This function must return an array with 3 indexes where\n  // \n  // [\n  //   Number,\n  //     How many octets to the next type?\n  //   String,\n  //     What is the name of the key to the given document (may be an array)?\n  //   Anything\n  //     Any output value\n  // ]\n  // \n});\n```\n\nI will give you an example of how this fallback works. When you encode something like this\n\n```javascript\nvar my_gps = BSON.encode({\n  coords: [\n    // \\x80 - Coordinates user-defined type\n    // key  - 0 (zero) to 4 (four)\n    // \\x00 - Separator\n    // .... - X, Y and Z coordinates\n    function(key) { return \"\\x80\" + key + \"\\x00\\x00\\x55\\xAA\"; },\n    function(key) { return \"\\x80\" + key + \"\\x00\\x11\\x66\\xBB\"; },\n    function(key) { return \"\\x80\" + key + \"\\x00\\x22\\x77\\xCC\"; },\n    function(key) { return \"\\x80\" + key + \"\\x00\\x33\\x88\\xDD\"; },\n    function(key) { return \"\\x80\" + key + \"\\x00\\x44\\x99\\xEE\"; }\n  ]\n});\nvar json_object = BSON.decode(my_gps, function(type, key, buffer) {\n  var coords = String.fromCharCode.apply(String, buffer);\n  return [\n    3,\n    key,\n    {\n      x: coords.charCodeAt(0),\n      y: coords.charCodeAt(1),\n      z: coords.charCodeAt(2)\n    }\n  ];\n});\n/*\n  json_object.coords    [Object, Object, Object, Object, Object]\n  json_object.coords[0] {\"x\":  0, \"y\":  85, \"z\": 170}\n  json_object.coords[1] {\"x\": 17, \"y\": 102, \"z\": 187}\n  json_object.coords[2] {\"x\": 34, \"y\": 119, \"z\": 204}\n  json_object.coords[3] {\"x\": 51, \"y\": 136, \"z\": 221} \n  json_object.coords[4] {\"x\": 68, \"y\": 153, \"z\": 238}\n*/\n```\n\nThe `my_gps` variable holds this BSON document `\\x30\\x00\\x00\\x00\\x04\\x63\\x6f\\x6f\\x72\\x64\\x73\\x00\\x23\\x00\\x00\\x00\\x80\\x30\\x00\\x00\\x55\\xaa\\x80\\x31\\x00\\x11\\x66\\xbb\\x80\\x32\\x00\\x22\\x77\\xcc\\x80\\x33\\x00\\x33\\x88\\xdd\\x80\\x34\\x00\\x44\\x99\\xee\\x00\\x00` and the following explanation may enlighten how this document is decoded and how the fallback function deal with it.\n\n```javascript\n// A document whose length is 48(0x30,0x00,0x00,0x00) and is written in little endian\n\\x30\\x00\\x00\\x00\n\n  // An array(0x04) whose name is \"coords\"(0x63,0x6F,0x6F,0x72,0x64,0x73)\n  // and the separator 0x00\n  \\x04\\x63\\x6f\\x6f\\x72\\x64\\x73\\x00\n  \n  // The length of this array is 35(0x23,0x00,0x00,0x00) written in little endian\n  \\x23\\x00\\x00\\x00\n  \n    // The type of this element is 0x80(unknown) the name is \"0\"(0x30) and 0x00\n    // is the separator. The BSON specification don't have a definition for a 0x80\n    // type so it must be an user-defined type and the fallback function will be called\n    \\x80\\x30\\x00\n    \\x00\\x55\\xaa\n    \n    // function(type, key, buffer) {\n    //   type   === 128 (0x80 interpreted as a number)\n    //   key    === \"0\" (0x30 interpreted as a string)\n    //   buffer === [0x00, 0x55, 0xaa, 0x80, 0x31, 0x00, 0x11, 0x66, 0xbb, 0x80,\n    //               0x32, 0x00, 0x22, 0x77, 0xcc, 0x80, 0x33, 0x00, 0x33, 0x88,\n    //               0xdd, 0x80, 0x34, 0x00, 0x44, 0x99, 0xee, 0x00, 0x00       ]\n    // \n    //   ... Code to parse the data ...\n    // \n    //   return [\n    //     3,\n    //       How many octets do I have to \"walk\" to get to the type of the next element?\n    //         1  |   2   |   3   | Type of the next element\n    //       \\x00 | \\x55  | \\xaa  |        \\x80\n    //       This value may not be negative but it may be zero\n    //     \n    //     key,\n    //       To the given document (array or object) which will be the name of this\n    //       element? In this case it's an array so I'll keep the same index here but\n    //       if I wanted I could set it to \u003c\"key\" + key\u003e and to access it I would have\n    //       to write \u003cjavascript_object.coords.key0\u003e for example\n    //     \n    //     value\n    //       Any value\n    //     \n    //   ];\n    // }\n    \n    // Same thing as before\n    \\x80\\x31\\x00\n    \\x11\\x66\\xbb\n    \n    // Same thing as before\n    \\x80\\x32\\x00\n    \\x22\\x77\\xcc\n    \n    // Same thing as before\n    \\x80\\x33\\x00\n    \\x33\\x88\\xdd\n    \n    // Same thing as before\n    \\x80\\x34\\x00\n    \\x44\\x99\\xee\n  \\x00\n\\x00\n```\n\nThis way you can decode any BSON type, even those without support.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdptole%2Fjs-bson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdptole%2Fjs-bson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdptole%2Fjs-bson/lists"}