diff --git a/backend/main/PackagePublisher.mo b/backend/main/PackagePublisher.mo index aa57e09d..778fccd8 100644 --- a/backend/main/PackagePublisher.mo +++ b/backend/main/PackagePublisher.mo @@ -66,20 +66,19 @@ module { }; }; + let isNewPackage = registry.getHighestVersion(config.name) == null; + // check permissions - switch (registry.getPackageOwner(config.name)) { - case (null) { - // deny '.' and '_' in name for new packages - for (char in config.name.chars()) { - let err = #err("invalid config: unexpected char '" # Char.toText(char) # "' in name '" # config.name # "'"); - if (char == '.' or char == '_') { - return err; - }; - }; - }; - case (?owner) { - if (owner != caller) { - return #err("You don't have permissions to publish this package"); + if (not isNewPackage and not registry.isOwner(config.name, caller) and not registry.isMaintainer(config.name, caller)) { + return #err("Only owners and maintainers can publish packages"); + }; + + // deny '.' and '_' in name for new packages + if (isNewPackage) { + for (char in config.name.chars()) { + let err = #err("invalid config: unexpected char '" # Char.toText(char) # "' in name '" # config.name # "'"); + if (char == '.' or char == '_') { + return err; }; }; }; @@ -103,7 +102,7 @@ module { if (dep.repo.size() == 0 and registry.getPackageConfig(PackageUtils.getDepName(dep.name), dep.version) == null) { return #err("Dependency " # packageId # " not found in registry"); }; - if (dep.repo.size() != 0 and registry.getPackageOwner(PackageUtils.getDepName(dep.name)) != null) { + if (dep.repo.size() != 0 and registry.getHighestVersion(PackageUtils.getDepName(dep.name)) != null) { return #err("GitHub dependency `" # dep.name # "` conflicts with an existing package in the Mops registry. Please change the dependency name in mops.toml file."); }; }; diff --git a/backend/main/main-canister.mo b/backend/main/main-canister.mo index 24504d11..d2daa494 100644 --- a/backend/main/main-canister.mo +++ b/backend/main/main-canister.mo @@ -62,7 +62,9 @@ actor class Main() { let API_VERSION = "1.3"; // (!) make changes in pair with cli var packageVersions = TrieMap.TrieMap(Text.equal, Text.hash); - var packageOwners = TrieMap.TrieMap(Text.equal, Text.hash); + var packageOwners = TrieMap.TrieMap(Text.equal, Text.hash); // legacy + var ownersByPackage = TrieMap.TrieMap(Text.equal, Text.hash); + var maintainersByPackage = TrieMap.TrieMap(Text.equal, Text.hash); var highestConfigs = TrieMap.TrieMap(Text.equal, Text.hash); var packageConfigs = TrieMap.TrieMap(Text.equal, Text.hash); @@ -76,7 +78,8 @@ actor class Main() { var registry = Registry.Registry( packageVersions, - packageOwners, + ownersByPackage, + maintainersByPackage, highestConfigs, packageConfigs, packagePublications, @@ -489,8 +492,28 @@ actor class Main() { users.setUserProp(caller, prop, value); }; - public shared ({caller}) func transferOwnership(packageName : PackageName, newOwner : Principal) : async Result.Result<(), Text> { - registry.transferOwnership(caller, packageName, newOwner); + public query func getPackageOwners(packageName : PackageName) : async [Principal] { + registry.getPackageOwners(packageName); + }; + + public query func getPackageMaintainers(packageName : PackageName) : async [Principal] { + registry.getPackageMaintainers(packageName); + }; + + public shared ({caller}) func addOwner(packageName : PackageName, newOwner : Principal) : async Result.Result<(), Text> { + registry.addOwner(caller, packageName, newOwner); + }; + + public shared ({caller}) func addMaintainer(packageName : PackageName, newMaintainer : Principal) : async Result.Result<(), Text> { + registry.addMaintainer(caller, packageName, newMaintainer); + }; + + public shared ({caller}) func removeOwner(packageName : PackageName, owner : Principal) : async Result.Result<(), Text> { + registry.removeOwner(caller, packageName, owner); + }; + + public shared ({caller}) func removeMaintainer(packageName : PackageName, maintainer : Principal) : async Result.Result<(), Text> { + registry.removeMaintainer(caller, packageName, maintainer); }; // BADGES @@ -526,10 +549,11 @@ actor class Main() { let backupManager = Backup.BackupManager(backupStateV2, {maxBackups = 20}); type BackupChunk = { - #v7 : { + #v8 : { #packagePublications : [(PackageId, PackagePublication)]; #packageVersions : [(PackageName, [PackageVersion])]; - #packageOwners : [(PackageName, Principal)]; + #ownersByPackage : [(PackageName, [Principal])]; + #maintainersByPackage : [(PackageName, [Principal])]; #packageConfigs : [(PackageId, PackageConfigV3)]; #highestConfigs : [(PackageName, PackageConfigV3)]; #fileIdsByPackage : [(PackageId, [FileId])]; @@ -555,22 +579,23 @@ actor class Main() { }; func _backup() : async () { - let backup = backupManager.NewBackup("v7"); + let backup = backupManager.NewBackup("v8"); await backup.startBackup(); - await backup.uploadChunk(to_candid(#v7(#packagePublications(Iter.toArray(packagePublications.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageVersions(Iter.toArray(packageVersions.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageOwners(Iter.toArray(packageOwners.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#fileIdsByPackage(Iter.toArray(fileIdsByPackage.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#hashByFileId(Iter.toArray(hashByFileId.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageFileStats(Iter.toArray(packageFileStats.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageTestStats(Iter.toArray(packageTestStats.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageBenchmarks(Iter.toArray(packageBenchmarks.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageNotes(Iter.toArray(packageNotes.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#downloadLog(downloadLog.toStable())) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#storageManager(storageManager.toStable())) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#users(users.toStable())) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#highestConfigs(Iter.toArray(highestConfigs.entries()))) : BackupChunk)); - await backup.uploadChunk(to_candid(#v7(#packageConfigs(Iter.toArray(packageConfigs.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packagePublications(Iter.toArray(packagePublications.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packageVersions(Iter.toArray(packageVersions.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#ownersByPackage(Iter.toArray(ownersByPackage.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#maintainersByPackage(Iter.toArray(maintainersByPackage.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#fileIdsByPackage(Iter.toArray(fileIdsByPackage.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#hashByFileId(Iter.toArray(hashByFileId.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packageFileStats(Iter.toArray(packageFileStats.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packageTestStats(Iter.toArray(packageTestStats.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packageBenchmarks(Iter.toArray(packageBenchmarks.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packageNotes(Iter.toArray(packageNotes.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#downloadLog(downloadLog.toStable())) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#storageManager(storageManager.toStable())) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#users(users.toStable())) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#highestConfigs(Iter.toArray(highestConfigs.entries()))) : BackupChunk)); + await backup.uploadChunk(to_candid(#v8(#packageConfigs(Iter.toArray(packageConfigs.entries()))) : BackupChunk)); await backup.finishBackup(); }; @@ -580,7 +605,7 @@ actor class Main() { assert(Utils.isAdmin(caller)); await backupManager.restore(backupId, func(blob : Blob) { - let ?#v7(chunk) : ?BackupChunk = from_candid(blob) else Debug.trap("Failed to restore chunk"); + let ?#v8(chunk) : ?BackupChunk = from_candid(blob) else Debug.trap("Failed to restore chunk"); switch (chunk) { case (#packagePublications(packagePublicationsStable)) { @@ -589,8 +614,11 @@ actor class Main() { case (#packageVersions(packageVersionsStable)) { packageVersions := TrieMap.fromEntries(packageVersionsStable.vals(), Text.equal, Text.hash); }; - case (#packageOwners(packageOwnersStable)) { - packageOwners := TrieMap.fromEntries(packageOwnersStable.vals(), Text.equal, Text.hash); + case (#ownersByPackage(ownersByPackageStable)) { + ownersByPackage := TrieMap.fromEntries(ownersByPackageStable.vals(), Text.equal, Text.hash); + }; + case (#maintainersByPackage(maintainersByPackageStable)) { + maintainersByPackage := TrieMap.fromEntries(maintainersByPackageStable.vals(), Text.equal, Text.hash); }; case (#fileIdsByPackage(fileIdsByPackageStable)) { fileIdsByPackage := TrieMap.fromEntries(fileIdsByPackageStable.vals(), Text.equal, Text.hash); @@ -634,7 +662,8 @@ actor class Main() { // re-init registry registry := Registry.Registry( packageVersions, - packageOwners, + ownersByPackage, + maintainersByPackage, highestConfigs, packageConfigs, packagePublications, @@ -652,6 +681,8 @@ actor class Main() { stable var packagePublicationsStable : [(PackageId, PackagePublication)] = []; stable var packageVersionsStable : [(PackageName, [PackageVersion])] = []; stable var packageOwnersStable : [(PackageName, Principal)] = []; + stable var ownersByPackageStable : [(PackageName, [Principal])] = []; + stable var maintainersByPackageStable : [(PackageName, [Principal])] = []; stable var packageConfigsStableV3 : [(PackageId, PackageConfigV3)] = []; stable var highestConfigsStableV3 : [(PackageName, PackageConfigV3)] = []; @@ -671,6 +702,8 @@ actor class Main() { packagePublicationsStable := Iter.toArray(packagePublications.entries()); packageVersionsStable := Iter.toArray(packageVersions.entries()); packageOwnersStable := Iter.toArray(packageOwners.entries()); + ownersByPackageStable := Iter.toArray(ownersByPackage.entries()); + maintainersByPackageStable := Iter.toArray(maintainersByPackage.entries()); fileIdsByPackageStable := Iter.toArray(fileIdsByPackage.entries()); hashByFileIdStable := Iter.toArray(hashByFileId.entries()); packageFileStatsStable := Iter.toArray(packageFileStats.entries()); @@ -698,6 +731,21 @@ actor class Main() { packageVersions := TrieMap.fromEntries(packageVersionsStable.vals(), Text.equal, Text.hash); packageVersionsStable := []; + // migrate packageOwners -> ownersByPackage + if (ownersByPackageStable.size() == 0) { + ownersByPackage := + packageOwnersStable.vals() + |> Iter.map<(PackageName, Principal), (PackageName, [Principal])>(_, func((name, owner)) = (name, [owner])) + |> TrieMap.fromEntries(_, Text.equal, Text.hash); + } + else { + ownersByPackage := TrieMap.fromEntries(ownersByPackageStable.vals(), Text.equal, Text.hash); + ownersByPackageStable := []; + }; + + maintainersByPackage := TrieMap.fromEntries(maintainersByPackageStable.vals(), Text.equal, Text.hash); + maintainersByPackageStable := []; + packageOwners := TrieMap.fromEntries(packageOwnersStable.vals(), Text.equal, Text.hash); packageOwnersStable := []; @@ -732,7 +780,8 @@ actor class Main() { registry := Registry.Registry( packageVersions, - packageOwners, + ownersByPackage, + maintainersByPackage, highestConfigs, packageConfigs, packagePublications, diff --git a/backend/main/registry/Registry.mo b/backend/main/registry/Registry.mo index 3e08a3a0..50c58d34 100644 --- a/backend/main/registry/Registry.mo +++ b/backend/main/registry/Registry.mo @@ -4,6 +4,7 @@ import Option "mo:base/Option"; import Array "mo:base/Array"; import Time "mo:base/Time"; import Result "mo:base/Result"; +import Principal "mo:base/Principal"; import Types "../types"; import Semver "../utils/semver"; @@ -34,7 +35,8 @@ module { public class Registry( packageVersions : TrieMap.TrieMap, - packageOwners : TrieMap.TrieMap, + ownersByPackage : TrieMap.TrieMap, + maintainersByPackage : TrieMap.TrieMap, highestConfigs : TrieMap.TrieMap, packageConfigs : TrieMap.TrieMap, packagePublications : TrieMap.TrieMap, @@ -59,7 +61,13 @@ module { packageVersions.put(newRelease.config.name, Array.append(versions, [newRelease.config.version])); packageConfigs.put(packageId, newRelease.config); - packageOwners.put(newRelease.config.name, newRelease.userId); + + // add owner for new package + let owners = getPackageOwners(newRelease.config.name); + if (owners.size() == 0) { + ownersByPackage.put(newRelease.config.name, [newRelease.userId]); + }; + packagePublications.put(packageId, { user = newRelease.userId; time = Time.now(); @@ -119,10 +127,6 @@ module { // By package name // ----------------------------- - public func getPackageOwner(name : PackageName) : ?Principal { - packageOwners.get(name); - }; - public func getPackageVersions(name : PackageName) : ?[PackageVersion] { packageVersions.get(name); }; @@ -169,17 +173,98 @@ module { // Package ownership // ----------------------------- - public func transferOwnership(caller : Principal, packageName : PackageName, newOwner : Principal) : Result.Result<(), Text> { - let ?oldOwner = packageOwners.get(packageName) else return #err("Package not found"); + public func getPackageOwners(name : PackageName) : [Principal] { + Option.get(ownersByPackage.get(name), []); + }; + + public func getPackageMaintainers(name : PackageName) : [Principal] { + Option.get(maintainersByPackage.get(name), []); + }; + + public func isOwner(name : PackageName, principal : Principal) : Bool { + for (owner in getPackageOwners(name).vals()) { + if (owner == principal) { + return true; + }; + }; + return false; + }; + + public func isMaintainer(name : PackageName, principal : Principal) : Bool { + for (maintainer in getPackageMaintainers(name).vals()) { + if (maintainer == principal) { + return true; + }; + }; + return false; + }; + + public func addOwner(caller : Principal, packageName : PackageName, newOwner : Principal) : Result.Result<(), Text> { + let ?owners = ownersByPackage.get(packageName) else return #err("Package not found"); + + if (isOwner(packageName, newOwner)) { + return #err("User is already an owner"); + }; + if (not isOwner(packageName, caller)) { + return #err("Only owners can add owners"); + }; + if (owners.size() >= 5) { + return #err("Maximum number of owners reached"); + }; + + ownersByPackage.put(packageName, Array.append(owners, [newOwner])); + #ok; + }; + + public func addMaintainer(caller : Principal, packageName : PackageName, newMaintainer : Principal) : Result.Result<(), Text> { + let maintainers = Option.get(maintainersByPackage.get(packageName), []); + + if (isMaintainer(packageName, newMaintainer)) { + return #err("User is already a maintainer"); + }; + if (not isOwner(packageName, caller)) { + return #err("Only owners can add maintainers"); + }; + if (maintainers.size() >= 5) { + return #err("Maximum number of maintainers reached"); + }; + + maintainersByPackage.put(packageName, Array.append(maintainers, [newMaintainer])); + #ok; + }; + + public func removeOwner(caller : Principal, packageName : PackageName, ownerToRemove : Principal) : Result.Result<(), Text> { + let ?owners = ownersByPackage.get(packageName) else return #err("Package not found"); + + if (not isOwner(packageName, ownerToRemove)) { + return #err("User is not an owner"); + }; + if (not isOwner(packageName, caller)) { + return #err("Only owners can remove owners"); + }; + if (owners.size() <= 1) { + return #err("At least one owner is required"); + }; + + ownersByPackage.put(packageName, Array.filter(owners, func(owner : Principal) : Bool { + owner != ownerToRemove; + })); + #ok; + }; + + public func removeMaintainer(caller : Principal, packageName : PackageName, maintainerToRemove : Principal) : Result.Result<(), Text> { + let maintainers = Option.get(maintainersByPackage.get(packageName), []); - if (oldOwner != caller) { - return #err("Only owner can transfer ownership"); + if (not isMaintainer(packageName, maintainerToRemove)) { + return #err("User is not a maintainer"); }; - if (newOwner == caller) { - return #err("You can't transfer ownership to yourself"); + if (not isOwner(packageName, caller)) { + return #err("Only owners can remove maintainers"); }; - packageOwners.put(packageName, newOwner); + maintainersByPackage.put(packageName, Array.filter(maintainers, func(maintainer : Principal) : Bool { + maintainer != maintainerToRemove; + })); #ok; }; }; diff --git a/backend/main/registry/getPackageSummary.mo b/backend/main/registry/getPackageSummary.mo index a5fd793e..82b50014 100644 --- a/backend/main/registry/getPackageSummary.mo +++ b/backend/main/registry/getPackageSummary.mo @@ -1,6 +1,7 @@ import Time "mo:base/Time"; -import Option "mo:base/Option"; import Debug "mo:base/Debug"; +import Array "mo:base/Array"; +import Principal "mo:base/Principal"; import {DAY} "mo:time-consts"; import Types "../types"; @@ -23,19 +24,32 @@ module { public func getPackageSummary(registry : Registry.Registry, users : Users.Users, downloadLog : DownloadLog.DownloadLog, name : PackageName, version : PackageVersion) : ?PackageSummary { do ? { let config = registry.getPackageConfig(name, version)!; + let publication = registry.getPackagePublication(name, version)!; + users.ensureUser(publication.user); + + let owners = registry.getPackageOwners(name); + for (owner in owners.vals()) { + users.ensureUser(owner); + }; - let owner = registry.getPackageOwner(name)!; - users.ensureUser(owner); + let maintainers = registry.getPackageMaintainers(name); + for (maintainer in maintainers.vals()) { + users.ensureUser(maintainer); + }; + let owner = if (owners.size() > 0) owners[0] else Principal.fromText("aaaaa-aa"); let highestVersion = registry.getHighestVersion(name)!; return ?{ depAlias = ""; - owner = owner; - ownerInfo = users.getUser(owner); + owner = owner; // legacy + ownerInfo = users.getUser(owner); // legacy + owners = Array.map(owners, users.getUser); + maintainers = Array.map(maintainers, users.getUser); config = config; publication = publication; + publisher = users.getUser(publication.user); downloadsInLast7Days = downloadLog.getDownloadsByPackageNameIn(config.name, 7 * DAY, Time.now()); downloadsInLast30Days = downloadLog.getDownloadsByPackageNameIn(config.name, 30 * DAY, Time.now()); downloadsTotal = downloadLog.getTotalDownloadsByPackageName(config.name); diff --git a/backend/main/registry/searchInRegistry.mo b/backend/main/registry/searchInRegistry.mo index c16e1a7e..7848f396 100644 --- a/backend/main/registry/searchInRegistry.mo +++ b/backend/main/registry/searchInRegistry.mo @@ -41,19 +41,23 @@ module { if (Text.startsWith(searchText, #text("owner:"))) { ignore do ? { let searchOwnerNameOrId = Text.stripStart(searchText, #text("owner:"))!; - let ownerId = registry.getPackageOwner(config.name)!; + let owners = registry.getPackageOwners(config.name); // search by owner id if (Option.isSome(PrincipalExt.fromText(searchOwnerNameOrId))) { - if (searchOwnerNameOrId == Principal.toText(ownerId)) { - sortingPoints += 3; + for (ownerId in owners.vals()) { + if (searchOwnerNameOrId == Principal.toText(ownerId)) { + sortingPoints += 3; + }; }; } // search by owner name else { - let ownerInfo = users.getUserOpt(ownerId)!; - if (searchOwnerNameOrId == ownerInfo.name) { - sortingPoints += 3; + for (ownerId in owners.vals()) { + let ownerInfo = users.getUserOpt(ownerId)!; + if (searchOwnerNameOrId == ownerInfo.name) { + sortingPoints += 3; + }; }; }; }; diff --git a/backend/main/types.mo b/backend/main/types.mo index c4c44b67..6c41db72 100644 --- a/backend/main/types.mo +++ b/backend/main/types.mo @@ -89,10 +89,13 @@ module { }; public type PackageSummary = { - owner : Principal; // TODO: ownerId? - ownerInfo : User; + owner : Principal; // legacy + ownerInfo : User; // legacy + owners : [User]; + maintainers : [User]; config : PackageConfigV3; publication : PackagePublication; + publisher : User; downloadsTotal : Nat; downloadsInLast30Days : Nat; downloadsInLast7Days : Nat; diff --git a/cli/CHANGELOG.md b/cli/CHANGELOG.md index 469aafcd..f32fe98d 100644 --- a/cli/CHANGELOG.md +++ b/cli/CHANGELOG.md @@ -1,5 +1,11 @@ # Mops CLI Changelog +## Unreleased +- Removed `mops transfer-ownership` command +- Added `mops owner` command to manage package owners ([docs](https://docs.mops.one/cli/mops-owner)) +- Added `mops maintainers` command to manage package maintainers ([docs](https://docs.mops.one/cli/mops-maintainers)) +- Fixed bug where `mops watch` would fail if dfx.json did not exist + ## 1.1.2 - Fixed `{MOPS_ENV}` substitution in local package path diff --git a/cli/cli.ts b/cli/cli.ts index dcd678e9..c19824bf 100755 --- a/cli/cli.ts +++ b/cli/cli.ts @@ -21,12 +21,13 @@ import {sync} from './commands/sync.js'; import {outdated} from './commands/outdated.js'; import {update} from './commands/update.js'; import {bench} from './commands/bench.js'; -import {transferOwnership} from './commands/transfer-ownership.js'; import {toolchain} from './commands/toolchain/index.js'; import {Tool} from './types.js'; import * as self from './commands/self.js'; import {resolvePackages} from './resolve-packages.js'; import {watch} from './commands/watch/watch.js'; +import {addOwner, printOwners, removeOwner} from './commands/owner.js'; +import {addMaintainer, printMaintainers, removeMaintainer} from './commands/maintainer.js'; declare global { // eslint-disable-next-line no-var @@ -289,6 +290,68 @@ userCommand program.addCommand(userCommand); +// mops owner * +const ownerCommand = new Command('owner').description('Package owner management'); + +// mops owner list +ownerCommand + .command('list') + .description('List package owners') + .action(async () => { + await printOwners(); + }); + +// mops owner add +ownerCommand + .command('add ') + .description('Add package owner') + .addOption(new Option('--yes', 'Do not ask for confirmation')) + .action(async (data, options) => { + await addOwner(data, options.yes); + }); + +// mops owner remove +ownerCommand + .command('remove ') + .description('Remove package owner') + .addOption(new Option('--yes', 'Do not ask for confirmation')) + .action(async (data, options) => { + await removeOwner(data, options.yes); + }); + +program.addCommand(ownerCommand); + +// mops maintainer * +const maintainerCommand = new Command('maintainer').description('Package maintainer management'); + +// mops maintainer list +maintainerCommand + .command('list') + .description('List package maintainers') + .action(async () => { + await printMaintainers(); + }); + +// mops maintainer add +maintainerCommand + .command('add ') + .description('Add package maintainer') + .addOption(new Option('--yes', 'Do not ask for confirmation')) + .action(async (data, options) => { + await addMaintainer(data, options.yes); + }); + +// mops maintainer remove +maintainerCommand + .command('remove ') + .description('Remove package maintainer') + .addOption(new Option('--yes', 'Do not ask for confirmation')) + .action(async (data, options) => { + await removeMaintainer(data, options.yes); + }); + +program.addCommand(maintainerCommand); + // bump program .command('bump [major|minor|patch]') @@ -323,14 +386,6 @@ program await update(pkg, options); }); -// transfer-ownership -program - .command('transfer-ownership [to-principal]') - .description('Transfer ownership of the current package to another principal') - .action(async (toPrincipal) => { - await transferOwnership(toPrincipal); - }); - // toolchain const toolchainCommand = new Command('toolchain').description('Toolchain management'); diff --git a/cli/commands/maintainer.ts b/cli/commands/maintainer.ts new file mode 100644 index 00000000..dbbdf9c5 --- /dev/null +++ b/cli/commands/maintainer.ts @@ -0,0 +1,105 @@ +import process from 'node:process'; +import chalk from 'chalk'; +import {checkConfigFile, getIdentity, readConfig} from '../mops.js'; +import {mainActor} from '../api/actors.js'; +import {Principal} from '@dfinity/principal'; +import prompts from 'prompts'; + +export async function printMaintainers() { + if (!checkConfigFile()) { + return; + } + + let config = readConfig(); + let actor = await mainActor(); + + let maintainers = await actor.getPackageMaintainers(config.package?.name || ''); + console.log(`Maintainers of package ${chalk.bold(config.package?.name)}:`); + for (let maintainer of maintainers) { + console.log(maintainer.toText()); + } +} + +export async function addMaintainer(maintainer : string, yes = false) { + if (!checkConfigFile()) { + return; + } + + let config = readConfig(); + let principal = Principal.fromText(maintainer); + + if (!yes) { + let promptsConfig = { + onCancel() { + console.log('aborted'); + process.exit(0); + }, + }; + + let {confirm} = await prompts({ + type: 'confirm', + name: 'confirm', + message: `Are you sure you want to add maintainer ${chalk.yellow(maintainer)} to ${chalk.yellow(config.package?.name)} package?`, + initial: true, + }, promptsConfig); + + if (!confirm) { + return; + } + } + + let identity = await getIdentity(); + let actor = await mainActor(identity); + + let res = await actor.addMaintainer(config.package?.name || '', principal); + if ('ok' in res) { + console.log(chalk.green('Success!')); + console.log(`Added maintainer ${chalk.bold(maintainer)} to package ${chalk.bold(config.package?.name)}`); + } + else { + console.error(chalk.red('Error: ') + res.err); + process.exit(1); + } +} + +export async function removeMaintainer(maintainer : string, yes = false) { + if (!checkConfigFile()) { + return; + } + + let config = readConfig(); + let principal = Principal.fromText(maintainer); + + if (!yes) { + let promptsConfig = { + onCancel() { + console.log('aborted'); + process.exit(0); + }, + }; + + let {confirm} = await prompts({ + type: 'confirm', + name: 'confirm', + message: `Are you sure you want to remove maintainer ${chalk.red(maintainer)} from ${chalk.red(config.package?.name)} package?`, + initial: true, + }, promptsConfig); + + if (!confirm) { + return; + } + } + + let identity = await getIdentity(); + let actor = await mainActor(identity); + + let res = await actor.removeMaintainer(config.package?.name || '', principal); + if ('ok' in res) { + console.log(chalk.green('Success!')); + console.log(`Removed maintainer ${chalk.bold(maintainer)} from package ${chalk.bold(config.package?.name)}`); + } + else { + console.error(chalk.red('Error: ') + res.err); + process.exit(1); + } +} \ No newline at end of file diff --git a/cli/commands/owner.ts b/cli/commands/owner.ts new file mode 100644 index 00000000..57e0ed17 --- /dev/null +++ b/cli/commands/owner.ts @@ -0,0 +1,105 @@ +import process from 'node:process'; +import chalk from 'chalk'; +import {checkConfigFile, getIdentity, readConfig} from '../mops.js'; +import {mainActor} from '../api/actors.js'; +import {Principal} from '@dfinity/principal'; +import prompts from 'prompts'; + +export async function printOwners() { + if (!checkConfigFile()) { + return; + } + + let config = readConfig(); + let actor = await mainActor(); + + let owners = await actor.getPackageOwners(config.package?.name || ''); + console.log(`Owners of package ${chalk.bold(config.package?.name)}:`); + for (let owner of owners) { + console.log(owner.toText()); + } +} + +export async function addOwner(owner : string, yes = false) { + if (!checkConfigFile()) { + return; + } + + let config = readConfig(); + let principal = Principal.fromText(owner); + + if (!yes) { + let promptsConfig = { + onCancel() { + console.log('aborted'); + process.exit(0); + }, + }; + + let {confirm} = await prompts({ + type: 'confirm', + name: 'confirm', + message: `Are you sure you want to add owner ${chalk.yellow(owner)} to ${chalk.yellow(config.package?.name)} package?`, + initial: true, + }, promptsConfig); + + if (!confirm) { + return; + } + } + + let identity = await getIdentity(); + let actor = await mainActor(identity); + + let res = await actor.addOwner(config.package?.name || '', principal); + if ('ok' in res) { + console.log(chalk.green('Success!')); + console.log(`Added owner ${chalk.bold(owner)} to package ${chalk.bold(config.package?.name)}`); + } + else { + console.error(chalk.red('Error: ') + res.err); + process.exit(1); + } +} + +export async function removeOwner(owner : string, yes = false) { + if (!checkConfigFile()) { + return; + } + + let config = readConfig(); + let principal = Principal.fromText(owner); + + if (!yes) { + let promptsConfig = { + onCancel() { + console.log('aborted'); + process.exit(0); + }, + }; + + let {confirm} = await prompts({ + type: 'confirm', + name: 'confirm', + message: `Are you sure you want to remove owner ${chalk.red(owner)} from ${chalk.red(config.package?.name)} package?`, + initial: true, + }, promptsConfig); + + if (!confirm) { + return; + } + } + + let identity = await getIdentity(); + let actor = await mainActor(identity); + + let res = await actor.removeOwner(config.package?.name || '', principal); + if ('ok' in res) { + console.log(chalk.green('Success!')); + console.log(`Removed owner ${chalk.bold(owner)} from package ${chalk.bold(config.package?.name)}`); + } + else { + console.error(chalk.red('Error: ') + res.err); + process.exit(1); + } +} \ No newline at end of file diff --git a/cli/commands/transfer-ownership.ts b/cli/commands/transfer-ownership.ts deleted file mode 100644 index 9e989305..00000000 --- a/cli/commands/transfer-ownership.ts +++ /dev/null @@ -1,45 +0,0 @@ -import process from 'node:process'; -import chalk from 'chalk'; -import {checkConfigFile, getIdentity, readConfig} from '../mops.js'; -import {mainActor} from '../api/actors.js'; -import {Principal} from '@dfinity/principal'; -import prompts from 'prompts'; - -export async function transferOwnership(toPrincipal : string) { - if (!checkConfigFile()) { - return; - } - - let config = readConfig(); - let principal = Principal.fromText(toPrincipal); - - let promptsConfig = { - onCancel() { - console.log('aborted'); - process.exit(0); - }, - }; - - console.log(chalk.red('Warning: ') + 'This action cannot be undone!'); - let {confirm} = await prompts({ - type: 'confirm', - name: 'confirm', - message: `Are you sure you want to transfer ownership of ${chalk.yellow(config.package?.name)} to ${chalk.yellow(toPrincipal)}?`, - initial: false, - }, promptsConfig); - - if (!confirm) { - return; - } - - let identity = await getIdentity(); - let actor = await mainActor(identity); - - let res = await actor.transferOwnership(config.package?.name || '', principal); - if ('ok' in res) { - console.log(chalk.green('Success!')); - } - else { - console.log(chalk.red('Error: ') + res.err); - } -} \ No newline at end of file diff --git a/cli/commands/watch/parseDfxJson.ts b/cli/commands/watch/parseDfxJson.ts index 79b56df6..9989cca2 100644 --- a/cli/commands/watch/parseDfxJson.ts +++ b/cli/commands/watch/parseDfxJson.ts @@ -51,14 +51,14 @@ function readDfxJson() : DfxConfig | Record { export function getMotokoCanisters() : Record { let dfxJson = readDfxJson(); - return Object.fromEntries(Object.entries(dfxJson.canisters) + return Object.fromEntries(Object.entries(dfxJson.canisters || {}) .filter(([_, canister]) => canister.type === 'motoko') .map(([name, canister]) => [name, canister.main ?? ''])); } export function getMotokoCanistersWithDeclarations() : Record { let dfxJson = readDfxJson(); - return Object.fromEntries(Object.entries(dfxJson.canisters) + return Object.fromEntries(Object.entries(dfxJson.canisters || {}) .filter(([_, canister]) => canister.type === 'motoko' && canister.declarations) .map(([name, canister]) => [name, canister.main ?? ''])); } \ No newline at end of file diff --git a/cli/declarations/main/main.did b/cli/declarations/main/main.did index c06a6ea8..5d82914f 100644 --- a/cli/declarations/main/main.did +++ b/cli/declarations/main/main.did @@ -90,7 +90,7 @@ type Result_6 = variant { err: Err; ok: vec record { - PackageName; + PackageName__1; PackageVersion__1; }; }; @@ -106,18 +106,18 @@ type Result_4 = }; type Result_3 = variant { - err: Err; - ok: FileId; + err: text; + ok; }; type Result_2 = variant { err: Err; - ok: PublishingId; + ok: FileId; }; type Result_1 = variant { - err: text; - ok; + err: Err; + ok: PublishingId; }; type Result = variant { @@ -157,9 +157,12 @@ type PackageSummary__1 = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageSummaryWithChanges__1 = @@ -171,9 +174,12 @@ type PackageSummaryWithChanges__1 = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageSummaryWithChanges = @@ -185,9 +191,12 @@ type PackageSummaryWithChanges = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageSummary = @@ -198,9 +207,12 @@ type PackageSummary = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageQuality = @@ -243,9 +255,12 @@ type PackageDetails = downloadsTotal: nat; fileStats: PackageFileStatsPublic; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; testStats: TestStats__1; versionHistory: vec PackageSummaryWithChanges__1; @@ -263,7 +278,7 @@ type PackageConfigV3_Publishing = keywords: vec text; license: text; moc: text; - name: PackageName__1; + name: PackageName; readme: text; repository: text; requirements: opt vec Requirement; @@ -283,7 +298,7 @@ type PackageConfigV3 = keywords: vec text; license: text; moc: text; - name: PackageName__1; + name: PackageName; readme: text; repository: text; requirements: vec Requirement; @@ -301,6 +316,8 @@ type PackageChanges = }; type Main = service { + addMaintainer: (PackageName__1, principal) -> (Result_3); + addOwner: (PackageName__1, principal) -> (Result_3); backup: () -> (); computeHashesForExistingFiles: () -> (); finishPublish: (PublishingId) -> (Result); @@ -308,14 +325,14 @@ type Main = getBackupCanisterId: () -> (principal) query; getDefaultPackages: (text) -> (vec record { - PackageName; + PackageName__1; PackageVersion__1; }) query; getDownloadTrendByPackageId: (PackageId) -> (vec DownloadsSnapshot__1) query; - getDownloadTrendByPackageName: (PackageName) -> + getDownloadTrendByPackageName: (PackageName__1) -> (vec DownloadsSnapshot__1) query; - getFileHashes: (PackageName, PackageVersion__1) -> (Result_8); + getFileHashes: (PackageName__1, PackageVersion__1) -> (Result_8); getFileHashesByPackageIds: (vec PackageId) -> (vec record { PackageId; @@ -324,19 +341,22 @@ type Main = blob; }; }); - getFileHashesQuery: (PackageName, PackageVersion__1) -> (Result_8) query; - getFileIds: (PackageName, PackageVersion__1) -> (Result_7) query; + getFileHashesQuery: (PackageName__1, PackageVersion__1) -> + (Result_8) query; + getFileIds: (PackageName__1, PackageVersion__1) -> (Result_7) query; getHighestSemverBatch: (vec record { - PackageName; + PackageName__1; PackageVersion__1; SemverPart; }) -> (Result_6) query; - getHighestVersion: (PackageName) -> (Result_5) query; + getHighestVersion: (PackageName__1) -> (Result_5) query; getMostDownloadedPackages: () -> (vec PackageSummary) query; getMostDownloadedPackagesIn7Days: () -> (vec PackageSummary) query; getNewPackages: () -> (vec PackageSummary) query; - getPackageDetails: (PackageName, PackageVersion__1) -> (Result_4) query; + getPackageDetails: (PackageName__1, PackageVersion__1) -> (Result_4) query; + getPackageMaintainers: (PackageName__1) -> (vec principal) query; + getPackageOwners: (PackageName__1) -> (vec principal) query; getPackagesByCategory: () -> (vec record { text; vec PackageSummary; @@ -350,17 +370,18 @@ type Main = getTotalPackages: () -> (nat) query; getUser: (principal) -> (opt User__1) query; http_request: (Request) -> (Response) query; - notifyInstall: (PackageName, PackageVersion__1) -> () oneway; + notifyInstall: (PackageName__1, PackageVersion__1) -> () oneway; notifyInstalls: (vec record { - PackageName; + PackageName__1; PackageVersion__1; }) -> () oneway; + removeMaintainer: (PackageName__1, principal) -> (Result_3); + removeOwner: (PackageName__1, principal) -> (Result_3); restore: (nat) -> (); search: (Text, opt nat, opt nat) -> (vec PackageSummary, PageCount) query; - setUserProp: (text, text) -> (Result_1); - startFileUpload: (PublishingId, Text, nat, blob) -> (Result_3); - startPublish: (PackageConfigV3_Publishing) -> (Result_2); - transferOwnership: (PackageName, principal) -> (Result_1); + setUserProp: (text, text) -> (Result_3); + startFileUpload: (PublishingId, Text, nat, blob) -> (Result_2); + startPublish: (PackageConfigV3_Publishing) -> (Result_1); transformRequest: (HttpTransformArg) -> (HttpResponse) query; uploadBenchmarks: (PublishingId, Benchmarks) -> (Result); uploadFileChunk: (PublishingId, FileId, nat, blob) -> (Result); @@ -410,7 +431,7 @@ type DepsStatus = }; type DependencyV2 = record { - name: PackageName__1; + name: PackageName; repo: text; version: text; }; diff --git a/cli/declarations/main/main.did.d.ts b/cli/declarations/main/main.did.d.ts index 642779b9..79d52110 100644 --- a/cli/declarations/main/main.did.d.ts +++ b/cli/declarations/main/main.did.d.ts @@ -25,7 +25,7 @@ export interface DepChange { 'newVersion' : string, } export interface DependencyV2 { - 'name' : PackageName__1, + 'name' : PackageName, 'repo' : string, 'version' : string, } @@ -56,6 +56,8 @@ export interface HttpTransformArg { 'response' : HttpResponse, } export interface Main { + 'addMaintainer' : ActorMethod<[PackageName__1, Principal], Result_3>, + 'addOwner' : ActorMethod<[PackageName__1, Principal], Result_3>, 'backup' : ActorMethod<[], undefined>, 'computeHashesForExistingFiles' : ActorMethod<[], undefined>, 'finishPublish' : ActorMethod<[PublishingId], Result>, @@ -63,35 +65,40 @@ export interface Main { 'getBackupCanisterId' : ActorMethod<[], Principal>, 'getDefaultPackages' : ActorMethod< [string], - Array<[PackageName, PackageVersion__1]> + Array<[PackageName__1, PackageVersion__1]> >, 'getDownloadTrendByPackageId' : ActorMethod< [PackageId], Array >, 'getDownloadTrendByPackageName' : ActorMethod< - [PackageName], + [PackageName__1], Array >, - 'getFileHashes' : ActorMethod<[PackageName, PackageVersion__1], Result_8>, + 'getFileHashes' : ActorMethod<[PackageName__1, PackageVersion__1], Result_8>, 'getFileHashesByPackageIds' : ActorMethod< [Array], Array<[PackageId, Array<[FileId, Uint8Array | number[]]>]> >, 'getFileHashesQuery' : ActorMethod< - [PackageName, PackageVersion__1], + [PackageName__1, PackageVersion__1], Result_8 >, - 'getFileIds' : ActorMethod<[PackageName, PackageVersion__1], Result_7>, + 'getFileIds' : ActorMethod<[PackageName__1, PackageVersion__1], Result_7>, 'getHighestSemverBatch' : ActorMethod< - [Array<[PackageName, PackageVersion__1, SemverPart]>], + [Array<[PackageName__1, PackageVersion__1, SemverPart]>], Result_6 >, - 'getHighestVersion' : ActorMethod<[PackageName], Result_5>, + 'getHighestVersion' : ActorMethod<[PackageName__1], Result_5>, 'getMostDownloadedPackages' : ActorMethod<[], Array>, 'getMostDownloadedPackagesIn7Days' : ActorMethod<[], Array>, 'getNewPackages' : ActorMethod<[], Array>, - 'getPackageDetails' : ActorMethod<[PackageName, PackageVersion__1], Result_4>, + 'getPackageDetails' : ActorMethod< + [PackageName__1, PackageVersion__1], + Result_4 + >, + 'getPackageMaintainers' : ActorMethod<[PackageName__1], Array>, + 'getPackageOwners' : ActorMethod<[PackageName__1], Array>, 'getPackagesByCategory' : ActorMethod< [], Array<[string, Array]> @@ -105,23 +112,24 @@ export interface Main { 'getTotalPackages' : ActorMethod<[], bigint>, 'getUser' : ActorMethod<[Principal], [] | [User__1]>, 'http_request' : ActorMethod<[Request], Response>, - 'notifyInstall' : ActorMethod<[PackageName, PackageVersion__1], undefined>, + 'notifyInstall' : ActorMethod<[PackageName__1, PackageVersion__1], undefined>, 'notifyInstalls' : ActorMethod< - [Array<[PackageName, PackageVersion__1]>], + [Array<[PackageName__1, PackageVersion__1]>], undefined >, + 'removeMaintainer' : ActorMethod<[PackageName__1, Principal], Result_3>, + 'removeOwner' : ActorMethod<[PackageName__1, Principal], Result_3>, 'restore' : ActorMethod<[bigint], undefined>, 'search' : ActorMethod< [Text, [] | [bigint], [] | [bigint]], [Array, PageCount] >, - 'setUserProp' : ActorMethod<[string, string], Result_1>, + 'setUserProp' : ActorMethod<[string, string], Result_3>, 'startFileUpload' : ActorMethod< [PublishingId, Text, bigint, Uint8Array | number[]], - Result_3 + Result_2 >, - 'startPublish' : ActorMethod<[PackageConfigV3_Publishing], Result_2>, - 'transferOwnership' : ActorMethod<[PackageName, Principal], Result_1>, + 'startPublish' : ActorMethod<[PackageConfigV3_Publishing], Result_1>, 'transformRequest' : ActorMethod<[HttpTransformArg], HttpResponse>, 'uploadBenchmarks' : ActorMethod<[PublishingId, Benchmarks], Result>, 'uploadFileChunk' : ActorMethod< @@ -145,7 +153,7 @@ export interface PackageConfigV3 { 'scripts' : Array + +
+
+ {#if user.name} + {user.name} {user.id} + {:else} + {user.id} + {/if} +
+ {#if !compact} + {#if user.github} + + GitHub logo + {user.github} + + {/if} + {#if user.twitter} + + + {user.twitter} + + {/if} + {/if} +
+ + \ No newline at end of file diff --git a/frontend/declarations/main/main.did b/frontend/declarations/main/main.did index c06a6ea8..5d82914f 100644 --- a/frontend/declarations/main/main.did +++ b/frontend/declarations/main/main.did @@ -90,7 +90,7 @@ type Result_6 = variant { err: Err; ok: vec record { - PackageName; + PackageName__1; PackageVersion__1; }; }; @@ -106,18 +106,18 @@ type Result_4 = }; type Result_3 = variant { - err: Err; - ok: FileId; + err: text; + ok; }; type Result_2 = variant { err: Err; - ok: PublishingId; + ok: FileId; }; type Result_1 = variant { - err: text; - ok; + err: Err; + ok: PublishingId; }; type Result = variant { @@ -157,9 +157,12 @@ type PackageSummary__1 = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageSummaryWithChanges__1 = @@ -171,9 +174,12 @@ type PackageSummaryWithChanges__1 = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageSummaryWithChanges = @@ -185,9 +191,12 @@ type PackageSummaryWithChanges = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageSummary = @@ -198,9 +207,12 @@ type PackageSummary = downloadsInLast7Days: nat; downloadsTotal: nat; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; }; type PackageQuality = @@ -243,9 +255,12 @@ type PackageDetails = downloadsTotal: nat; fileStats: PackageFileStatsPublic; highestVersion: PackageVersion; + maintainers: vec User; owner: principal; ownerInfo: User; + owners: vec User; publication: PackagePublication; + publisher: User; quality: PackageQuality; testStats: TestStats__1; versionHistory: vec PackageSummaryWithChanges__1; @@ -263,7 +278,7 @@ type PackageConfigV3_Publishing = keywords: vec text; license: text; moc: text; - name: PackageName__1; + name: PackageName; readme: text; repository: text; requirements: opt vec Requirement; @@ -283,7 +298,7 @@ type PackageConfigV3 = keywords: vec text; license: text; moc: text; - name: PackageName__1; + name: PackageName; readme: text; repository: text; requirements: vec Requirement; @@ -301,6 +316,8 @@ type PackageChanges = }; type Main = service { + addMaintainer: (PackageName__1, principal) -> (Result_3); + addOwner: (PackageName__1, principal) -> (Result_3); backup: () -> (); computeHashesForExistingFiles: () -> (); finishPublish: (PublishingId) -> (Result); @@ -308,14 +325,14 @@ type Main = getBackupCanisterId: () -> (principal) query; getDefaultPackages: (text) -> (vec record { - PackageName; + PackageName__1; PackageVersion__1; }) query; getDownloadTrendByPackageId: (PackageId) -> (vec DownloadsSnapshot__1) query; - getDownloadTrendByPackageName: (PackageName) -> + getDownloadTrendByPackageName: (PackageName__1) -> (vec DownloadsSnapshot__1) query; - getFileHashes: (PackageName, PackageVersion__1) -> (Result_8); + getFileHashes: (PackageName__1, PackageVersion__1) -> (Result_8); getFileHashesByPackageIds: (vec PackageId) -> (vec record { PackageId; @@ -324,19 +341,22 @@ type Main = blob; }; }); - getFileHashesQuery: (PackageName, PackageVersion__1) -> (Result_8) query; - getFileIds: (PackageName, PackageVersion__1) -> (Result_7) query; + getFileHashesQuery: (PackageName__1, PackageVersion__1) -> + (Result_8) query; + getFileIds: (PackageName__1, PackageVersion__1) -> (Result_7) query; getHighestSemverBatch: (vec record { - PackageName; + PackageName__1; PackageVersion__1; SemverPart; }) -> (Result_6) query; - getHighestVersion: (PackageName) -> (Result_5) query; + getHighestVersion: (PackageName__1) -> (Result_5) query; getMostDownloadedPackages: () -> (vec PackageSummary) query; getMostDownloadedPackagesIn7Days: () -> (vec PackageSummary) query; getNewPackages: () -> (vec PackageSummary) query; - getPackageDetails: (PackageName, PackageVersion__1) -> (Result_4) query; + getPackageDetails: (PackageName__1, PackageVersion__1) -> (Result_4) query; + getPackageMaintainers: (PackageName__1) -> (vec principal) query; + getPackageOwners: (PackageName__1) -> (vec principal) query; getPackagesByCategory: () -> (vec record { text; vec PackageSummary; @@ -350,17 +370,18 @@ type Main = getTotalPackages: () -> (nat) query; getUser: (principal) -> (opt User__1) query; http_request: (Request) -> (Response) query; - notifyInstall: (PackageName, PackageVersion__1) -> () oneway; + notifyInstall: (PackageName__1, PackageVersion__1) -> () oneway; notifyInstalls: (vec record { - PackageName; + PackageName__1; PackageVersion__1; }) -> () oneway; + removeMaintainer: (PackageName__1, principal) -> (Result_3); + removeOwner: (PackageName__1, principal) -> (Result_3); restore: (nat) -> (); search: (Text, opt nat, opt nat) -> (vec PackageSummary, PageCount) query; - setUserProp: (text, text) -> (Result_1); - startFileUpload: (PublishingId, Text, nat, blob) -> (Result_3); - startPublish: (PackageConfigV3_Publishing) -> (Result_2); - transferOwnership: (PackageName, principal) -> (Result_1); + setUserProp: (text, text) -> (Result_3); + startFileUpload: (PublishingId, Text, nat, blob) -> (Result_2); + startPublish: (PackageConfigV3_Publishing) -> (Result_1); transformRequest: (HttpTransformArg) -> (HttpResponse) query; uploadBenchmarks: (PublishingId, Benchmarks) -> (Result); uploadFileChunk: (PublishingId, FileId, nat, blob) -> (Result); @@ -410,7 +431,7 @@ type DepsStatus = }; type DependencyV2 = record { - name: PackageName__1; + name: PackageName; repo: text; version: text; }; diff --git a/frontend/declarations/main/main.did.d.ts b/frontend/declarations/main/main.did.d.ts index 642779b9..79d52110 100644 --- a/frontend/declarations/main/main.did.d.ts +++ b/frontend/declarations/main/main.did.d.ts @@ -25,7 +25,7 @@ export interface DepChange { 'newVersion' : string, } export interface DependencyV2 { - 'name' : PackageName__1, + 'name' : PackageName, 'repo' : string, 'version' : string, } @@ -56,6 +56,8 @@ export interface HttpTransformArg { 'response' : HttpResponse, } export interface Main { + 'addMaintainer' : ActorMethod<[PackageName__1, Principal], Result_3>, + 'addOwner' : ActorMethod<[PackageName__1, Principal], Result_3>, 'backup' : ActorMethod<[], undefined>, 'computeHashesForExistingFiles' : ActorMethod<[], undefined>, 'finishPublish' : ActorMethod<[PublishingId], Result>, @@ -63,35 +65,40 @@ export interface Main { 'getBackupCanisterId' : ActorMethod<[], Principal>, 'getDefaultPackages' : ActorMethod< [string], - Array<[PackageName, PackageVersion__1]> + Array<[PackageName__1, PackageVersion__1]> >, 'getDownloadTrendByPackageId' : ActorMethod< [PackageId], Array >, 'getDownloadTrendByPackageName' : ActorMethod< - [PackageName], + [PackageName__1], Array >, - 'getFileHashes' : ActorMethod<[PackageName, PackageVersion__1], Result_8>, + 'getFileHashes' : ActorMethod<[PackageName__1, PackageVersion__1], Result_8>, 'getFileHashesByPackageIds' : ActorMethod< [Array], Array<[PackageId, Array<[FileId, Uint8Array | number[]]>]> >, 'getFileHashesQuery' : ActorMethod< - [PackageName, PackageVersion__1], + [PackageName__1, PackageVersion__1], Result_8 >, - 'getFileIds' : ActorMethod<[PackageName, PackageVersion__1], Result_7>, + 'getFileIds' : ActorMethod<[PackageName__1, PackageVersion__1], Result_7>, 'getHighestSemverBatch' : ActorMethod< - [Array<[PackageName, PackageVersion__1, SemverPart]>], + [Array<[PackageName__1, PackageVersion__1, SemverPart]>], Result_6 >, - 'getHighestVersion' : ActorMethod<[PackageName], Result_5>, + 'getHighestVersion' : ActorMethod<[PackageName__1], Result_5>, 'getMostDownloadedPackages' : ActorMethod<[], Array>, 'getMostDownloadedPackagesIn7Days' : ActorMethod<[], Array>, 'getNewPackages' : ActorMethod<[], Array>, - 'getPackageDetails' : ActorMethod<[PackageName, PackageVersion__1], Result_4>, + 'getPackageDetails' : ActorMethod< + [PackageName__1, PackageVersion__1], + Result_4 + >, + 'getPackageMaintainers' : ActorMethod<[PackageName__1], Array>, + 'getPackageOwners' : ActorMethod<[PackageName__1], Array>, 'getPackagesByCategory' : ActorMethod< [], Array<[string, Array]> @@ -105,23 +112,24 @@ export interface Main { 'getTotalPackages' : ActorMethod<[], bigint>, 'getUser' : ActorMethod<[Principal], [] | [User__1]>, 'http_request' : ActorMethod<[Request], Response>, - 'notifyInstall' : ActorMethod<[PackageName, PackageVersion__1], undefined>, + 'notifyInstall' : ActorMethod<[PackageName__1, PackageVersion__1], undefined>, 'notifyInstalls' : ActorMethod< - [Array<[PackageName, PackageVersion__1]>], + [Array<[PackageName__1, PackageVersion__1]>], undefined >, + 'removeMaintainer' : ActorMethod<[PackageName__1, Principal], Result_3>, + 'removeOwner' : ActorMethod<[PackageName__1, Principal], Result_3>, 'restore' : ActorMethod<[bigint], undefined>, 'search' : ActorMethod< [Text, [] | [bigint], [] | [bigint]], [Array, PageCount] >, - 'setUserProp' : ActorMethod<[string, string], Result_1>, + 'setUserProp' : ActorMethod<[string, string], Result_3>, 'startFileUpload' : ActorMethod< [PublishingId, Text, bigint, Uint8Array | number[]], - Result_3 + Result_2 >, - 'startPublish' : ActorMethod<[PackageConfigV3_Publishing], Result_2>, - 'transferOwnership' : ActorMethod<[PackageName, Principal], Result_1>, + 'startPublish' : ActorMethod<[PackageConfigV3_Publishing], Result_1>, 'transformRequest' : ActorMethod<[HttpTransformArg], HttpResponse>, 'uploadBenchmarks' : ActorMethod<[PublishingId, Benchmarks], Result>, 'uploadFileChunk' : ActorMethod< @@ -145,7 +153,7 @@ export interface PackageConfigV3 { 'scripts' : Array