ts-proto 1.105.2 → 1.106.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,24 @@
1
+ ## [1.106.2](https://github.com/stephenh/ts-proto/compare/v1.106.1...v1.106.2) (2022-02-27)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * Add M1/ARM support for the test suite ([#516](https://github.com/stephenh/ts-proto/issues/516)) ([7cf5625](https://github.com/stephenh/ts-proto/commit/7cf56251726d149eebd015367476f36e4edb48aa))
7
+
8
+ ## [1.106.1](https://github.com/stephenh/ts-proto/compare/v1.106.0...v1.106.1) (2022-02-21)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * support json_name containing hyphen on all field types ([#521](https://github.com/stephenh/ts-proto/issues/521)) ([8d9e78e](https://github.com/stephenh/ts-proto/commit/8d9e78eb39c460f6727458f6a2dd149deb983668))
14
+
15
+ # [1.106.0](https://github.com/stephenh/ts-proto/compare/v1.105.2...v1.106.0) (2022-02-21)
16
+
17
+
18
+ ### Features
19
+
20
+ * Support json names containing non-alphanumeric characters ([#520](https://github.com/stephenh/ts-proto/issues/520)) ([ce44668](https://github.com/stephenh/ts-proto/commit/ce44668b8fe01b14f50ac3c5c950f73db769fa76))
21
+
1
22
  ## [1.105.2](https://github.com/stephenh/ts-proto/compare/v1.105.1...v1.105.2) (2022-02-17)
2
23
 
3
24
 
package/build/main.js CHANGED
@@ -895,7 +895,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
895
895
  // add a check for each incoming field
896
896
  messageDesc.field.forEach((field) => {
897
897
  const fieldName = case_1.maybeSnakeToCamel(field.name, options);
898
- const jsonName = utils_1.determineFieldJsonName(field, options);
898
+ const jsonName = utils_1.getFieldJsonName(field, options);
899
+ const jsonProperty = utils_1.getPropertyAccessor('object', jsonName);
900
+ const jsonPropertyOptional = utils_1.getPropertyAccessor('object', jsonName, true);
899
901
  // get code that extracts value from incoming object
900
902
  const readSnippet = (from) => {
901
903
  if (types_1.isEnum(field)) {
@@ -1013,8 +1015,8 @@ function generateFromJson(ctx, fullName, messageDesc) {
1013
1015
  const fieldType = types_1.toTypeName(ctx, messageDesc, field);
1014
1016
  const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
1015
1017
  chunks.push(ts_poet_1.code `
1016
- ${fieldName}: ${ctx.utils.isObject}(object.${jsonName})
1017
- ? Object.entries(object.${jsonName}).reduce<${fieldType}>((acc, [key, value]) => {
1018
+ ${fieldName}: ${ctx.utils.isObject}(${jsonProperty})
1019
+ ? Object.entries(${jsonProperty}).reduce<${fieldType}>((acc, [key, value]) => {
1018
1020
  acc[${i}] = ${readSnippet('value')};
1019
1021
  return acc;
1020
1022
  }, {})
@@ -1024,12 +1026,12 @@ function generateFromJson(ctx, fullName, messageDesc) {
1024
1026
  else {
1025
1027
  const readValueSnippet = readSnippet('e');
1026
1028
  if (readValueSnippet.toString() === ts_poet_1.code `e`.toString()) {
1027
- chunks.push(ts_poet_1.code `${fieldName}: Array.isArray(object?.${jsonName}) ? [...object.${jsonName}] : [],`);
1029
+ chunks.push(ts_poet_1.code `${fieldName}: Array.isArray(${jsonPropertyOptional}) ? [...${jsonProperty}] : [],`);
1028
1030
  }
1029
1031
  else {
1030
1032
  // Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
1031
1033
  chunks.push(ts_poet_1.code `
1032
- ${fieldName}: Array.isArray(object?.${jsonName}) ? object.${jsonName}.map((e: any) => ${readValueSnippet}): [],
1034
+ ${fieldName}: Array.isArray(${jsonPropertyOptional}) ? ${jsonProperty}.map((e: any) => ${readValueSnippet}): [],
1033
1035
  `);
1034
1036
  }
1035
1037
  }
@@ -1042,36 +1044,36 @@ function generateFromJson(ctx, fullName, messageDesc) {
1042
1044
  const fieldName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
1043
1045
  chunks.push(ts_poet_1.code `${fieldName}: `);
1044
1046
  }
1045
- const ternaryIf = ts_poet_1.code `${ctx.utils.isSet}(object.${jsonName})`;
1046
- const ternaryThen = ts_poet_1.code `{ $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${jsonName}`)}`;
1047
+ const ternaryIf = ts_poet_1.code `${ctx.utils.isSet}(${jsonProperty})`;
1048
+ const ternaryThen = ts_poet_1.code `{ $case: '${fieldName}', ${fieldName}: ${readSnippet(`${jsonProperty}`)}`;
1047
1049
  chunks.push(ts_poet_1.code `${ternaryIf} ? ${ternaryThen}} : `);
1048
1050
  if (field === lastCase) {
1049
1051
  chunks.push(ts_poet_1.code `undefined,`);
1050
1052
  }
1051
1053
  }
1052
1054
  else if (types_1.isAnyValueType(field)) {
1053
- chunks.push(ts_poet_1.code `${fieldName}: ${ctx.utils.isSet}(object?.${jsonName})
1054
- ? ${readSnippet(`object.${jsonName}`)}
1055
+ chunks.push(ts_poet_1.code `${fieldName}: ${ctx.utils.isSet}(${jsonPropertyOptional})
1056
+ ? ${readSnippet(`${jsonProperty}`)}
1055
1057
  : undefined,
1056
1058
  `);
1057
1059
  }
1058
1060
  else if (types_1.isStructType(field)) {
1059
- chunks.push(ts_poet_1.code `${fieldName}: ${ctx.utils.isObject}(object.${jsonName})
1060
- ? ${readSnippet(`object.${jsonName}`)}
1061
+ chunks.push(ts_poet_1.code `${fieldName}: ${ctx.utils.isObject}(${jsonProperty})
1062
+ ? ${readSnippet(`${jsonProperty}`)}
1061
1063
  : undefined,`);
1062
1064
  }
1063
1065
  else if (types_1.isListValueType(field)) {
1064
1066
  chunks.push(ts_poet_1.code `
1065
- ${fieldName}: Array.isArray(object.${jsonName})
1066
- ? ${readSnippet(`object.${jsonName}`)}
1067
+ ${fieldName}: Array.isArray(${jsonProperty})
1068
+ ? ${readSnippet(`${jsonProperty}`)}
1067
1069
  : undefined,
1068
1070
  `);
1069
1071
  }
1070
1072
  else {
1071
1073
  const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
1072
1074
  chunks.push(ts_poet_1.code `
1073
- ${fieldName}: ${ctx.utils.isSet}(object.${jsonName})
1074
- ? ${readSnippet(`object.${jsonName}`)}
1075
+ ${fieldName}: ${ctx.utils.isSet}(${jsonProperty})
1076
+ ? ${readSnippet(`${jsonProperty}`)}
1075
1077
  : ${fallback},
1076
1078
  `);
1077
1079
  }
@@ -1092,7 +1094,8 @@ function generateToJson(ctx, fullName, messageDesc) {
1092
1094
  // then add a case for each field
1093
1095
  messageDesc.field.forEach((field) => {
1094
1096
  const fieldName = case_1.maybeSnakeToCamel(field.name, options);
1095
- const jsonName = utils_1.determineFieldJsonName(field, options);
1097
+ const jsonName = utils_1.getFieldJsonName(field, options);
1098
+ const jsonProperty = utils_1.getPropertyAccessor('obj', jsonName);
1096
1099
  const readSnippet = (from) => {
1097
1100
  if (types_1.isEnum(field)) {
1098
1101
  const toJson = types_1.getEnumMethod(ctx, field.typeName, 'ToJSON');
@@ -1183,10 +1186,10 @@ function generateToJson(ctx, fullName, messageDesc) {
1183
1186
  if (types_1.isMapType(ctx, messageDesc, field)) {
1184
1187
  // Maps might need their values transformed, i.e. bytes --> base64
1185
1188
  chunks.push(ts_poet_1.code `
1186
- obj.${jsonName} = {};
1189
+ ${jsonProperty} = {};
1187
1190
  if (message.${fieldName}) {
1188
1191
  Object.entries(message.${fieldName}).forEach(([k, v]) => {
1189
- obj.${jsonName}[k] = ${readSnippet('v')};
1192
+ ${jsonProperty}[k] = ${readSnippet('v')};
1190
1193
  });
1191
1194
  }
1192
1195
  `);
@@ -1195,9 +1198,9 @@ function generateToJson(ctx, fullName, messageDesc) {
1195
1198
  // Arrays might need their elements transformed
1196
1199
  chunks.push(ts_poet_1.code `
1197
1200
  if (message.${fieldName}) {
1198
- obj.${jsonName} = message.${fieldName}.map(e => ${readSnippet('e')});
1201
+ ${jsonProperty} = message.${fieldName}.map(e => ${readSnippet('e')});
1199
1202
  } else {
1200
- obj.${jsonName} = [];
1203
+ ${jsonProperty} = [];
1201
1204
  }
1202
1205
  `);
1203
1206
  }
@@ -1205,11 +1208,11 @@ function generateToJson(ctx, fullName, messageDesc) {
1205
1208
  // oneofs in a union are only output as `oneof name = ...`
1206
1209
  const oneofName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
1207
1210
  const v = readSnippet(`message.${oneofName}?.${fieldName}`);
1208
- chunks.push(ts_poet_1.code `message.${oneofName}?.$case === '${fieldName}' && (obj.${jsonName} = ${v});`);
1211
+ chunks.push(ts_poet_1.code `message.${oneofName}?.$case === '${fieldName}' && (${jsonProperty} = ${v});`);
1209
1212
  }
1210
1213
  else {
1211
1214
  const v = readSnippet(`message.${fieldName}`);
1212
- chunks.push(ts_poet_1.code `message.${fieldName} !== undefined && (obj.${jsonName} = ${v});`);
1215
+ chunks.push(ts_poet_1.code `message.${fieldName} !== undefined && (${jsonProperty} = ${v});`);
1213
1216
  }
1214
1217
  });
1215
1218
  chunks.push(ts_poet_1.code `return obj;`);
package/build/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.impProto = exports.determineFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.protoFilesToGenerate = void 0;
3
+ exports.impProto = exports.getPropertyAccessor = exports.getFieldJsonName = exports.FormattedMethodDescriptor = exports.assertInstanceOf = exports.maybePrefixPackage = exports.prefixDisableLinter = exports.maybeAddComment = exports.upperFirst = exports.lowerFirst = exports.singular = exports.fail = exports.readToBuffer = exports.protoFilesToGenerate = void 0;
4
4
  const ts_poet_1 = require("ts-poet");
5
5
  const options_1 = require("./options");
6
6
  const case_1 = require("./case");
@@ -144,7 +144,7 @@ class FormattedMethodDescriptor {
144
144
  }
145
145
  }
146
146
  exports.FormattedMethodDescriptor = FormattedMethodDescriptor;
147
- function determineFieldJsonName(field, options) {
147
+ function getFieldJsonName(field, options) {
148
148
  // jsonName will be camelCased by the protocol compiler, plus can be overridden by the user,
149
149
  // so just use that instead of our own maybeSnakeToCamel
150
150
  if (options.snakeToCamel.includes('json')) {
@@ -154,7 +154,21 @@ function determineFieldJsonName(field, options) {
154
154
  return field.name;
155
155
  }
156
156
  }
157
- exports.determineFieldJsonName = determineFieldJsonName;
157
+ exports.getFieldJsonName = getFieldJsonName;
158
+ /**
159
+ * Returns a snippet for reading an object's property, such as `foo.bar`, or `foo['bar']` if the property name contains unusual characters.
160
+ * For simplicity, we don't match the ECMA 5/6 rules for valid identifiers exactly, and return array syntax liberally.
161
+ * @param objectName
162
+ * @param propertyName
163
+ * @param optional
164
+ */
165
+ function getPropertyAccessor(objectName, propertyName, optional = false) {
166
+ let validIdentifier = /^[a-zA-Z_$][\w$]*$/;
167
+ return validIdentifier.test(propertyName)
168
+ ? `${objectName}${optional ? '?' : ''}.${propertyName}`
169
+ : `${objectName}${optional ? '?.' : ''}[${JSON.stringify(propertyName)}]`;
170
+ }
171
+ exports.getPropertyAccessor = getPropertyAccessor;
158
172
  function impProto(options, module, type) {
159
173
  return ts_poet_1.imp(`${type}@./${module}${options.fileSuffix}`);
160
174
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-proto",
3
- "version": "1.105.2",
3
+ "version": "1.106.2",
4
4
  "description": "",
5
5
  "main": "build/plugin.js",
6
6
  "repository": "github:stephenh/ts-proto",