From 71aa5279dd2c8af0c444efb70bb1112c1cedf2fd Mon Sep 17 00:00:00 2001 From: Evan Hahn Date: Wed, 2 Oct 2024 09:25:16 -0500 Subject: [PATCH] feat: add self-hosted server details to `DeviceInfo` This adds a new object, `selfHostedServerDetails`, to `DeviceInfo`. It currently has one property, `baseUrl`, but could have more later. See [#268]. [#268]: https://github.com/digidem/comapeo-schema/pull/268 --- proto/deviceInfo/v1.proto | 5 ++++ schema/deviceInfo/v1.json | 11 +++++++++ src/lib/encode-conversions.ts | 11 +++++++++ test/fixtures/bad-docs.js | 36 ++++++++++++++++++++++++++++ test/fixtures/good-docs-completed.js | 18 ++++++++++++++ 5 files changed, 81 insertions(+) diff --git a/proto/deviceInfo/v1.proto b/proto/deviceInfo/v1.proto index 900110b..48a902a 100644 --- a/proto/deviceInfo/v1.proto +++ b/proto/deviceInfo/v1.proto @@ -21,6 +21,11 @@ message DeviceInfo_1 { selfHostedServer = 4; } + message SelfHostedServerDetails { + string baseUrl = 1 [(required) = true]; + } + string name = 5; DeviceType deviceType = 6; + optional SelfHostedServerDetails selfHostedServerDetails = 7; } diff --git a/schema/deviceInfo/v1.json b/schema/deviceInfo/v1.json index c591ba6..3ce1d0d 100644 --- a/schema/deviceInfo/v1.json +++ b/schema/deviceInfo/v1.json @@ -23,6 +23,17 @@ "UNRECOGNIZED" ], "description": "Type of device" + }, + "selfHostedServerDetails": { + "type": "object", + "properties": { + "baseUrl": { + "description": "base URL for the server", + "type": "string", + "minLength": 1 + } + }, + "required": ["baseUrl"] } }, "required": ["schemaName", "name", "deviceType"], diff --git a/src/lib/encode-conversions.ts b/src/lib/encode-conversions.ts index 421450b..12d8017 100644 --- a/src/lib/encode-conversions.ts +++ b/src/lib/encode-conversions.ts @@ -122,6 +122,17 @@ export const convertRole: ConvertFunction<'role'> = (mapeoDoc) => { } export const convertDeviceInfo: ConvertFunction<'deviceInfo'> = (mapeoDoc) => { + const { selfHostedServerDetails } = mapeoDoc + if (selfHostedServerDetails) { + try { + new URL(selfHostedServerDetails.baseUrl || '') + } catch (_err) { + throw new Error( + 'deviceInfo.selfHostedServerDetails.baseUrl is not a valid URL' + ) + } + } + return { common: convertCommon(mapeoDoc), ...mapeoDoc, diff --git a/test/fixtures/bad-docs.js b/test/fixtures/bad-docs.js index 7f1b4a7..c8013df 100644 --- a/test/fixtures/bad-docs.js +++ b/test/fixtures/bad-docs.js @@ -97,6 +97,42 @@ export const badDocs = [ deleted: false, }, }, + { + text: 'server without base URL', + /** @type {import('../../dist/index.js').DeviceInfo} */ + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.originalVersionId, + schemaName: 'deviceInfo', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + name: 'my server', + deviceType: 'selfHostedServer', + deleted: false, + selfHostedServerDetails: {}, + }, + }, + { + text: 'server with bogus base URL', + /** @type {import('../../dist/index.js').DeviceInfo} */ + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.originalVersionId, + schemaName: 'deviceInfo', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + name: 'my server', + deviceType: 'selfHostedServer', + deleted: false, + selfHostedServerDetails: { + baseUrl: 'foo', + }, + }, + }, { text: 'icon without name', doc: { diff --git a/test/fixtures/good-docs-completed.js b/test/fixtures/good-docs-completed.js index f9d8c99..7f0c4d7 100644 --- a/test/fixtures/good-docs-completed.js +++ b/test/fixtures/good-docs-completed.js @@ -212,6 +212,24 @@ export const goodDocsCompleted = [ deviceType: 'UNRECOGNIZED', }, }, + { + doc: { + docId: cachedValues.docId, + versionId: cachedValues.versionId, + originalVersionId: cachedValues.originalVersionId, + schemaName: 'deviceInfo', + createdAt: cachedValues.createdAt, + updatedAt: cachedValues.updatedAt, + links: [], + name: 'my server', + deviceType: 'selfHostedServer', + deleted: false, + selfHostedServerDetails: { + baseUrl: 'https://mapeo.example/foo', + }, + }, + expected: {}, + }, { doc: { docId: cachedValues.docId,