Skip to content

Conversation

@jeremymeng
Copy link
Member

@jeremymeng jeremymeng commented Apr 30, 2021

and address JS review feedback. API changes include

  • Change to a single ContainerRegistryClient with helper classes of hierarchy ContainerRepository => RegistryArtifact to group repository and artifact operations
  • Add string literal types for artifact architectures and operation systems.
  • Combine the parameters to Set*Properties() methods
  • Add readonly properties like loginServer and fullyQualifiedName for better interaction with docker and other tools.
  • Various renames

for `set*Properties()` methods.
- type alias for known architecture and operating systems.
- orderby literals: "timeAsc" and "timeDesc"
Fix linting issue

Update api review md file
@jeremymeng
Copy link
Member Author

@chradek @xirzec please take a look

Copy link
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some initial feedback on the api shapes

```ts

import * as coreClient from '@azure/core-client';
import * as coreHttps from '@azure/core-rest-pipeline';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did we intend to alias this as a group? I notice we directly import PipelineOptions below

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these two are from the generated code and probably pulled in by api-extractor when we export generated types.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somehow it's gone in the latest version, after I removed export of a generated type.

import { TokenCredential } from '@azure/core-auth';

// @public
export type ArtifactArchitecture = "386" | "amd64" | "arm" | "arm64" | "mips" | "mipsle" | "mips64" | "mips64le" | "ppc64" | "ppc64le" | "riscv64" | "s390x" | "wasm" | string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this type provide value? TS will collapse this to type ArtifactArchitecture = string

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I was thinking about making them extensible, but the generated code has export const enum KnownArtifactArchitecture which I don't think we like in TS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to string, and export KnownArtifactArchitecture literal unions.


// @public
export interface ArtifactManifestProperties {
readonly architecture?: ArtifactArchitecture | null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does null vs undefined mean? Does it remove the property at the source when doing a patch/update?

question applies to other nullable properties too

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are output only. It's an error from copy-&-pasting the generated code.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed | null

readonly operatingSystem?: ArtifactOperatingSystem | null;
readonly repositoryName?: string;
readonly size?: number;
readonly tags?: string[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make this default to an empty array similar to manifests?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

}

// @public
export type ArtifactOperatingSystem = "aix" | "android" | "darwin" | "dragonfly" | "freebsd" | "illumos" | "ios" | "js" | "linux" | "netbsd" | "openbsd" | "plan9" | "solaris" | "windows" | string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same issue as above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aliased it to string

getArtifact(repositoryName: string, tagOrDigest: string): RegistryArtifact;
getRepository(repositoryName: string): ContainerRepository;
listRepositoryNames(options?: ListRepositoriesOptions): PagedAsyncIterableIterator<string, string[]>;
loginServer: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this are public, mutable properties?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be readonly

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

export class ContainerRepositoryClient {
constructor(endpointUrl: string, repository: string, credential: TokenCredential, options?: ContainerRegistryClientOptions);
export class ContainerRepository {
// Warning: (ae-forgotten-export) The symbol "GeneratedClient" needs to be exported by the entry point index.d.ts
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this feels a bit leaky, we should be able to avoid exposing GeneratedClient -- seems like this class should be hidden and we can expose a compatible ContainerRegistry interface that we return the class instance for

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I will expose interface instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment on lines 94 to 95
readonly deletedManifests?: string[];
readonly deletedTags?: string[];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be nice to default these arrays to empty array

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

writeableProperties?: ContentProperties;
export class RegistryArtifact {
// @internal
constructor(registryUrl: string, repositoryName: string, tagOrDigest: string, client: GeneratedClient);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thinking, let's make this an interface since it's not a Client

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

constructor(registryUrl: string, repositoryName: string, tagOrDigest: string, client: GeneratedClient);
delete(options?: DeleteArtifactOptions): Promise<void>;
deleteTag(tag: string, options?: DeleteTagOptions): Promise<void>;
// (undocumented)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

docstring?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

@jeremymeng jeremymeng mentioned this pull request May 7, 2021
4 tasks
Copy link
Member

@xirzec xirzec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed notes + api shape and both look good to me modulo some comments. 👍

I didn't review changes to other files, so probably good to get one more reviewer signoff before merging.

// @public
export interface ArtifactManifestProperties {
readonly architecture?: ArtifactArchitecture | null;
readonly architecture?: ArtifactArchitecture;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is just string now, can we make it string here instead of having to define a type that aliases string?

readonly digest?: string;
readonly lastUpdatedOn?: Date;
manifests?: ArtifactManifestProperties[];
readonly operatingSystem?: ArtifactOperatingSystem | null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same thinking here

? "timeasc"
: options.orderBy === "timeDesc"
? "timedesc"
: undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if toLowerCase would be better here. It's not really that relevant in itself, however: These constant values, would they change later? should we scope these transformations in some functions? so that the transformation changes happen separately from the logic changes?

Take it or leave it, I'm just sharing an idea 🌞

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to a transformation helper function.

}
if (currentPage.manifests) {
yield currentPage.manifests.map((t) => {
return {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Key Vault we like to put translations like this (type A to type B) in a "transformations" file. What we find important is not the name of the file, but the idea of separating the renames from the logic around the renames. Sometimes these renames happen more than once, so these functions can be re-used. Here's one for KV Keys: https://github.com/Azure/azure-sdk-for-js/blob/master/sdk/keyvault/keyvault-keys/src/transformations.ts

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extracted this into a helper function in transformation.ts

Copy link
Contributor

@sadasant sadasant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you Jeremy!, this is good work 👍

@jeremymeng jeremymeng merged commit 5eff9b8 into Azure:master May 10, 2021
@jeremymeng jeremymeng deleted the acr-beta2-swagger branch May 10, 2021 22:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client This issue points to a problem in the data-plane of the library. Container Registry

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants