-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
feat: add typing for request params #1141
Conversation
This is exactly what I've been looking for... and was about to investigate working on :) Thanks and hopefully it can be vetted and merged soon. |
@google/google-node-team what, nobody wants to review my 300,000 line change? |
I took a look at the generated types and have a few comments. Mostly I was reviewing the export interface Params$Resource$Instances$Insert {
auth?: string|OAuth2Client|JWT|Compute|UserRefreshClient;
project: string;
requestId?: string;
sourceInstanceTemplate?: string;
zone: string;
resource?: Schema$Instance;
}
The resource of type export interface Schema$Instance {
...
/**
* [Output Only] The CPU platform used by this instance.
*/
cpuPlatform?: string; Not sure if there's a way to separate out output-only fields that clutter this type when using it as an input. Using On the other hand, having unified input and output Schema types means making pretty much all fields need to be optional, even if the responses from the API always have certain fields. This makes using the results somewhat less convenient because it will be hard to tell where error checks are really needed. I expect to see client code littered with export interface Schema$Instance {
cpuPlatform: string; // not optional, always returned by server
name: string; // always returned, not optional.
...
}
export interface Schema$InstanceInsert {
// cpuPlatform isn't even mentioned here because it's output-only
name: string; // required for creating an instance
...
}
export interface Params$Resource$Instances$Insert {
resource: Schema$InstanceInsert; // Not optional, required to create an instance
...
} Of course this is only possible if the source API definition file has the detail required. Maybe this is reaching for the stars... I'd be very happy with just the types you already have generated. |
This is really great feedback.
Yeah - that's really tough. If we go down that road, I just need to make every property optional, and do required field checking at runtime (which I need to do anyway). The tradeoff here is that you won't really know what's required or not statically. I could really go either way on this one 🤷♂️ Totally open for debate.
Sadly, this is one of those places where I'm limited by what information is available in the discovery docs I'm using to generate these APIs. Lets use compute.instances.insert as an example: The discovery doc tells me that the body of the request can take an |
One argument for making them optional is that it's idiomatic usage to specify the zone and project at the global or api level in JavaScript. Making it a static type error for TypeScript means anyone migrating from JS to TS gets a spurious type error on almost every api call. The biggest value in having types comes from type safety and convenience for autocomplete. The latter is what really helps discoverability and what most developers are after for this API. Type safety is nice too but it's already unreliable in this API because of the missing detail in the schema file. So my opinion is that you might as well shoot for convenience all the way, instead of a haphazard mix of the two. Runtime checks are a good enough fallback for the lack of type safety, IMHO.
The discovery doc appears to be itself generated from something else... perhaps a protobuf definition? I ask because there are comments like "[Output Only]" which are used in a somewhat mechanically consistent way -- perhaps something in the original source definition format that wasn't expressed in the JSON? In any case thanks for checking. |
You've changed my mind :) I made all the params optional. On how the discovery doc is generated... I'm not sure! I will find out. |
Awesome. Really looking forward to using these APIs with types. |
@acchou re: compute - we actually have another Node.js client with manually written (not generated) methods, want to check it out? @google-cloud/compute |
(but it's plain JavaScript, no TypeScript yet while it's planned :) ) |
src/scripts/generator.ts
Outdated
@@ -109,7 +109,13 @@ export class Generator { | |||
} | |||
|
|||
private cleanPropertyName(prop: string) { | |||
return prop.replace('@', '').replace('-', ''); | |||
const match = prop.match(/@|\-|\./g); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/scripts/generator.ts
Outdated
|
||
private hasResourceParam(method: SchemaMethod) { | ||
return method.parameters && | ||
Object.keys(method.parameters).indexOf('resource') > -1; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
src/templates/api-endpoint.njk
Outdated
@@ -19,6 +19,7 @@ | |||
*/ | |||
|
|||
import { GoogleApis } from '../..'; | |||
import {OAuth2Client, JWT, Compute, UserRefreshClient} from 'google-auth-library'; |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
test/test.media.ts
Outdated
@@ -99,7 +99,7 @@ describe('Media', () => { | |||
const fileName = path.join(__dirname, '../../test/fixtures/mediabody.txt'); | |||
const fileSize = (await pify(fs.stat)(fileName)).size; | |||
const google = new GoogleApis(); | |||
const youtube = google.youtube('v3'); | |||
const youtube = google.youtube<youtube_v3.Youtube>('v3'); |
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
This comment was marked as spam.
Sorry, something went wrong.
Thanks for the vibrant discussion and ideas folks! I think we got it :) Take a look and let me know what you think. |
Looks good to me. Thanks for taking this one step further to make it more convenient for clients of the api. |
Scroll to the bottom for the good part 🐱