diff --git a/buf.gen.yaml b/buf.gen.yaml index a3c0343..08e4ecd 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -17,3 +17,4 @@ plugins: - enumsAsLiterals=true # - outputIndex=true - oneof=unions + - Mgeometry/stub.proto=@comapeo/geometry diff --git a/package-lock.json b/package-lock.json index 8180c2f..771aa9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { - "name": "@mapeo/schema", + "name": "@comapeo/schema", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@mapeo/schema", + "name": "@comapeo/schema", "version": "1.0.0", "license": "MIT", "dependencies": { + "@comapeo/geometry": "^1.0.1", "compact-encoding": "^2.12.0", "protobufjs": "^7.2.5", "type-fest": "^4.26.0" @@ -24,7 +25,7 @@ "eslint": "^8.46.0", "glob": "^10.3.3", "hypercore": "^10.4.1", - "json-schema-to-typescript": "^13.0.2", + "json-schema-to-typescript": "^15.0.2", "mkdirp": "^3.0.1", "npm-run-all": "^4.1.5", "prettier": "^3.0.0", @@ -46,6 +47,24 @@ "node": ">=0.10.0" } }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "11.7.0", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.0.tgz", + "integrity": "sha512-pRrmXMCwnmrkS3MLgAIW5dXRzeTv6GLjkjb4HmxNnvAKXN1Nfzp4KmGADBQvlVUcqi+a5D+hfGDLLnd5NnYxog==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/philsturgeon" + } + }, "node_modules/@babel/code-frame": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", @@ -152,24 +171,6 @@ "node": ">=4" } }, - "node_modules/@bcherny/json-schema-ref-parser": { - "version": "10.0.5-fork", - "resolved": "https://registry.npmjs.org/@bcherny/json-schema-ref-parser/-/json-schema-ref-parser-10.0.5-fork.tgz", - "integrity": "sha512-E/jKbPoca1tfUPj3iSbitDZTGnq6FUFjkH6L8U2oDwSuwK1WhnnVtCG7oFOTg/DDnyoXbQYUiUiGOibHqaGVnw==", - "dev": true, - "dependencies": { - "@jsdevtools/ono": "^7.1.3", - "@types/json-schema": "^7.0.6", - "call-me-maybe": "^1.0.1", - "js-yaml": "^4.1.0" - }, - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://github.com/sponsors/philsturgeon" - } - }, "node_modules/@bcoe/v8-coverage": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", @@ -295,6 +296,15 @@ "node": ">=12" } }, + "node_modules/@comapeo/geometry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@comapeo/geometry/-/geometry-1.0.1.tgz", + "integrity": "sha512-ZH9akj8k/awYUm8GVGyGSs99xNGJotWoo3czCS3Ds3/RgewiSxHbe1JU6PnJ/M2sT6GqbTatAGgNky9g5pK6Vg==", + "license": "MIT", + "dependencies": { + "protobufjs": "^7.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -563,7 +573,8 @@ "version": "7.1.3", "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@json-schema-spec/json-pointer": { "version": "0.1.2", @@ -718,16 +729,6 @@ "integrity": "sha512-NmvvYrQC9QqbbEfm6ISHfCvvfQIwq53B4hZ7aAP6mEXsPc2F15Lkxj+jGzqVeKTT+Ir0HXAj4O9YUDsIpJbOuA==", "dev": true }, - "node_modules/@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "dependencies": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, "node_modules/@types/hast": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", @@ -745,22 +746,18 @@ "dev": true }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.14.196", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.196.tgz", - "integrity": "sha512-22y3o88f4a94mKljsZcanlNWPzO0uBsBdzLAngf2tp533LzZcQzb6+eZPJ+vCTt+bqF2XnvT9gejTLsAcJAJyQ==", - "dev": true - }, - "node_modules/@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/minimist": { "version": "1.2.2", @@ -779,12 +776,6 @@ "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", "dev": true }, - "node_modules/@types/prettier": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", - "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true - }, "node_modules/@types/unist": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", @@ -870,12 +861,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1046,12 +1031,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-me-maybe": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", - "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", - "dev": true - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1167,22 +1146,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-color": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.3.tgz", - "integrity": "sha512-OkoZnxyC4ERN3zLzZaY9Emb7f/MhBOIpePv0Ycok0fJYT+Ouo00UBEIwsVsr0yoow++n5YWlSUgST9GKhNHiRQ==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.61", - "es6-iterator": "^2.0.3", - "memoizee": "^0.4.15", - "timers-ext": "^0.1.7" - }, - "engines": { - "node": ">=0.10" - } - }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -1316,16 +1279,6 @@ "node": ">= 8" } }, - "node_modules/d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", - "dev": true, - "dependencies": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" - } - }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1551,54 +1504,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.3", - "next-tick": "^1.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "node_modules/es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "ext": "^1.1.2" - } - }, - "node_modules/es6-weak-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", - "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "^0.10.46", - "es6-iterator": "^2.0.3", - "es6-symbol": "^3.1.1" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -1783,16 +1688,6 @@ "node": ">=0.10.0" } }, - "node_modules/event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", - "dev": true, - "dependencies": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", @@ -1802,21 +1697,6 @@ "node": ">=0.8.x" } }, - "node_modules/ext": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", - "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", - "dev": true, - "dependencies": { - "type": "^2.7.2" - } - }, - "node_modules/ext/node_modules/type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -2081,18 +1961,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-stdin": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", - "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/get-symbol-description": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", @@ -2621,12 +2489,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-promise": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", - "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==", - "dev": true - }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -2797,97 +2659,27 @@ "dev": true }, "node_modules/json-schema-to-typescript": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-13.0.2.tgz", - "integrity": "sha512-TCaEVW4aI2FmMQe7f98mvr3/oiVmXEC1xZjkTZ9L/BSoTXFlC7p64mD5AD2d8XWycNBQZUnHwXL5iVXt1HWwNQ==", - "dev": true, - "dependencies": { - "@bcherny/json-schema-ref-parser": "10.0.5-fork", - "@types/json-schema": "^7.0.11", - "@types/lodash": "^4.14.182", - "@types/prettier": "^2.6.1", - "cli-color": "^2.0.2", - "get-stdin": "^8.0.0", - "glob": "^7.1.6", - "glob-promise": "^4.2.2", + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/json-schema-to-typescript/-/json-schema-to-typescript-15.0.2.tgz", + "integrity": "sha512-+cRBw+bBJ3k783mZroDIgz1pLNPB4hvj6nnbHTWwEVl0dkW8qdZ+M9jWhBb+Y0FAdHvNsXACga3lewGO8lktrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^11.5.5", + "@types/json-schema": "^7.0.15", + "@types/lodash": "^4.17.7", + "glob": "^10.3.12", "is-glob": "^4.0.3", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", - "minimist": "^1.2.6", - "mkdirp": "^1.0.4", - "mz": "^2.7.0", - "prettier": "^2.6.2" + "minimist": "^1.2.8", + "prettier": "^3.2.5" }, "bin": { "json2ts": "dist/src/cli.js" }, "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/json-schema-to-typescript/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/json-schema-to-typescript/node_modules/glob-promise": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-4.2.2.tgz", - "integrity": "sha512-xcUzJ8NWN5bktoTIX7eOclO1Npxd/dyVqUJxlLIDasT4C7KZyqlPIwkdJ0Ypiy3p2ZKahTjK4M9uC3sNSfNMzw==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.3" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "individual", - "url": "https://github.com/sponsors/ahmadnassri" - }, - "peerDependencies": { - "glob": "^7.1.6" - } - }, - "node_modules/json-schema-to-typescript/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/json-schema-to-typescript/node_modules/prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "bin": { - "prettier": "bin-prettier.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=16.0.0" } }, "node_modules/json-schema-traverse": { @@ -2991,15 +2783,6 @@ "dev": true, "license": "ISC" }, - "node_modules/lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.2" - } - }, "node_modules/lunr": { "version": "2.3.9", "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", @@ -3058,22 +2841,6 @@ "dev": true, "license": "MIT" }, - "node_modules/memoizee": { - "version": "0.4.15", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", - "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", - "dev": true, - "dependencies": { - "d": "^1.0.1", - "es5-ext": "^0.10.53", - "es6-weak-map": "^2.0.3", - "event-emitter": "^0.3.5", - "is-promise": "^2.2.2", - "lru-queue": "^0.1.0", - "next-tick": "^1.1.0", - "timers-ext": "^0.1.7" - } - }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -3237,10 +3004,11 @@ } }, "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3299,17 +3067,6 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, "node_modules/nanoassert": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-2.0.0.tgz", @@ -3335,12 +3092,6 @@ "integrity": "sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw==", "dev": true }, - "node_modules/next-tick": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", - "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", - "dev": true - }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", @@ -3586,15 +3337,6 @@ "which": "bin/which" } }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -3893,10 +3635,11 @@ } }, "node_modules/prettier": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.0.tgz", - "integrity": "sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -3908,10 +3651,11 @@ } }, "node_modules/protobufjs": { - "version": "7.2.5", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", - "integrity": "sha512-gGXRSXvxQ7UiPgfw8gevrfRWcTlSbOFg+p/N+JVJEK5VhueL2miT6qTymqAmjr1Q5WbOCyJbyrk6JfWKwlFn6A==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.4.0.tgz", + "integrity": "sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -4903,43 +4647,12 @@ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, "node_modules/timeout-refresh": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/timeout-refresh/-/timeout-refresh-2.0.1.tgz", "integrity": "sha512-SVqEcMZBsZF9mA78rjzCrYrUs37LMJk3ShZ851ygZYW1cMeIjs9mL57KO6Iv5mmjSQnOe/29/VAfGXo+oRCiVw==", "dev": true }, - "node_modules/timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "dependencies": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5005,12 +4718,6 @@ "protobufjs": "^7.2.4" } }, - "node_modules/type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", - "dev": true - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index 960b456..ef6722e 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "eslint": "^8.46.0", "glob": "^10.3.3", "hypercore": "^10.4.1", - "json-schema-to-typescript": "^13.0.2", + "json-schema-to-typescript": "^15.0.2", "mkdirp": "^3.0.1", "npm-run-all": "^4.1.5", "prettier": "^3.0.0", @@ -57,6 +57,7 @@ "typescript": "^5.5.4" }, "dependencies": { + "@comapeo/geometry": "^1.0.1", "compact-encoding": "^2.12.0", "protobufjs": "^7.2.5", "type-fest": "^4.26.0" diff --git a/proto/geometry/stub.proto b/proto/geometry/stub.proto new file mode 100644 index 0000000..23800ba --- /dev/null +++ b/proto/geometry/stub.proto @@ -0,0 +1,7 @@ +syntax = "proto3"; +package mapeo; + +// stub to keep buf happy. ts-proto replaces this with +// the decoder/encoder from @comapeo/geometry + +message Geometry {} diff --git a/proto/remoteDetectionAlert/v1.proto b/proto/remoteDetectionAlert/v1.proto new file mode 100644 index 0000000..ee2e440 --- /dev/null +++ b/proto/remoteDetectionAlert/v1.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; +package mapeo; + +import "common/v1.proto"; +import "geometry/stub.proto"; +import "google/protobuf/timestamp.proto"; +import "options.proto"; +import "tags/v1.proto"; + +message RemoteDetectionAlert_1 { + // **DO NOT CHANGE dataTypeId** generated with `openssl rand -hex 6` + option (dataTypeId) = "33a966ee6c90"; + option (schemaName) = "remoteDetectionAlert"; + + Common_1 common = 1; + + google.protobuf.Timestamp detectionDateStart = 2 [(required) = true]; + google.protobuf.Timestamp detectionDateEnd = 3 [(required) = true]; + string sourceId = 4; + Geometry geometry = 5; + map metadata = 6; +} diff --git a/schema/remoteDetectionAlert/v1.json b/schema/remoteDetectionAlert/v1.json new file mode 100644 index 0000000..0f487da --- /dev/null +++ b/schema/remoteDetectionAlert/v1.json @@ -0,0 +1,80 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "$id": "http://mapeo.world/schemas/remoteDetectionAlert/v1.json", + "title": "RemoteDetectionAlert", + "description": "A remote detection alert is a type of element in the map that relates to an alert (regarding an urgent event that happened on the territory)", + "type": "object", + "properties": { + "schemaName": { + "description": "Must be `remoteDetectionAlert`", + "type": "string", + "const": "remoteDetectionAlert" + }, + "detectionDateStart": { + "type": "string", + "format": "date-time", + "description": "Timestamp of when the detected alert started" + }, + "detectionDateEnd": { + "type": "string", + "format": "date-time", + "description": "Timestamp of when the detected alert ended" + }, + "sourceId": { + "type": "string", + "description": "unique string identifiying this alert, different from the `docId`" + }, + "metadata": { + "type": "object", + "description": "Additional metadata related to this alert. It is a map from a string to any element (including lists)", + "properties": {}, + "additionalProperties": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "null" + }, + { + "type": "array", + "items": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "type": "null" + } + ] + } + } + ] + } + }, + "geometry": { + "$ref": "http://comapeo.app/schemas/shared/geometry.json" + } + }, + "required": [ + "schemaName", + "detectionDateStart", + "detectionDateEnd", + "sourceId", + "metadata", + "geometry" + ], + "additionalProperties": false +} diff --git a/scripts/lib/generate-jsonschema-exports.js b/scripts/lib/generate-jsonschema-exports.js index 2fa8fd0..96255d4 100644 --- a/scripts/lib/generate-jsonschema-exports.js +++ b/scripts/lib/generate-jsonschema-exports.js @@ -1,5 +1,8 @@ // @ts-check import { default as _ } from '@json-schema-tools/dereferencer' +import { createRequire } from 'module' +const require = createRequire(import.meta.url) +const GeometryJSONSchema = require('@comapeo/geometry/json/geometry.json') // Dereferencer's exports are all wrong for ESM imports /** @type {any} */ @@ -28,7 +31,12 @@ export async function generateJSONSchemaExports(jsonSchemas) { const dereferencer = new JsonSchemaDereferencer( // Need to create a deep clone to avoid issue described in https://github.com/digidem/mapeo-schema/issues/109 JSON.parse(JSON.stringify(jsonSchema)), - { mutate: false } + { + mutate: false, + refCache: { + [GeometryJSONSchema.$id]: GeometryJSONSchema, + }, + } ) dereferencedDocSchemas[schemaName] = await dereferencer.resolve() } diff --git a/scripts/lib/generate-jsonschema-ts.js b/scripts/lib/generate-jsonschema-ts.js index 1c1e3e1..ed6fcb6 100644 --- a/scripts/lib/generate-jsonschema-ts.js +++ b/scripts/lib/generate-jsonschema-ts.js @@ -1,6 +1,12 @@ // @ts-check import { compile } from 'json-schema-to-typescript' import { capitalize } from './utils.js' +import { createRequire } from 'module' + +const require = createRequire(import.meta.url) +const GeometryJSONSchema = require('@comapeo/geometry/json/geometry.json') + +/** @import { ResolverOptions, JSONSchema } from '@apidevtools/json-schema-ref-parser' */ /** * Returns generated typescript definitions for JSONSchemas @@ -16,6 +22,12 @@ export async function generateJSONSchemaTS(config, jsonSchemas) { const ts = await compile(jsonSchema, capitalize(schemaName), { additionalProperties: false, unknownAny: false, + $refOptions: { + resolve: { + http: false, + geometry: geometryResolver, + }, + }, }) typescriptDefs[schemaName] = ts } @@ -84,3 +96,14 @@ function getValueName(schemaName) { ? 'MapeoCommon' : capitalize(schemaName) + 'Value' } + +/** @type {ResolverOptions} */ +const geometryResolver = { + order: 1, + canRead(file) { + return file.url === GeometryJSONSchema.$id + }, + read() { + return GeometryJSONSchema + }, +} diff --git a/scripts/lib/generate-validations.js b/scripts/lib/generate-validations.js index d504632..b3181ba 100644 --- a/scripts/lib/generate-validations.js +++ b/scripts/lib/generate-validations.js @@ -1,6 +1,10 @@ // @ts-check import Ajv from 'ajv' import standaloneCode from 'ajv/dist/standalone/index.js' +import { createRequire } from 'module' + +const require = createRequire(import.meta.url) +const GeometryJSONSchema = require('@comapeo/geometry/json/geometry.json') const ucs2lengthCode = 'require("ajv/dist/runtime/ucs2length").default' @@ -25,7 +29,7 @@ export function generateValidations(config, jsonSchemas) { code: { source: true, esm: true }, formats: { 'date-time': true }, }) - ajv.addKeyword('meta:enum') + ajv.addKeyword('meta:enum').addSchema(GeometryJSONSchema) // generate validation code return [ diff --git a/scripts/lib/parse-config.js b/scripts/lib/parse-config.js index a909cf7..2a7da67 100644 --- a/scripts/lib/parse-config.js +++ b/scripts/lib/parse-config.js @@ -6,7 +6,7 @@ import schema from 'protocol-buffers-schema' import { capitalize, PROJECT_ROOT } from './utils.js' // These messages are embedded in others and do not define Mapeo data types -const EMBEDDED_MESSAGES = ['tags', 'common', 'versionId'] +const EMBEDDED_MESSAGES = ['tags', 'common', 'versionId', 'geometry'] // We avoid creating data type IDs that match these, since blobs (e.g. icons) // can be stored in Mapeo hypercores, and we want to avoid trying to parse a diff --git a/src/decode.ts b/src/decode.ts index c35043d..dcd607a 100644 --- a/src/decode.ts +++ b/src/decode.ts @@ -20,6 +20,7 @@ import { convertIcon, convertTranslation, convertTrack, + convertRemoteDetectionAlert, } from './lib/decode-conversions.js' import cenc from 'compact-encoding' import { DATA_TYPE_ID_BYTES, SCHEMA_VERSION_BYTES } from './constants.js' @@ -80,6 +81,8 @@ export function decode( return convertTranslation(message, versionObj) case 'track': return convertTrack(message, versionObj) + case 'remoteDetectionAlert': + return convertRemoteDetectionAlert(message, versionObj) default: throw new ExhaustivenessError(message) } diff --git a/src/encode.ts b/src/encode.ts index 21d31ba..45ae336 100644 --- a/src/encode.ts +++ b/src/encode.ts @@ -18,6 +18,7 @@ import { convertIcon, convertTranslation, convertTrack, + convertRemoteDetectionAlert, } from './lib/encode-conversions.js' import { ExhaustivenessError } from './lib/utils.js' @@ -86,6 +87,12 @@ export function encode(mapeoDoc: MapeoDocEncode): Buffer { protobuf = Encode[mapeoDoc.schemaName](message).finish() break } + case 'remoteDetectionAlert': { + const message = convertRemoteDetectionAlert(mapeoDoc) + protobuf = Encode[mapeoDoc.schemaName](message).finish() + break + } + default: throw new ExhaustivenessError(mapeoDoc) } diff --git a/src/lib/decode-conversions.ts b/src/lib/decode-conversions.ts index 601d496..4737c59 100644 --- a/src/lib/decode-conversions.ts +++ b/src/lib/decode-conversions.ts @@ -343,6 +343,30 @@ export const convertTrack: ConvertFunction<'track'> = (message, versionObj) => { } } +export const convertRemoteDetectionAlert: ConvertFunction< + 'remoteDetectionAlert' +> = (message, versionObj) => { + const { common, schemaVersion, ...rest } = message + const jsonSchemaCommon = convertCommon(common, versionObj) + if (!rest.detectionDateStart) { + throw new Error('missing required detectionDateStart') + } + if (!rest.detectionDateEnd) { + throw new Error('missing required detectionDateEnd') + } + if (!rest.geometry) { + throw new Error('missing required geometry') + } + return { + ...jsonSchemaCommon, + ...rest, + detectionDateStart: rest.detectionDateStart, + detectionDateEnd: rest.detectionDateEnd, + metadata: convertTags(rest.metadata), + geometry: rest.geometry, + } +} + function convertIconVariant( variant: Icon_1_IconVariant ): Icon['variants'][number] { diff --git a/src/lib/encode-conversions.ts b/src/lib/encode-conversions.ts index def3e42..afbc4bb 100644 --- a/src/lib/encode-conversions.ts +++ b/src/lib/encode-conversions.ts @@ -229,6 +229,17 @@ export const convertTrack: ConvertFunction<'track'> = (mapeoDoc) => { return track } +export const convertRemoteDetectionAlert: ConvertFunction< + 'remoteDetectionAlert' +> = (mapeoDoc) => { + // TODO: should we add a check for sourceId? (so that it complies with the id format we expect?) + return { + common: convertCommon(mapeoDoc), + ...mapeoDoc, + metadata: convertTags(mapeoDoc.metadata), + } +} + function convertCommon( common: SetOptional ): ProtoTypesWithSchemaInfo['common'] { diff --git a/src/types.ts b/src/types.ts index 90b649c..4b0fc2c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -20,6 +20,7 @@ type SupportedSchemaNames = | 'coreOwnership' | 'translation' | 'track' + | 'remoteDetectionAlert' export type SchemaName = Extract export type SchemaNameAll = keyof typeof dataTypeIds diff --git a/test/fixtures/bad-docs.js b/test/fixtures/bad-docs.js index f569371..7f1b4a7 100644 --- a/test/fixtures/bad-docs.js +++ b/test/fixtures/bad-docs.js @@ -139,4 +139,18 @@ export const badDocs = [ color: '#ff00g1', }, }, + { + text: 'remoteDetectionAlert with missing elements', + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.versionId, + schemaName: 'remoteDetectionAlert', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + deleted: false, + sourceId: '', + }, + }, ] diff --git a/test/fixtures/good-docs-completed.js b/test/fixtures/good-docs-completed.js index 0aa08ce..f9d8c99 100644 --- a/test/fixtures/good-docs-completed.js +++ b/test/fixtures/good-docs-completed.js @@ -332,4 +332,25 @@ export const goodDocsCompleted = [ }, expected: {}, }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.originalVersionId, + schemaName: 'remoteDetectionAlert', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + deleted: false, + sourceId: cachedValues.docId, + detectionDateStart: cachedValues.createdAt, + detectionDateEnd: cachedValues.updatedAt, + geometry: { + type: 'Point', + coordinates: [100, 101], + }, + metadata: {}, + }, + expected: {}, + }, ] diff --git a/test/fixtures/good-docs-minimal.js b/test/fixtures/good-docs-minimal.js index cc1de59..a8870f2 100644 --- a/test/fixtures/good-docs-minimal.js +++ b/test/fixtures/good-docs-minimal.js @@ -205,4 +205,54 @@ export const goodDocsMinimal = [ }, expected: {}, }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.originalVersionId, + schemaName: 'remoteDetectionAlert', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + deleted: false, + sourceId: '', + detectionDateStart: cachedValues.createdAt, + detectionDateEnd: cachedValues.updatedAt, + geometry: { + type: 'Point', + coordinates: [100, 101], + }, + metadata: {}, + }, + expected: {}, + }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.originalVersionId, + schemaName: 'remoteDetectionAlert', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + deleted: false, + sourceId: '', + detectionDateStart: cachedValues.createdAt, + detectionDateEnd: cachedValues.updatedAt, + geometry: { + type: 'Polygon', + coordinates: [ + [ + [100.0, 0.0], + [101.0, 0.0], + [101.0, 1.0], + [100.0, 1.0], + [100.0, 0.0], + ], + ], + }, + metadata: {}, + }, + expected: {}, + }, ]