diff --git a/output/hyperschema/index.js b/output/hyperschema/index.js new file mode 100644 index 000000000..2f8291c36 --- /dev/null +++ b/output/hyperschema/index.js @@ -0,0 +1,266 @@ +// This file is autogenerated by the hyperschema compiler +// Schema Version: 1 +/* eslint-disable camelcase */ +/* eslint-disable quotes */ + +const VERSION = 1 +const { c } = require('hyperschema/runtime') + +// eslint-disable-next-line no-unused-vars +let version = VERSION + +// @pear/dht-nodes +const encoding0 = { + preencode (state, m) { + c.string.preencode(state, m.host) + c.int.preencode(state, m.port) + }, + encode (state, m) { + c.string.encode(state, m.host) + c.int.encode(state, m.port) + }, + decode (state) { + const res = {} + res.host = null + res.port = 0 + + res.host = c.string.decode(state) + res.port = c.int.decode(state) + + return res + } +} + +// @pear/encryption-keys +const encoding1 = { + preencode (state, m) { + c.string.preencode(state, m.publicKey) + c.string.preencode(state, m.privateKey) + }, + encode (state, m) { + c.string.encode(state, m.publicKey) + c.string.encode(state, m.privateKey) + }, + decode (state) { + const res = {} + res.publicKey = null + res.privateKey = null + + res.publicKey = c.string.decode(state) + res.privateKey = c.string.decode(state) + + return res + } +} + +// @pear/permits +const encoding2 = { + preencode (state, m) { + c.string.preencode(state, m.z32) + }, + encode (state, m) { + c.string.encode(state, m.z32) + }, + decode (state) { + const res = {} + res.z32 = null + + res.z32 = c.string.decode(state) + + return res + } +} + +// @pear/identity +const encoding3 = { + preencode (state, m) { + let flags = 0 + if (m.privateKey) flags |= 1 + + c.string.preencode(state, m.publicKey) + c.uint.preencode(state, flags) + + if (m.privateKey) c.string.preencode(state, m.privateKey) + }, + encode (state, m) { + let flags = 0 + if (m.privateKey) flags |= 1 + + c.string.encode(state, m.publicKey) + c.uint.encode(state, flags) + + if (m.privateKey) c.string.encode(state, m.privateKey) + }, + decode (state) { + const res = {} + res.publicKey = null + res.privateKey = null + + res.publicKey = c.string.decode(state) + + const flags = state.start < state.end ? c.uint.decode(state) : 0 + if ((flags & 1) !== 0) res.privateKey = c.string.decode(state) + + return res + } +} + +// @pear/apps +const encoding4 = { + preencode (state, m) { + c.string.preencode(state, m.key) + }, + encode (state, m) { + c.string.encode(state, m.key) + }, + decode (state) { + const res = {} + res.key = null + + res.key = c.string.decode(state) + + return res + } +} + +// @pear/apps-owned +const encoding5 = { + preencode (state, m) { + c.string.preencode(state, m.key) + }, + encode (state, m) { + c.string.encode(state, m.key) + }, + decode (state) { + const res = {} + res.key = null + + res.key = c.string.decode(state) + + return res + } +} + +// @pear/app-storage +const encoding6 = { + preencode (state, m) { + c.string.preencode(state, m.app) + }, + encode (state, m) { + c.string.encode(state, m.app) + }, + decode (state) { + const res = {} + res.app = null + + res.app = c.string.decode(state) + + return res + } +} + +// @pear/channels +const encoding7 = { + preencode (state, m) { + c.string.preencode(state, m.key) + }, + encode (state, m) { + c.string.encode(state, m.key) + }, + decode (state) { + const res = {} + res.key = null + + res.key = c.string.decode(state) + + return res + } +} + +// @pear/error-logs +const encoding8 = { + preencode (state, m) { + c.string.preencode(state, m.type) + c.string.preencode(state, m.trace) + }, + encode (state, m) { + c.string.encode(state, m.type) + c.string.encode(state, m.trace) + }, + decode (state) { + const res = {} + res.type = null + res.trace = null + + res.type = c.string.decode(state) + res.trace = c.string.decode(state) + + return res + } +} + +// @pear/perf-stats +const encoding9 = { + preencode (state, m) { + c.int.preencode(state, m.uptimeSeconds) + c.float64.preencode(state, m.ramUsage) + c.float64.preencode(state, m.cpuUsage) + c.string.preencode(state, m.os) + }, + encode (state, m) { + c.int.encode(state, m.uptimeSeconds) + c.float64.encode(state, m.ramUsage) + c.float64.encode(state, m.cpuUsage) + c.string.encode(state, m.os) + }, + decode (state) { + const res = {} + res.uptimeSeconds = 0 + res.ramUsage = 0 + res.cpuUsage = 0 + res.os = null + + res.uptimeSeconds = c.int.decode(state) + res.ramUsage = c.float64.decode(state) + res.cpuUsage = c.float64.decode(state) + res.os = c.string.decode(state) + + return res + } +} + +function getStructByName (name) { + switch (name) { + case '@pear/dht-nodes': return encoding0 + case '@pear/encryption-keys': return encoding1 + case '@pear/permits': return encoding2 + case '@pear/identity': return encoding3 + case '@pear/apps': return encoding4 + case '@pear/apps-owned': return encoding5 + case '@pear/app-storage': return encoding6 + case '@pear/channels': return encoding7 + case '@pear/error-logs': return encoding8 + case '@pear/perf-stats': return encoding9 + default: throw new Error('Encoder not found ' + name) + } +} + +function resolveStruct (name, v = VERSION) { + const enc = getStructByName(name) + return { + preencode (state, m) { + version = v + enc.preencode(state, m) + }, + encode (state, m) { + version = v + enc.encode(state, m) + }, + decode (state) { + version = v + return enc.decode(state) + } + } +} + +module.exports = { resolveStruct, version } diff --git a/output/hyperschema/schema.json b/output/hyperschema/schema.json new file mode 100644 index 000000000..09b98630e --- /dev/null +++ b/output/hyperschema/schema.json @@ -0,0 +1,187 @@ +{ + "version": 1, + "schema": [ + { + "name": "dht-nodes", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "host", + "required": true, + "type": "string", + "version": 1 + }, + { + "name": "port", + "required": true, + "type": "int", + "version": 1 + } + ] + }, + { + "name": "encryption-keys", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "publicKey", + "required": true, + "type": "string", + "version": 1 + }, + { + "name": "privateKey", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "permits", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "z32", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "identity", + "namespace": "pear", + "compact": false, + "flagsPosition": 1, + "fields": [ + { + "name": "publicKey", + "required": true, + "type": "string", + "version": 1 + }, + { + "name": "privateKey", + "required": false, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "apps", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "key", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "apps-owned", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "key", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "app-storage", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "app", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "channels", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "key", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "error-logs", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "type", + "required": true, + "type": "string", + "version": 1 + }, + { + "name": "trace", + "required": true, + "type": "string", + "version": 1 + } + ] + }, + { + "name": "perf-stats", + "namespace": "pear", + "compact": false, + "flagsPosition": -1, + "fields": [ + { + "name": "uptimeSeconds", + "required": true, + "type": "int", + "version": 1 + }, + { + "name": "ramUsage", + "required": true, + "type": "float64", + "version": 1 + }, + { + "name": "cpuUsage", + "required": true, + "type": "float64", + "version": 1 + }, + { + "name": "os", + "required": true, + "type": "string", + "version": 1 + } + ] + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index ba3f35eff..a5647bf8c 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "lint:fix": "standard --fix", "archdump": "node scripts/bootstrap.js --archdump", "prestage": "node scripts/bootstrap.js --archdump --external-corestore && node scripts/prune-dual-prebuilds.mjs", - "bootstrap": "node scripts/bootstrap.js" + "bootstrap": "node scripts/bootstrap.js", + "schema": "bare scripts/schema.js" }, "author": "Holepunch", "pear": { @@ -129,6 +130,7 @@ "graceful-goodbye": "^1.3.0", "hyperbee": "^2.0.1", "hypercore": "^10.36.4", + "hyperschema": "^1.0.3", "newline-decoder": "^1.0.2", "pear-inspect": "^1.2.2", "port-get": "^1.0.4", diff --git a/scripts/schema.js b/scripts/schema.js new file mode 100644 index 000000000..b2e3193a8 --- /dev/null +++ b/scripts/schema.js @@ -0,0 +1,152 @@ +const Hyperschema = require('hyperschema') +const SCHEMA_DIR = './output/hyperschema' + +const schema = Hyperschema.from(SCHEMA_DIR) +const pear = schema.namespace('pear') + +pear.register({ + name: 'dht-nodes', + fields: [ + { + name: 'host', + type: 'string', + required: true + }, + { + name: 'port', + type: 'int', + required: true + } + ] +}) + +pear.register({ + name: 'encryption-keys', + fields: [ + { + name: 'publicKey', + type: 'string', + required: true + }, + { + name: 'privateKey', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'permits', + fields: [ + { + name: 'z32', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'identity', + fields: [ + { + name: 'publicKey', + type: 'string', + required: true + }, + { + name: 'privateKey', + type: 'string', + required: false + } + ] +}) + +pear.register({ + name: 'apps', + fields: [ + { + name: 'key', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'apps-owned', + fields: [ + { + name: 'key', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'app-storage', + fields: [ + { + name: 'app', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'channels', + fields: [ + { + name: 'key', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'error-logs', + fields: [ + { + name: 'type', + type: 'string', + required: true + }, + { + name: 'trace', + type: 'string', + required: true + } + ] +}) + +pear.register({ + name: 'perf-stats', + fields: [ + { + name: 'uptimeSeconds', + type: 'int', + required: true + }, + { + name: 'ramUsage', + type: 'float64', + required: true + }, + { + name: 'cpuUsage', + type: 'float64', + required: true + }, + { + name: 'os', + type: 'string', + required: true + } + ] +}) + +Hyperschema.toDisk(schema) diff --git a/subsystems/sidecar/index.js b/subsystems/sidecar/index.js index ac7f0ac8f..c58474f4a 100644 --- a/subsystems/sidecar/index.js +++ b/subsystems/sidecar/index.js @@ -20,6 +20,7 @@ const { isMac } = require('which-runtime') const { command } = require('paparam') const deriveEncryptionKey = require('pw-to-ek') const reports = require('./lib/reports') +const HyperDB = require('hyperdb') const Store = require('./lib/store') const Applings = require('./lib/applings') const Bundle = require('./lib/bundle') @@ -36,6 +37,7 @@ const { SALT, KNOWN_NODES_LIMIT } = require('../../constants') const { ERR_INTERNAL_ERROR, ERR_PERMISSION_REQUIRED } = require('../../errors') +const db = HyperDB.rocks(path.join(PLATFORM_DIR, 'metrics.db'), require('./output/hyperschema')) const identity = new Store('identity') const encryptionKeys = new Store('encryption-keys') const knownNodes = new Store('dht') @@ -968,6 +970,7 @@ class Sidecar extends ReadyResource { const nodes = this.swarm.dht.toArray({ limit: KNOWN_NODES_LIMIT }) if (nodes.length) { await knownNodes.set('nodes', nodes) + await db.insert('dht-nodes', nodes) LOG.info('sidecar', '- DHT known-nodes wrote to file ' + nodes.length + ' nodes') LOG.trace('sidecar', nodes.map(node => ` - ${node.host}:${node.port}`).join('\n')) }