From 2f91a3947e1cd392931f0605eb9f2d72de450698 Mon Sep 17 00:00:00 2001 From: Matthew Brisebois Date: Wed, 11 Sep 2024 17:21:29 -0600 Subject: [PATCH] Implement download zome package --- dnas/zomehub/sdk/src/lib.rs | 5 ++++ dnas/zomehub/types/src/zome_package_entry.rs | 1 + .../types/src/zome_package_version_entry.rs | 13 +++++++++ dnas/zomehub/zomelets/src/index.js | 25 +++++++++++++++++ dnas/zomehub/zomelets/src/types.js | 8 ++++++ .../zomehub/zome_package_versions_suite.js | 27 ++++++++++++++++++- .../zomehub/zome_packages_suite.js | 15 +++++++++-- zomes/zomehub/src/lib.rs | 4 +++ .../zomehub_csr/src/zome_package_handlers.rs | 19 +++++++++++++ 9 files changed, 114 insertions(+), 3 deletions(-) diff --git a/dnas/zomehub/sdk/src/lib.rs b/dnas/zomehub/sdk/src/lib.rs index 08d2137..95df1a6 100644 --- a/dnas/zomehub/sdk/src/lib.rs +++ b/dnas/zomehub/sdk/src/lib.rs @@ -16,6 +16,7 @@ use zomehub_types::{ ZomeEntry, ZomePackageEntry, ZomePackageVersionEntry, + ApiCompatibility, mere_memory_types, }; @@ -76,6 +77,7 @@ impl TryInto for EntryHash { #[derive(Serialize, Deserialize, Clone, Debug)] pub struct CreateZomePackageInput { pub name: String, + pub title: String, pub description: String, pub zome_type: ZomeType, @@ -95,6 +97,7 @@ impl TryFrom for ZomePackageEntry { Ok( Self { name: input.name, + title: input.title, description: input.description, zome_type: input.zome_type, maintainer: input.maintainer @@ -118,6 +121,7 @@ pub struct CreateZomePackageVersionInput { // optional pub changelog: Option, pub source_code_revision_uri: Option, + pub api_compatibility: ApiCompatibility, // Common fields #[serde(default)] @@ -135,6 +139,7 @@ impl TryFrom for ZomePackageVersionEntry { changelog: input.changelog, source_code_revision_uri: input.source_code_revision_uri, + api_compatibility: input.api_compatibility, metadata: input.metadata, } ) diff --git a/dnas/zomehub/types/src/zome_package_entry.rs b/dnas/zomehub/types/src/zome_package_entry.rs index 01cf5ab..acd1bd4 100644 --- a/dnas/zomehub/types/src/zome_package_entry.rs +++ b/dnas/zomehub/types/src/zome_package_entry.rs @@ -15,6 +15,7 @@ use hdi::prelude::*; #[derive(Clone)] pub struct ZomePackageEntry { pub name: String, + pub title: String, pub description: String, pub zome_type: ZomeType, pub maintainer: Authority, diff --git a/dnas/zomehub/types/src/zome_package_version_entry.rs b/dnas/zomehub/types/src/zome_package_version_entry.rs index ed2ff61..62e6bd5 100644 --- a/dnas/zomehub/types/src/zome_package_version_entry.rs +++ b/dnas/zomehub/types/src/zome_package_version_entry.rs @@ -7,6 +7,18 @@ use std::collections::BTreeMap; use hdi::prelude::*; +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +pub struct ApiCompatibilityBuiltWith { + pub hdi_version: String, + pub hdk_version: Option, // Only required for coordinator zomes +} + +#[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] +pub struct ApiCompatibility { + pub build_with: ApiCompatibilityBuiltWith, + pub tested_with: String, +} + // // Zome Package Version Entry @@ -20,6 +32,7 @@ pub struct ZomePackageVersionEntry { // Optional pub changelog: Option, pub source_code_revision_uri: Option, + pub api_compatibility: ApiCompatibility, // Common fields pub metadata: BTreeMap, diff --git a/dnas/zomehub/zomelets/src/index.js b/dnas/zomehub/zomelets/src/index.js index 4c47cb3..5eab51c 100644 --- a/dnas/zomehub/zomelets/src/index.js +++ b/dnas/zomehub/zomelets/src/index.js @@ -118,6 +118,11 @@ export const ZomeHubCSRZomelet = new Zomelet({ return new ZomePackage( result, this ); }, + async get_zome_package_by_name ( input ) { + const result = await this.call( input ); + + return new ZomePackage( result, this ); + }, async get_zome_package_entry ( input ) { const result = await this.call( new AnyDhtHash( input ) ); @@ -218,6 +223,14 @@ export const ZomeHubCSRZomelet = new Zomelet({ // // Virtual functions // + async form_zome_entry ( bytes ) { + return { + "zome_type": ZOME_TYPES.INTEGRITY, + "mere_memory_addr": new EntryHash( input.mere_memory_addr ), + "file_size": bytes.length, + "hash": await this.zomes.mere_memory_api.calculate_hash( bytes ), + }; + }, async save_integrity ( bytes ) { const addr = await this.zomes.mere_memory_api.save( bytes ); @@ -260,6 +273,18 @@ export const ZomeHubCSRZomelet = new Zomelet({ return versions; }, + async download_zome_package ( input ) { + const zome_package = await this.functions.get_zome_package_by_name( input ); + const versions = await this.functions.get_zome_package_versions_sorted( zome_package.$id ); + const latest_version = versions[0]; + const zome = await this.functions.get_zome( latest_version.zome_entry ); + + return [ + zome_package, + latest_version, + zome, + ]; + }, }, { "zomes": { "mere_memory_api": MereMemoryZomelet, diff --git a/dnas/zomehub/zomelets/src/types.js b/dnas/zomehub/zomelets/src/types.js index 71be77e..763c5d8 100644 --- a/dnas/zomehub/zomelets/src/types.js +++ b/dnas/zomehub/zomelets/src/types.js @@ -55,6 +55,7 @@ export const MaintainerType = String; export const ZomePackageStruct = { "name": String, + "title": String, "description": String, "zome_type": String, "maintainer": { @@ -131,6 +132,13 @@ export const ZomePackageVersionStruct = { "zome_entry": EntryHash, "changelog": OptionType( String ), "source_code_revision_uri": OptionType( String ), + "api_compatibility": { + "build_with": { + "hdi_version": String, + "hdk_version": OptionType( String ), + }, + "tested_with": String, + }, "metadata": Object, }; diff --git a/tests/integration/zomehub/zome_package_versions_suite.js b/tests/integration/zomehub/zome_package_versions_suite.js index 29851be..f3106da 100644 --- a/tests/integration/zomehub/zome_package_versions_suite.js +++ b/tests/integration/zomehub/zome_package_versions_suite.js @@ -26,6 +26,7 @@ export default function ( args_fn ) { let pack1; let pack1_v1; + let pack1_name; before(async function () { ({ @@ -38,8 +39,12 @@ export default function ( args_fn ) { zome1, } = args_fn()); + const title = faker.commerce.productName(); + pack1_name = title.toLowerCase(/\s/g, '-'); + pack1 = await zomehub_csr.create_zome_package({ - "name": faker.commerce.productName(), + "name": pack1_name, + title, "description": faker.lorem.paragraphs( 2 ), "zome_type": "integrity", }); @@ -51,6 +56,13 @@ export default function ( args_fn ) { "for_package": pack1.$id, "zome_entry": zome1_addr, "source_code_revision_uri": faker.internet.url(), + "api_compatibility": { + "build_with": { + "hdi_version": faker.system.semver(), + "hdk_version": faker.system.semver(), + }, + "tested_with": faker.system.semver(), + }, }); log.normal("Create Zome package version: %s", json.debug(pack1_v1) ); @@ -70,6 +82,13 @@ export default function ( args_fn ) { "for_package": pack1.$id, "zome_entry": zome1_addr, "source_code_revision_uri": faker.internet.url(), + "api_compatibility": { + "build_with": { + "hdi_version": faker.system.semver(), + "hdk_version": null, + }, + "tested_with": faker.system.semver(), + }, }); } @@ -101,6 +120,12 @@ export default function ( args_fn ) { log.normal("Version links: %s", json.debug(version_links) ); }); + it("should download latest version", async function () { + const latest_version = await zomehub_csr.download_zome_package( pack1_name ); + + log.normal("Latest package version: %s", json.debug(latest_version) ); + }); + linearSuite("Errors", function () { }); diff --git a/tests/integration/zomehub/zome_packages_suite.js b/tests/integration/zomehub/zome_packages_suite.js index bf8b6f2..86ecfc8 100644 --- a/tests/integration/zomehub/zome_packages_suite.js +++ b/tests/integration/zomehub/zome_packages_suite.js @@ -24,7 +24,8 @@ export default function ( args_fn ) { let zomehub_csr; let zome1_addr, zome1; - let pack1; + let pack1 + let pack1_name; before(async function () { ({ @@ -39,8 +40,12 @@ export default function ( args_fn ) { }); it("should create Zome Package entry", async function () { + const title = faker.commerce.productName(); + pack1_name = title.toLowerCase(/\s/g, '-'); + pack1 = await zomehub_csr.create_zome_package({ - "name": faker.commerce.productName(), + "name": pack1_name, + title, "description": faker.lorem.paragraphs( 2 ), "zome_type": "integrity", }); @@ -67,6 +72,12 @@ export default function ( args_fn ) { expect( package_list ).to.have.length( 1 ); }); + it("should get Zome Package by name", async function () { + const zome_package = await zomehub_csr.get_zome_package_by_name( pack1_name ); + + log.normal("Get Zome package: %s", json.debug(zome_package) ); + }); + linearSuite("Errors", function () { }); diff --git a/zomes/zomehub/src/lib.rs b/zomes/zomehub/src/lib.rs index 4d1e740..e590f81 100644 --- a/zomes/zomehub/src/lib.rs +++ b/zomes/zomehub/src/lib.rs @@ -58,6 +58,8 @@ pub enum LinkTypes { AgentToZomePackage, AgentToZomePackageVersion, + NameToZomePackage, + ZomePackageToZomePackageVersion, } @@ -71,6 +73,8 @@ impl TryFrom for LinkTypes { "AgentToZomePackage" => LinkTypes::AgentToZomePackage, "AgentToZomePackageVersion" => LinkTypes::AgentToZomePackageVersion, + "NameToZomePackage" => LinkTypes::NameToZomePackage, + "ZomePackageToZomePackageVersion" => LinkTypes::ZomePackageToZomePackageVersion, _ => return Err(guest_error!(format!("Unknown LinkTypes variant: {}", name ))), diff --git a/zomes/zomehub_csr/src/zome_package_handlers.rs b/zomes/zomehub_csr/src/zome_package_handlers.rs index 971ff5b..0bd81f0 100644 --- a/zomes/zomehub_csr/src/zome_package_handlers.rs +++ b/zomes/zomehub_csr/src/zome_package_handlers.rs @@ -7,7 +7,9 @@ use hdk::prelude::*; use hdk_extensions::{ must_get, hdi_extensions::{ + guest_error, ScopedTypeConnector, + AnyLinkableHashTransformer, }, }; use zomehub::{ @@ -34,6 +36,9 @@ fn create_zome_package_entry(input: ZomePackageEntry) -> ExternResult ExternResult } +#[hdk_extern] +pub fn get_zome_package_by_name(name: String) -> ExternResult> { + let anchor_path = Path::from( vec![ Component::from(name.as_bytes().to_vec()) ] ).path_entry_hash()?; + let name_anchor = LinkBase::new( anchor_path, LinkTypes::NameToZomePackage ); + let package_link = name_anchor.get_links( None )?.first() + .ok_or(guest_error!(format!( + "No package found for name '{}'", + name + )))?.to_owned(); + + Ok( get_entity( &package_link.target.must_be_action_hash()? )? ) +} + + #[hdk_extern] fn get_zome_packages_for_agent(maybe_agent_id: Option) -> ExternResult>>