Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Unit read API for loading by symbol rather than fully-qualified record UUID #387

Open
wants to merge 4 commits into
base: sprout
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 20 additions & 3 deletions modules/vf-graphql-holochain/queries/unit.ts
Expand Up @@ -5,21 +5,38 @@
* @since: 2019-09-12
*/

import { DNAIdMappings, ReadParams } from '../types.js'
import { DNAIdMappings, ById } from '../types.js'
import { mapZomeFn } from '../connection.js'

import {
Unit, UnitConnection, UnitResponse,
} from '@valueflows/vf-graphql'
import { PagingParams } from '../resolvers/zomeSearchInputTypes.js'

export interface BySymbol {
symbol: string,
}

export default (dnaConfig: DNAIdMappings, conductorUri: string) => {
const readOne = mapZomeFn<ReadParams, UnitResponse>(dnaConfig, conductorUri, 'specification', 'unit', 'get_unit')
const readOne = mapZomeFn<ById, UnitResponse>(dnaConfig, conductorUri, 'specification', 'unit', 'get_unit')
const readOneBySymbol = mapZomeFn<BySymbol, UnitResponse>(dnaConfig, conductorUri, 'specification', 'unit', 'get_unit_by_symbol')
const readAll = mapZomeFn<PagingParams, UnitConnection>(dnaConfig, conductorUri, 'specification', 'unit_index', 'read_all_units')

return {
unit: async (root, args): Promise<Unit> => {
return (await readOne(args)).unit
let res
try {
res = await readOne(args)
} catch (e) {
try {
// attempt GUID-based read of Unit based on symbol
res = await readOneBySymbol(args)
} catch (_retried) {
// throw original (UUID-based) read error if both fail
throw e
}
}
return res.unit
},
units: async (root, args: PagingParams): Promise<UnitConnection> => {
return await readAll(args)
Expand Down
21 changes: 20 additions & 1 deletion test/specification/test_unit_crud.js
Expand Up @@ -29,12 +29,14 @@ test('Unit record API', async (t) => {
unit {
id
revisionId
symbol
}
}
res2: createUnit(unit: $rs2) {
unit {
id
revisionId
symbol
}
}
}
Expand All @@ -47,6 +49,7 @@ test('Unit record API', async (t) => {
t.ok(createResp.data.res.unit.id, 'record created')
t.equal(createResp.data.res.unit.id.split(':')[0], exampleEntry.symbol, 'record index set')
let uId = createResp.data.res.unit.id
let uSymbol = createResp.data.res.unit.symbol
let u2Id = createResp.data.res2.unit.id
let uRevision = createResp.data.res.unit.revisionId
const getResp = await alice.graphQL(`
Expand All @@ -62,7 +65,23 @@ test('Unit record API', async (t) => {
id: uId,
})

t.deepLooseEqual(getResp.data.res, { 'id': uId, revisionId: uRevision, ...exampleEntry }, 'record read OK')
const expectedRecord = { 'id': uId, revisionId: uRevision, ...exampleEntry }

t.deepLooseEqual(getResp.data.res, expectedRecord, 'record read OK')

const getSResp = await alice.graphQL(`
query($id: ID!) {
res: unit(id: $id) {
id
revisionId
label
symbol
}
}
`, {
id: uSymbol,
})
t.deepLooseEqual(getSResp.data.res, expectedRecord, 'record read by (globally-unique, not universally-unique) symbol OK')


const queryAllUnits = await alice.graphQL(`
Expand Down
11 changes: 11 additions & 0 deletions zomes/rea_unit/lib/src/lib.rs
Expand Up @@ -61,6 +61,17 @@ pub fn handle_get_unit(id: UnitId) -> RecordAPIResult<ResponseData>
construct_response(&entry_id, &meta, &entry)
}

pub fn handle_get_unit_by_symbol<S>(symbol: S) -> RecordAPIResult<ResponseData>
where S: AsRef<str> + std::fmt::Display,
{
let (meta, entry_id, entry): (_,UnitId,_) =
read_anchored_record_entry::<LinkTypes, EntryData, EntryStorage, UnitInternalAddress, _,_>(
LinkTypes::UnitIdentifier,
symbol.as_ref(),
)?;
construct_response(&entry_id, &meta, &entry)
}

// internal method used by index zomes to locate indexed unit record data
pub fn handle_get_unit_by_address(address: UnitInternalAddress) -> RecordAPIResult<ResponseData>
{
Expand Down
10 changes: 10 additions & 0 deletions zomes/rea_unit/zome/src/lib.rs
Expand Up @@ -34,6 +34,16 @@ fn get_unit(ById { id }: ById) -> ExternResult<ResponseData> {
Ok(handle_get_unit(id)?)
}

#[derive(Debug, Serialize, Deserialize)]
struct BySymbol {
symbol: String,
}

#[hdk_extern]
fn get_unit_by_symbol(BySymbol { symbol }: BySymbol) -> ExternResult<ResponseData> {
Ok(handle_get_unit_by_symbol(symbol)?)
}

// used by indexing zomes to retrieve indexed record data
#[hdk_extern]
fn __internal_get_unit_by_hash(ByAddress { address }: ByAddress<UnitInternalAddress>) -> ExternResult<ResponseData> {
Expand Down