Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/tstamm/fix-node16-resolution-in-…
Browse files Browse the repository at this point in the history
…protoplugin' into psachs/node16-import-problem
  • Loading branch information
timostamm committed Oct 27, 2023
2 parents 43ad55d + aedb3c1 commit 23203bd
Show file tree
Hide file tree
Showing 5 changed files with 329 additions and 10 deletions.
39 changes: 32 additions & 7 deletions packages/protobuf/src/codegen-info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,42 @@ import {
import { getUnwrappedFieldType } from "./private/field-wrapper.js";
import { scalarDefaultValue } from "./private/scalars.js";
import { reifyWkt } from "./private/reify-wkt.js";
import type {
DescEnum,
DescEnumValue,
DescField,
DescMessage,
DescMethod,
DescOneof,
DescService,
} from "./descriptor-set";
import { LongType, ScalarType } from "./field.js";

interface CodegenInfo {
/**
* Name of the runtime library NPM package.
*/
readonly packageName: string;
readonly localName: typeof localName;
readonly localName: (
desc:
| DescEnum
| DescEnumValue
| DescMessage
| DescOneof
| DescField
| DescService
| DescMethod,
) => string;
readonly symbols: Record<RuntimeSymbolName, RuntimeSymbolInfo>;
readonly getUnwrappedFieldType: typeof getUnwrappedFieldType;
readonly getUnwrappedFieldType: (field: DescField) => ScalarType | undefined;
readonly wktSourceFiles: readonly string[];
readonly scalarDefaultValue: typeof scalarDefaultValue;
readonly scalarDefaultValue: (type: ScalarType, longType: LongType) => any; // eslint-disable-line @typescript-eslint/no-explicit-any
/**
* @deprecated please use reifyWkt from @bufbuild/protoplugin/ecmascript instead
*/
readonly reifyWkt: typeof reifyWkt;
readonly safeIdentifier: typeof safeIdentifier;
readonly safeObjectProperty: typeof safeObjectProperty;
readonly safeIdentifier: (name: string) => string;
readonly safeObjectProperty: (name: string) => string;
}

type RuntimeSymbolName =
Expand Down Expand Up @@ -64,7 +89,7 @@ type RuntimeSymbolInfo = {
const packageName = "@bufbuild/protobuf";

export const codegenInfo: CodegenInfo = {
packageName,
packageName: "@bufbuild/protobuf",
localName,
reifyWkt,
getUnwrappedFieldType,
Expand Down Expand Up @@ -108,4 +133,4 @@ export const codegenInfo: CodegenInfo = {
"google/protobuf/type.proto",
"google/protobuf/wrappers.proto",
],
} as const;
};
2 changes: 1 addition & 1 deletion packages/protobuf/src/private/options-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import type { JsonValue } from "../json-format";
import type { JsonValue } from "../json-format.js";

/**
*
Expand Down
2 changes: 2 additions & 0 deletions packages/protobuf/src/private/reify-wkt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ type DescWkt =
};

/**
* @deprecated please use reifyWkt from @bufbuild/protoplugin/ecmascript instead
*
* Reifies a given DescMessage into a more concrete object representing its
* respective well-known type. The returned object will contain properties
* representing the WKT's defined fields.
Expand Down
4 changes: 2 additions & 2 deletions packages/protoplugin/src/ecmascript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@
// limitations under the License.

import { codegenInfo } from "@bufbuild/protobuf";

export { reifyWkt } from "./reify-wkt.js";
export { Target } from "./target.js";
export { Schema } from "./schema.js";
export { RuntimeImports } from "./runtime-imports.js";
export { GeneratedFile, FileInfo, Printable } from "./generated-file.js";
export { ImportSymbol } from "./import-symbol.js";

export const { localName, reifyWkt } = codegenInfo;
export const { localName } = codegenInfo;

export {
createJsDocBlock,
Expand Down
292 changes: 292 additions & 0 deletions packages/protoplugin/src/ecmascript/reify-wkt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
// Copyright 2021-2023 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.

import type { DescField, DescMessage, DescOneof } from "@bufbuild/protobuf";
import { ScalarType } from "@bufbuild/protobuf";

type DescWkt =
| {
typeName: "google.protobuf.Any";
typeUrl: DescField;
value: DescField;
}
| {
typeName: "google.protobuf.Timestamp";
seconds: DescField;
nanos: DescField;
}
| {
typeName: "google.protobuf.Duration";
seconds: DescField;
nanos: DescField;
}
| {
typeName: "google.protobuf.Struct";
fields: DescField & { fieldKind: "map" };
}
| {
typeName: "google.protobuf.Value";
kind: DescOneof;
nullValue: DescField & { fieldKind: "enum" };
numberValue: DescField;
stringValue: DescField;
boolValue: DescField;
structValue: DescField & { fieldKind: "message" };
listValue: DescField & { fieldKind: "message" };
}
| {
typeName: "google.protobuf.ListValue";
values: DescField & { fieldKind: "message" };
}
| {
typeName: "google.protobuf.FieldMask";
paths: DescField;
}
| {
typeName: "google.protobuf.DoubleValue";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.FloatValue";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.Int64Value";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.UInt64Value";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.Int32Value";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.UInt32Value";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.BoolValue";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.StringValue";
value: DescField & { fieldKind: "scalar" };
}
| {
typeName: "google.protobuf.BytesValue";
value: DescField & { fieldKind: "scalar" };
};

/**
* Reifies a given DescMessage into a more concrete object representing its
* respective well-known type. The returned object will contain properties
* representing the WKT's defined fields.
*
* Useful during code generation when immediate access to a particular field
* is needed without having to search the object's typename and DescField list.
*
* Returns undefined if the WKT cannot be completely constructed via the
* DescMessage.
*/
export function reifyWkt(message: DescMessage): DescWkt | undefined {
switch (message.typeName) {
case "google.protobuf.Any": {
const typeUrl = message.fields.find(
(f) =>
f.number == 1 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.STRING,
);
const value = message.fields.find(
(f) =>
f.number == 2 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.BYTES,
);
if (typeUrl && value) {
return {
typeName: message.typeName,
typeUrl,
value,
};
}
break;
}
case "google.protobuf.Timestamp": {
const seconds = message.fields.find(
(f) =>
f.number == 1 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.INT64,
);
const nanos = message.fields.find(
(f) =>
f.number == 2 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.INT32,
);
if (seconds && nanos) {
return {
typeName: message.typeName,
seconds,
nanos,
};
}
break;
}
case "google.protobuf.Duration": {
const seconds = message.fields.find(
(f) =>
f.number == 1 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.INT64,
);
const nanos = message.fields.find(
(f) =>
f.number == 2 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.INT32,
);
if (seconds && nanos) {
return {
typeName: message.typeName,
seconds,
nanos,
};
}
break;
}
case "google.protobuf.Struct": {
const fields = message.fields.find((f) => f.number == 1 && !f.repeated);
if (
fields?.fieldKind !== "map" ||
fields.mapValue.kind !== "message" ||
fields.mapValue.message.typeName !== "google.protobuf.Value"
) {
break;
}
return { typeName: message.typeName, fields };
}
case "google.protobuf.Value": {
const kind = message.oneofs.find((o) => o.name === "kind");
const nullValue = message.fields.find(
(f) => f.number == 1 && f.oneof === kind,
);
if (
nullValue?.fieldKind !== "enum" ||
nullValue.enum.typeName !== "google.protobuf.NullValue"
) {
return undefined;
}
const numberValue = message.fields.find(
(f) =>
f.number == 2 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.DOUBLE &&
f.oneof === kind,
);
const stringValue = message.fields.find(
(f) =>
f.number == 3 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.STRING &&
f.oneof === kind,
);
const boolValue = message.fields.find(
(f) =>
f.number == 4 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.BOOL &&
f.oneof === kind,
);
const structValue = message.fields.find(
(f) => f.number == 5 && f.oneof === kind,
);
if (
structValue?.fieldKind !== "message" ||
structValue.message.typeName !== "google.protobuf.Struct"
) {
return undefined;
}
const listValue = message.fields.find(
(f) => f.number == 6 && f.oneof === kind,
);
if (
listValue?.fieldKind !== "message" ||
listValue.message.typeName !== "google.protobuf.ListValue"
) {
return undefined;
}
if (kind && numberValue && stringValue && boolValue) {
return {
typeName: message.typeName,
kind,
nullValue,
numberValue,
stringValue,
boolValue,
structValue,
listValue,
};
}
break;
}
case "google.protobuf.ListValue": {
const values = message.fields.find((f) => f.number == 1 && f.repeated);
if (
values?.fieldKind != "message" ||
values.message.typeName !== "google.protobuf.Value"
) {
break;
}
return { typeName: message.typeName, values };
}
case "google.protobuf.FieldMask": {
const paths = message.fields.find(
(f) =>
f.number == 1 &&
f.fieldKind == "scalar" &&
f.scalar === ScalarType.STRING &&
f.repeated,
);
if (paths) {
return { typeName: message.typeName, paths };
}
break;
}
case "google.protobuf.DoubleValue":
case "google.protobuf.FloatValue":
case "google.protobuf.Int64Value":
case "google.protobuf.UInt64Value":
case "google.protobuf.Int32Value":
case "google.protobuf.UInt32Value":
case "google.protobuf.BoolValue":
case "google.protobuf.StringValue":
case "google.protobuf.BytesValue": {
const value = message.fields.find(
(f) => f.number == 1 && f.name == "value",
);
if (!value) {
break;
}
if (value.fieldKind !== "scalar") {
break;
}
return { typeName: message.typeName, value };
}
}
return undefined;
}

0 comments on commit 23203bd

Please sign in to comment.