diff --git a/src/registry-client.ts b/src/registry-client.ts index ec49994..41c9fa7 100644 --- a/src/registry-client.ts +++ b/src/registry-client.ts @@ -10,15 +10,14 @@ const attributeField = ` attributes { key value { - null - int - float - string - boolean - json - reference { - id - } + ... on BooleanValue { bool: value } + ... on IntValue { int: value } + ... on FloatValue { float: value } + ... on StringValue { string: value } + ... on BytesValue { bytes: value } + ... on LinkValue { link: value } + ... on ArrayValue { array: value { __typename } } + ... on MapValue { map: value { key mapping: value { __typename } } } } } `; @@ -257,9 +256,11 @@ export class RegistryClient { attributes: Util.toGQLAttributes(attributes), all }; + console.debug("[DEBUG] variables", variables); let result = (await this._graph(query)(variables))['queryRecords']; result = RegistryClient.prepareAttributes('attributes')(result); + console.debug("[DEBUG] prepared result", result); return result; } diff --git a/src/sdk.test.ts b/src/sdk.test.ts index b59af12..b366c6b 100644 --- a/src/sdk.test.ts +++ b/src/sdk.test.ts @@ -50,18 +50,18 @@ describe('Querying', () => { expect(records.length).toBeGreaterThanOrEqual(1); const { attributes: { repo_registration_record_cid: record_repo_registration_record_cid } } = records[0]; - expect(repo_registration_record_cid).toBe(record_repo_registration_record_cid); + expect(repo_registration_record_cid).toStrictEqual(record_repo_registration_record_cid); }); test('Query records by attributes.', async () => { - const { version, name } = watcher.record; - const records = await registry.queryRecords({ version, name }, true); + const { version, url } = watcher.record; + const records = await registry.queryRecords({ version, url }, true); expect(records.length).toBe(1); [ watcher ] = records; - const { attributes: { version: recordVersion, name: recordName } } = watcher; + const { attributes: { version: recordVersion, url: recordName } } = watcher; expect(recordVersion).toBe(version); - expect(recordName).toBe(name); + expect(recordName).toBe(url); }); test('Query records by id.', async () => { @@ -75,6 +75,7 @@ describe('Querying', () => { expect(record.id).toBe(watcher.id); // temp fix expect(record.attributes.repo_registration_record_cid).toBeDefined(); - expect(record.attributes.repo_registration_record_cid).toHaveLength(46); + expect(record.attributes.repo_registration_record_cid).toHaveProperty("/"); + expect(record.attributes.repo_registration_record_cid["/"]).toHaveLength(46); }); }); diff --git a/src/testing/data/watcher.yml b/src/testing/data/watcher.yml index c1900b5..d9deb11 100644 --- a/src/testing/data/watcher.yml +++ b/src/testing/data/watcher.yml @@ -1,7 +1,10 @@ record: type: WebsiteRegistrationRecord url: 'https://cerc.io' - repo_registration_record_cid: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D - build_artifact_cid: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9 - tls_cert_cid: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR + repo_registration_record_cid: + /: QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D + build_artifact_cid: + /: QmP8jTG1m9GSDJLCbeWhVSVgEzCPPwXRdCRuJtQ5Tz9Kc9 + tls_cert_cid: + /: QmbWqxBEKC3P8tqsKc98xmWNzrzDtRLMiMPL8wBuTGsMnR version: 1.0.23 diff --git a/src/util.ts b/src/util.ts index e69a78d..d42b057 100644 --- a/src/util.ts +++ b/src/util.ts @@ -10,21 +10,21 @@ export class Util { /** * Sorts JSON object. */ - static sortJSON(object: any) { - if (object instanceof Array) { - for (let i = 0; i < object.length; i++) { - object[i] = Util.sortJSON(object[i]); + static sortJSON(obj: any) { + if (obj instanceof Array) { + for (let i = 0; i < obj.length; i++) { + obj[i] = Util.sortJSON(obj[i]); } - return object; + return obj; } - if (typeof object !== 'object' || object === null) return object; + if (typeof obj !== 'object' || obj === null) return obj; - let keys = Object.keys(object); + let keys = Object.keys(obj); keys = keys.sort(); const newObject: {[key: string]: any} = {}; for (let i = 0; i < keys.length; i++) { - newObject[keys[i]] = Util.sortJSON(object[keys[i]]); + newObject[keys[i]] = Util.sortJSON(obj[keys[i]]); } return newObject; } @@ -32,31 +32,41 @@ export class Util { /** * Marshal object into gql 'attributes' variable. */ - static toGQLAttributes(object: any) { + static toGQLAttributes(obj: any) { + console.log("[DEBUG] toGQLAttributes", obj); const vars: any[] = []; - - Object.keys(object).forEach(key => { - let type: string = typeof object[key]; - if (object[key] === null) { - vars.push({ key, value: { 'null': true } }); - } else if (type === 'number') { - type = (object[key] % 1 === 0) ? 'int' : 'float'; - vars.push({ key, value: { [type]: object[key] } }); - } else if (type === 'string') { - vars.push({ key, value: { 'string': object[key] } }); - } else if (type === 'boolean') { - vars.push({ key, value: { 'boolean': object[key] } }); - } else if (type === 'object') { - const nestedObject = object[key]; - if (nestedObject['/'] !== undefined) { - vars.push({ key, value: { 'reference': { id: nestedObject['/'] } } }); - } - } + Object.keys(obj).forEach(key => { + vars.push({ key, value: this.toGQLValue(obj[key]) }); }); - return vars; } + static toGQLValue(obj: any) { + if (obj === null) { + return null; + } + let type: string = typeof obj; + switch (type) { + case 'number': + type = (obj % 1 === 0) ? 'int' : 'float'; + return { [type]: obj }; + case 'string': + return { 'string': obj }; + case 'boolean': + return { 'boolean': obj }; + case 'object': + if (obj['/'] !== undefined) { + return { 'link': obj['/'] }; + } + if (obj instanceof Array) { + return { 'array': obj }; + } + return { 'map': obj }; + default: + throw new Error(`Unknown object type '${type}': ${obj}`); + } + } + /** * Unmarshal attributes array to object. */ @@ -64,24 +74,20 @@ export class Util { const res: {[key: string]: any} = {}; attributes.forEach(attr => { - if (attr.value.null) { - res[attr.key] = null; - } else if (attr.value.json) { - res[attr.key] = JSON.parse(attr.value.json); - } else if (attr.value.reference) { - // Convert GQL reference to IPLD style link. - const ref = attr.value.reference; - res[attr.key] = { '/': ref.id }; - } else { - const { values, null: n, ...types } = attr.value; - const value = Object.values(types).find(v => v !== null); - res[attr.key] = value; - } + res[attr.key] = this.fromGQLValue(attr.value); }); return res; } + static fromGQLValue(obj: any) { + const present = Object.keys(obj).find(k => obj[k] !== null); + if (present === undefined) { + throw new Error('Object has no non-null values'); + } + return obj[present]; + } + /** * Get record content ID. */