ts-proto 1.97.0 → 1.99.0
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 +28 -0
- package/README.markdown +17 -1
- package/build/main.js +115 -40
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
# [1.99.0](https://github.com/stephenh/ts-proto/compare/v1.98.0...v1.99.0) (2022-01-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* yarn watch updates (specified) tests when source files change ([#465](https://github.com/stephenh/ts-proto/issues/465)) ([275d0e7](https://github.com/stephenh/ts-proto/commit/275d0e7c61f3acb2b1fd670b1974e64dd49d6ff4))
|
|
7
|
+
|
|
8
|
+
# [1.98.0](https://github.com/stephenh/ts-proto/compare/v1.97.2...v1.98.0) (2022-01-06)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* watch for changed integration test files ([#464](https://github.com/stephenh/ts-proto/issues/464)) ([988cd7e](https://github.com/stephenh/ts-proto/commit/988cd7eb84bc3b8b72d6b4d59c38aa794c16c638))
|
|
14
|
+
|
|
15
|
+
## [1.97.2](https://github.com/stephenh/ts-proto/compare/v1.97.1...v1.97.2) (2022-01-06)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Performance Improvements
|
|
19
|
+
|
|
20
|
+
* fromJSON returns object literal to allow v8 optimizations ([#463](https://github.com/stephenh/ts-proto/issues/463)) ([5fcd05b](https://github.com/stephenh/ts-proto/commit/5fcd05b79e7c02547c4b6db46fae7a7202f97629))
|
|
21
|
+
|
|
22
|
+
## [1.97.1](https://github.com/stephenh/ts-proto/compare/v1.97.0...v1.97.1) (2022-01-05)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* oneof=union breaks wrapper types [#458](https://github.com/stephenh/ts-proto/issues/458) ([#462](https://github.com/stephenh/ts-proto/issues/462)) ([dd16992](https://github.com/stephenh/ts-proto/commit/dd16992a409f24e88e3a142830cd0745f50dbd10))
|
|
28
|
+
|
|
1
29
|
# [1.97.0](https://github.com/stephenh/ts-proto/compare/v1.96.1...v1.97.0) (2021-12-30)
|
|
2
30
|
|
|
3
31
|
|
package/README.markdown
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
- [Table of contents](#table-of-contents)
|
|
14
14
|
- [Overview](#overview)
|
|
15
15
|
- [QuickStart](#quickstart)
|
|
16
|
+
- [Buf](#buf)
|
|
16
17
|
- [Goals](#goals)
|
|
17
18
|
- [Example Types](#example-types)
|
|
18
19
|
- [Highlights](#highlights)
|
|
@@ -84,6 +85,19 @@ This will generate `*.ts` source files for the given `*.proto` types.
|
|
|
84
85
|
|
|
85
86
|
If you want to package these source files into an npm package to distribute to clients, just run `tsc` on them as usual to generate the `.js`/`.d.ts` files, and deploy the output as a regular npm package.
|
|
86
87
|
|
|
88
|
+
## Buf
|
|
89
|
+
|
|
90
|
+
If you're using Buf, pass `strategy: all` in your `buf.gen.yaml` file ([docs](https://docs.buf.build/configuration/v1/buf-gen-yaml#strategy)).
|
|
91
|
+
|
|
92
|
+
```yaml
|
|
93
|
+
version: v1
|
|
94
|
+
plugins:
|
|
95
|
+
- name: ts
|
|
96
|
+
out: ../gen/ts
|
|
97
|
+
strategy: all
|
|
98
|
+
path: ../node_modules/ts-proto/protoc-gen-ts_proto
|
|
99
|
+
```
|
|
100
|
+
|
|
87
101
|
# Goals
|
|
88
102
|
|
|
89
103
|
- Idiomatic TypeScript/ES6 types
|
|
@@ -404,11 +418,13 @@ The commands below assume you have **Docker** installed. To use a **local** copy
|
|
|
404
418
|
**Workflow**
|
|
405
419
|
|
|
406
420
|
- Modifying the plugin implementation:
|
|
421
|
+
- The most important logic is found in [src/main.ts](src/main.ts).
|
|
407
422
|
- Run `yarn bin2ts` or `yarn bin2ts:local`.
|
|
408
423
|
_Since the proto files were not changed, you only need to regenerate the typescript files._
|
|
409
424
|
- Run `yarn test` to verify the typescript files are compatible with the reference implementation, and pass other tests.
|
|
410
425
|
- Updating or adding `.proto` files in the integration directory:
|
|
411
|
-
- Run `yarn
|
|
426
|
+
- Run `yarn watch` to automatically regenerate test files when proto files change.
|
|
427
|
+
- Or run `yarn build:test` to regenerate all integration test files.
|
|
412
428
|
- Run `yarn test` to retest.
|
|
413
429
|
|
|
414
430
|
**Contributing**
|
package/build/main.js
CHANGED
|
@@ -86,8 +86,8 @@ function generateFile(ctx, fileDesc) {
|
|
|
86
86
|
if (options.outputPartialMethods) {
|
|
87
87
|
staticMembers.push(generateFromPartial(ctx, fullName, message));
|
|
88
88
|
}
|
|
89
|
-
staticMembers.push(...generateWrap(fullTypeName));
|
|
90
|
-
staticMembers.push(...generateUnwrap(fullTypeName));
|
|
89
|
+
staticMembers.push(...generateWrap(ctx, fullTypeName));
|
|
90
|
+
staticMembers.push(...generateUnwrap(ctx, fullTypeName));
|
|
91
91
|
chunks.push(ts_poet_1.code `
|
|
92
92
|
export const ${ts_poet_1.def(fullName)} = {
|
|
93
93
|
${ts_poet_1.joinCode(staticMembers, { on: ',\n\n' })}
|
|
@@ -195,6 +195,7 @@ function makeUtils(options) {
|
|
|
195
195
|
...makeDeepPartial(options, longs),
|
|
196
196
|
...makeTimestampMethods(options, longs),
|
|
197
197
|
...longs,
|
|
198
|
+
...makeComparisonUtils(),
|
|
198
199
|
};
|
|
199
200
|
}
|
|
200
201
|
exports.makeUtils = makeUtils;
|
|
@@ -396,6 +397,17 @@ function makeTimestampMethods(options, longs) {
|
|
|
396
397
|
`);
|
|
397
398
|
return { toTimestamp, fromTimestamp, fromJsonTimestamp };
|
|
398
399
|
}
|
|
400
|
+
function makeComparisonUtils() {
|
|
401
|
+
const isObject = ts_poet_1.conditionalOutput('isObject', ts_poet_1.code `
|
|
402
|
+
function isObject(value: any): boolean {
|
|
403
|
+
return typeof value === 'object' && value !== null;
|
|
404
|
+
}`);
|
|
405
|
+
const isSet = ts_poet_1.conditionalOutput('isSet', ts_poet_1.code `
|
|
406
|
+
function isSet(value: any): boolean {
|
|
407
|
+
return value !== null && value !== undefined;
|
|
408
|
+
}`);
|
|
409
|
+
return { isObject, isSet };
|
|
410
|
+
}
|
|
399
411
|
// Create the interface with properties
|
|
400
412
|
function generateInterfaceDeclaration(ctx, fullName, messageDesc, sourceInfo, fullTypeName) {
|
|
401
413
|
var _a;
|
|
@@ -805,13 +817,17 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
805
817
|
// create the basic function declaration
|
|
806
818
|
chunks.push(ts_poet_1.code `
|
|
807
819
|
fromJSON(${messageDesc.field.length > 0 ? 'object' : '_'}: any): ${fullName} {
|
|
808
|
-
|
|
820
|
+
return {
|
|
809
821
|
`);
|
|
822
|
+
if (ctx.options.outputTypeRegistry) {
|
|
823
|
+
chunks.push(ts_poet_1.code `$type: ${fullName}.$type,`);
|
|
824
|
+
}
|
|
825
|
+
const oneofFieldsCases = messageDesc.oneofDecl.map((oneof, oneofIndex) => messageDesc.field.filter(types_1.isWithinOneOf).filter((field) => field.oneofIndex === oneofIndex));
|
|
810
826
|
// add a check for each incoming field
|
|
811
827
|
messageDesc.field.forEach((field) => {
|
|
812
828
|
const fieldName = case_1.maybeSnakeToCamel(field.name, options);
|
|
813
829
|
const jsonName = utils_1.determineFieldJsonName(field, options);
|
|
814
|
-
// get
|
|
830
|
+
// get code that extracts value from incoming object
|
|
815
831
|
const readSnippet = (from) => {
|
|
816
832
|
if (types_1.isEnum(field)) {
|
|
817
833
|
const fromJson = types_1.getEnumMethod(ctx, field.typeName, 'FromJSON');
|
|
@@ -846,6 +862,9 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
846
862
|
else if (types_1.isAnyValueType(field) || types_1.isStructType(field)) {
|
|
847
863
|
return ts_poet_1.code `${from}`;
|
|
848
864
|
}
|
|
865
|
+
else if (types_1.isListValueType(field)) {
|
|
866
|
+
return ts_poet_1.code `[...${from}]`;
|
|
867
|
+
}
|
|
849
868
|
else if (types_1.isValueType(ctx, field)) {
|
|
850
869
|
const valueType = types_1.valueTypeName(ctx, field.typeName);
|
|
851
870
|
if (types_1.isLongValueType(field) && options.forceLong === options_1.LongOption.LONG) {
|
|
@@ -854,9 +873,6 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
854
873
|
else if (types_1.isBytesValueType(field)) {
|
|
855
874
|
return ts_poet_1.code `new ${case_1.capitalize(valueType.toCodeString())}(${from})`;
|
|
856
875
|
}
|
|
857
|
-
else if (types_1.isListValueType(field)) {
|
|
858
|
-
return ts_poet_1.code `[...${from}]`;
|
|
859
|
-
}
|
|
860
876
|
else {
|
|
861
877
|
return ts_poet_1.code `${case_1.capitalize(valueType.toCodeString())}(${from})`;
|
|
862
878
|
}
|
|
@@ -919,56 +935,71 @@ function generateFromJson(ctx, fullName, messageDesc) {
|
|
|
919
935
|
const fieldType = types_1.toTypeName(ctx, messageDesc, field);
|
|
920
936
|
const i = maybeCastToNumber(ctx, messageDesc, field, 'key');
|
|
921
937
|
chunks.push(ts_poet_1.code `
|
|
922
|
-
|
|
923
|
-
acc[
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
}
|
|
928
|
-
else if (types_1.isAnyValueType(field)) {
|
|
929
|
-
chunks.push(ts_poet_1.code `
|
|
930
|
-
message.${fieldName} = Array.isArray(object?.${jsonName}) ? [...object.${jsonName}] : [];
|
|
938
|
+
${fieldName}: ${ctx.utils.isObject}(object.${jsonName})
|
|
939
|
+
? Object.entries(object.${jsonName}).reduce<${fieldType}>((acc, [key, value]) => {
|
|
940
|
+
acc[${i}] = ${readSnippet('value')};
|
|
941
|
+
return acc;
|
|
942
|
+
}, {})
|
|
943
|
+
: {},
|
|
931
944
|
`);
|
|
932
945
|
}
|
|
933
946
|
else {
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
947
|
+
const readValueSnippet = readSnippet('e');
|
|
948
|
+
if (readValueSnippet.toString() === ts_poet_1.code `e`.toString()) {
|
|
949
|
+
chunks.push(ts_poet_1.code `${fieldName}: Array.isArray(object?.${jsonName}) ? [...object.${jsonName}] : [],`);
|
|
950
|
+
}
|
|
951
|
+
else {
|
|
952
|
+
// Explicit `any` type required to make TS with noImplicitAny happy. `object` is also `any` here.
|
|
953
|
+
chunks.push(ts_poet_1.code `
|
|
954
|
+
${fieldName}: Array.isArray(object?.${jsonName}) ? object.${jsonName}.map((e: any) => ${readValueSnippet}): [],
|
|
955
|
+
`);
|
|
956
|
+
}
|
|
938
957
|
}
|
|
939
958
|
}
|
|
940
959
|
else if (types_1.isWithinOneOfThatShouldBeUnion(options, field)) {
|
|
941
|
-
|
|
942
|
-
const
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
960
|
+
const cases = oneofFieldsCases[field.oneofIndex];
|
|
961
|
+
const firstCase = cases[0];
|
|
962
|
+
const lastCase = cases[cases.length - 1];
|
|
963
|
+
if (field === firstCase) {
|
|
964
|
+
const fieldName = case_1.maybeSnakeToCamel(messageDesc.oneofDecl[field.oneofIndex].name, options);
|
|
965
|
+
chunks.push(ts_poet_1.code `${fieldName}: `);
|
|
966
|
+
}
|
|
967
|
+
const ternaryIf = ts_poet_1.code `${ctx.utils.isSet}(object.${jsonName})`;
|
|
968
|
+
const ternaryThen = ts_poet_1.code `{ $case: '${fieldName}', ${fieldName}: ${readSnippet(`object.${jsonName}`)}`;
|
|
969
|
+
chunks.push(ts_poet_1.code `${ternaryIf} ? ${ternaryThen}} : `);
|
|
970
|
+
if (field === lastCase) {
|
|
971
|
+
chunks.push(ts_poet_1.code `undefined,`);
|
|
972
|
+
}
|
|
947
973
|
}
|
|
948
974
|
else if (types_1.isAnyValueType(field)) {
|
|
949
|
-
chunks.push(ts_poet_1.code
|
|
975
|
+
chunks.push(ts_poet_1.code `${fieldName}: ${ctx.utils.isSet}(object?.${jsonName})
|
|
976
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
977
|
+
: undefined,
|
|
978
|
+
`);
|
|
950
979
|
}
|
|
951
980
|
else if (types_1.isStructType(field)) {
|
|
952
|
-
chunks.push(ts_poet_1.code
|
|
981
|
+
chunks.push(ts_poet_1.code `${fieldName}: ${ctx.utils.isObject}(object.${jsonName})
|
|
982
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
983
|
+
: undefined,`);
|
|
953
984
|
}
|
|
954
985
|
else if (types_1.isListValueType(field)) {
|
|
955
986
|
chunks.push(ts_poet_1.code `
|
|
956
|
-
|
|
957
|
-
? ${readSnippet(`object.${
|
|
958
|
-
:
|
|
987
|
+
${fieldName}: Array.isArray(object.${jsonName})
|
|
988
|
+
? ${readSnippet(`object.${jsonName}`)}
|
|
989
|
+
: undefined,
|
|
959
990
|
`);
|
|
960
991
|
}
|
|
961
992
|
else {
|
|
962
993
|
const fallback = types_1.isWithinOneOf(field) ? 'undefined' : types_1.defaultValue(ctx, field);
|
|
963
994
|
chunks.push(ts_poet_1.code `
|
|
964
|
-
|
|
995
|
+
${fieldName}: ${ctx.utils.isSet}(object.${jsonName})
|
|
965
996
|
? ${readSnippet(`object.${jsonName}`)}
|
|
966
|
-
: ${fallback}
|
|
997
|
+
: ${fallback},
|
|
967
998
|
`);
|
|
968
999
|
}
|
|
969
1000
|
});
|
|
970
1001
|
// and then wrap up the switch/while/return
|
|
971
|
-
chunks.push(ts_poet_1.code `
|
|
1002
|
+
chunks.push(ts_poet_1.code `};`);
|
|
972
1003
|
chunks.push(ts_poet_1.code `}`);
|
|
973
1004
|
return ts_poet_1.joinCode(chunks, { on: '\n' });
|
|
974
1005
|
}
|
|
@@ -1223,7 +1254,7 @@ function generateFromPartial(ctx, fullName, messageDesc) {
|
|
|
1223
1254
|
chunks.push(ts_poet_1.code `}`);
|
|
1224
1255
|
return ts_poet_1.joinCode(chunks, { on: '\n' });
|
|
1225
1256
|
}
|
|
1226
|
-
function generateWrap(fullProtoTypeName) {
|
|
1257
|
+
function generateWrap(ctx, fullProtoTypeName) {
|
|
1227
1258
|
const chunks = [];
|
|
1228
1259
|
if (types_1.isStructTypeName(fullProtoTypeName)) {
|
|
1229
1260
|
chunks.push(ts_poet_1.code `wrap(object: {[key: string]: any} | undefined): Struct {
|
|
@@ -1237,7 +1268,29 @@ function generateWrap(fullProtoTypeName) {
|
|
|
1237
1268
|
}`);
|
|
1238
1269
|
}
|
|
1239
1270
|
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1240
|
-
|
|
1271
|
+
if (ctx.options.oneof === options_1.OneofOption.UNIONS) {
|
|
1272
|
+
chunks.push(ts_poet_1.code `wrap(value: any): Value {
|
|
1273
|
+
if (value === null) {
|
|
1274
|
+
return {kind: {$case: 'nullValue', nullValue: NullValue.NULL_VALUE}};
|
|
1275
|
+
} else if (typeof value === 'boolean') {
|
|
1276
|
+
return {kind: {$case: 'boolValue', boolValue: value}};
|
|
1277
|
+
} else if (typeof value === 'number') {
|
|
1278
|
+
return {kind: {$case: 'numberValue', numberValue: value}};
|
|
1279
|
+
} else if (typeof value === 'string') {
|
|
1280
|
+
return {kind: {$case: 'stringValue', stringValue: value}};
|
|
1281
|
+
} else if (Array.isArray(value)) {
|
|
1282
|
+
return {kind: {$case: 'listValue', listValue: value}};
|
|
1283
|
+
} else if (typeof value === 'object') {
|
|
1284
|
+
return {kind: {$case: 'structValue', structValue: value}};
|
|
1285
|
+
} else if (typeof value === 'undefined') {
|
|
1286
|
+
return {} as Value;
|
|
1287
|
+
} else {
|
|
1288
|
+
throw new Error('Unsupported any value type: ' + typeof value);
|
|
1289
|
+
}
|
|
1290
|
+
}`);
|
|
1291
|
+
}
|
|
1292
|
+
else {
|
|
1293
|
+
chunks.push(ts_poet_1.code `wrap(value: any): Value {
|
|
1241
1294
|
if (value === null) {
|
|
1242
1295
|
return {nullValue: NullValue.NULL_VALUE} as Value;
|
|
1243
1296
|
} else if (typeof value === 'boolean') {
|
|
@@ -1256,15 +1309,16 @@ function generateWrap(fullProtoTypeName) {
|
|
|
1256
1309
|
throw new Error('Unsupported any value type: ' + typeof value);
|
|
1257
1310
|
}
|
|
1258
1311
|
}`);
|
|
1312
|
+
}
|
|
1259
1313
|
}
|
|
1260
1314
|
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
|
1261
|
-
chunks.push(ts_poet_1.code `wrap(value: Array<any>): ListValue {
|
|
1262
|
-
return {values: value};
|
|
1315
|
+
chunks.push(ts_poet_1.code `wrap(value: Array<any> | undefined): ListValue {
|
|
1316
|
+
return {values: value ?? []};
|
|
1263
1317
|
}`);
|
|
1264
1318
|
}
|
|
1265
1319
|
return chunks;
|
|
1266
1320
|
}
|
|
1267
|
-
function generateUnwrap(fullProtoTypeName) {
|
|
1321
|
+
function generateUnwrap(ctx, fullProtoTypeName) {
|
|
1268
1322
|
const chunks = [];
|
|
1269
1323
|
if (types_1.isStructTypeName(fullProtoTypeName)) {
|
|
1270
1324
|
chunks.push(ts_poet_1.code `unwrap(message: Struct): {[key: string]: any} {
|
|
@@ -1276,7 +1330,27 @@ function generateUnwrap(fullProtoTypeName) {
|
|
|
1276
1330
|
}`);
|
|
1277
1331
|
}
|
|
1278
1332
|
if (types_1.isAnyValueTypeName(fullProtoTypeName)) {
|
|
1279
|
-
|
|
1333
|
+
if (ctx.options.oneof === options_1.OneofOption.UNIONS) {
|
|
1334
|
+
chunks.push(ts_poet_1.code `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
1335
|
+
if (message.kind?.$case === 'nullValue') {
|
|
1336
|
+
return null;
|
|
1337
|
+
} else if (message.kind?.$case === 'numberValue') {
|
|
1338
|
+
return message.kind?.numberValue;
|
|
1339
|
+
} else if (message.kind?.$case === 'stringValue') {
|
|
1340
|
+
return message.kind?.stringValue;
|
|
1341
|
+
} else if (message.kind?.$case === 'boolValue') {
|
|
1342
|
+
return message.kind?.boolValue;
|
|
1343
|
+
} else if (message.kind?.$case === 'structValue') {
|
|
1344
|
+
return message.kind?.structValue;
|
|
1345
|
+
} else if (message.kind?.$case === 'listValue') {
|
|
1346
|
+
return message.kind?.listValue;
|
|
1347
|
+
} else {
|
|
1348
|
+
return undefined;
|
|
1349
|
+
}
|
|
1350
|
+
}`);
|
|
1351
|
+
}
|
|
1352
|
+
else {
|
|
1353
|
+
chunks.push(ts_poet_1.code `unwrap(message: Value): string | number | boolean | Object | null | Array<any> | undefined {
|
|
1280
1354
|
if (message?.stringValue !== undefined) {
|
|
1281
1355
|
return message.stringValue;
|
|
1282
1356
|
} else if (message?.numberValue !== undefined) {
|
|
@@ -1292,6 +1366,7 @@ function generateUnwrap(fullProtoTypeName) {
|
|
|
1292
1366
|
}
|
|
1293
1367
|
return undefined;
|
|
1294
1368
|
}`);
|
|
1369
|
+
}
|
|
1295
1370
|
}
|
|
1296
1371
|
if (types_1.isListValueTypeName(fullProtoTypeName)) {
|
|
1297
1372
|
chunks.push(ts_poet_1.code `unwrap(message: ListValue): Array<any> {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ts-proto",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.99.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/plugin.js",
|
|
6
6
|
"repository": "github:stephenh/ts-proto",
|
|
@@ -19,9 +19,10 @@
|
|
|
19
19
|
"proto2pbjs:local": "integration/pbjs.sh",
|
|
20
20
|
"bin2ts:local": "integration/codegen.sh",
|
|
21
21
|
"test": "yarn jest -c jest.config.js --maxWorkers=2",
|
|
22
|
-
"prettier": "prettier --write {src,tests}/**/*.ts",
|
|
22
|
+
"prettier": "prettier --write {src,tests}/**/*.ts integration/*.ts",
|
|
23
23
|
"prettier:check": "prettier --list-different {src,tests}/**/*.ts",
|
|
24
|
-
"setup:docker": "docker-compose build"
|
|
24
|
+
"setup:docker": "docker-compose build",
|
|
25
|
+
"watch": "ts-node integration/watch.ts"
|
|
25
26
|
},
|
|
26
27
|
"files": [
|
|
27
28
|
"build"
|
|
@@ -45,6 +46,7 @@
|
|
|
45
46
|
"@semantic-release/release-notes-generator": "^9.0.2",
|
|
46
47
|
"@types/jest": "^26.0.22",
|
|
47
48
|
"@types/node": "^14.14.37",
|
|
49
|
+
"chokidar": "^3.5.2",
|
|
48
50
|
"jest": "^26.6.3",
|
|
49
51
|
"prettier": "^2.2.1",
|
|
50
52
|
"reflect-metadata": "^0.1.13",
|