// Copyright 2020-2025 Buf Technologies, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package buf.alpha.registry.v1alpha1;

import "buf/alpha/module/v1alpha1/module.proto";
import "buf/alpha/registry/v1alpha1/module.proto";

// ResolveService is the resolve service.
//
// This is the public service.
service ResolveService {
  // GetModulePins finds all the latest digests and respective dependencies of
  // the provided module references and picks a set of distinct modules pins.
  //
  // Note that module references with commits should still be passed to this function
  // to make sure this function can do dependency resolution.
  //
  // This function also deals with tiebreaking what ModulePin wins for the same repository.
  rpc GetModulePins(GetModulePinsRequest) returns (GetModulePinsResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetGoVersion resolves the given plugin and module references to a version.
  rpc GetGoVersion(GetGoVersionRequest) returns (GetGoVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetSwiftVersion resolves the given plugin and module references to a version.
  rpc GetSwiftVersion(GetSwiftVersionRequest) returns (GetSwiftVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetMavenVersion resolves the given plugin and module references to a version.
  rpc GetMavenVersion(GetMavenVersionRequest) returns (GetMavenVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetNPMVersion resolves the given plugin and module references to a version.
  rpc GetNPMVersion(GetNPMVersionRequest) returns (GetNPMVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetPythonVersion resolves the given plugin and module references to a version.
  rpc GetPythonVersion(GetPythonVersionRequest) returns (GetPythonVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetCargoVersion resolves the given plugin and module references to a version.
  rpc GetCargoVersion(GetCargoVersionRequest) returns (GetCargoVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetNugetVersion resolves the given plugin and module references to a version.
  rpc GetNugetVersion(GetNugetVersionRequest) returns (GetNugetVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
  // GetCmakeVersion resolves the given plugin and module references to a version.
  rpc GetCmakeVersion(GetCmakeVersionRequest) returns (GetCmakeVersionResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
}

message GetModulePinsRequest {
  repeated buf.alpha.module.v1alpha1.ModuleReference module_references = 1;

  // current_module_pins allows for partial dependency updates by letting clients
  // send a request with the pins for their current module and only the
  // identities of the dependencies they want to update in module_references.
  //
  // When resolving, if a client supplied module pin is:
  // - in the transitive closure of pins resolved from the module_references,
  //   the client supplied module pin will be an extra candidate for tie
  //   breaking.
  // - NOT in the in the transitive closure of pins resolved from the
  //   module_references, it will be returned as is.
  repeated buf.alpha.module.v1alpha1.ModulePin current_module_pins = 2;
}

message GetModulePinsResponse {
  repeated buf.alpha.module.v1alpha1.ModulePin module_pins = 1;
}

// LocalResolveService is the local resolve service.
//
// This is called by ResolveService implementations, and is enterprise.
service LocalResolveService {
  // GetLocalModulePins gets the latest pins for the specified local module references.
  // It also includes all of the modules transitive dependencies for the specified references.
  //
  // We want this for two reasons:
  //
  //  1. It makes it easy to say "we know we're looking for owner/repo on this specific remote".
  //     While we could just do this in GetModulePins by being aware of what our remote is
  //     (something we probably still need to know, DNS problems aside, which are more
  //     theoretical), this helps.
  //  2. Having a separate method makes us able to say "do not make decisions about what
  //     wins between competing pins for the same repo". This should only be done in
  //     GetModulePins, not in this function, i.e. only done at the top level.
  rpc GetLocalModulePins(GetLocalModulePinsRequest) returns (GetLocalModulePinsResponse) {
    option idempotency_level = NO_SIDE_EFFECTS;
  }
}

message GetLocalModulePinsRequest {
  repeated buf.alpha.registry.v1alpha1.LocalModuleReference local_module_references = 1;
}

enum ResolvedReferenceType {
  reserved 4;
  reserved "RESOLVED_REFERENCE_TYPE_TRACK";

  RESOLVED_REFERENCE_TYPE_UNSPECIFIED = 0;
  RESOLVED_REFERENCE_TYPE_COMMIT = 1;
  RESOLVED_REFERENCE_TYPE_BRANCH = 2;
  RESOLVED_REFERENCE_TYPE_TAG = 3;
  RESOLVED_REFERENCE_TYPE_DRAFT = 5;
}

message LocalModuleResolveResult {
  reserved 4;
  reserved "is_bsr_head";

  // A copy of the reference that was resolved.
  buf.alpha.registry.v1alpha1.LocalModuleReference reference = 1;
  // The pin the reference resolved to.
  buf.alpha.registry.v1alpha1.LocalModulePin pin = 2;
  // The type the reference resolved as.
  ResolvedReferenceType resolved_reference_type = 3;
}

message GetLocalModulePinsResponse {
  repeated LocalModuleResolveResult local_module_resolve_results = 1;

  // dependencies are the dependencies of the LocalModulePins.
  //
  // This includes the transitive deps.
  repeated buf.alpha.module.v1alpha1.ModulePin dependencies = 2;
}

message GetGoVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetGoVersionResponse {
  // version is the resolved version to be used with the go module proxy.
  string version = 1;
}

message GetMavenVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetMavenVersionResponse {
  // version is the resolved version to be used with the maven repository.
  string version = 1;
}

message GetNPMVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetNPMVersionResponse {
  // version is the resolved version to be used with the npm registry.
  string version = 1;
}

message GetSwiftVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetSwiftVersionResponse {
  // version is the resolved version to be used with the swift registry.
  string version = 1;
}

message GetPythonVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetPythonVersionResponse {
  // version is the resolved version to be used with the python repository.
  string version = 1;
}

message GetCargoVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetCargoVersionResponse {
  // version is the resolved version to be used with the cargo registry.
  string version = 1;
}

message GetNugetVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetNugetVersionResponse {
  // version is the resolved version to be used with the nuget registry.
  string version = 1;
}

message GetCmakeVersionRequest {
  // The plugin reference to resolve.
  GetRemotePackageVersionPlugin plugin_reference = 1;
  // The module reference to resolve.
  LocalModuleReference module_reference = 2;
}

message GetCmakeVersionResponse {
  // version is the resolved version to be used with the cmake registry.
  string version = 1;
}

// GetRemotePackageVersionPlugin is a plugin reference.
// If the version is empty, this is a reference to the latest version.
message GetRemotePackageVersionPlugin {
  // The owner of the plugin.
  // example: bufbuild
  string owner = 1;
  // The name of the plugin.
  // example: connect-go
  string name = 2;
  // The version of the plugin.
  // If empty, this is a reference to the latest version.
  // example: v1.0.0
  string version = 3;
  // The revision of the plugin version.
  // example: 1
  uint32 revision = 4;
}
