initial commit of actions

This commit is contained in:
Dominik Polakovics Polakovics 2026-01-31 18:56:04 +01:00
commit 949ece5785
44660 changed files with 12034344 additions and 0 deletions

View file

@ -0,0 +1,174 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

View file

@ -0,0 +1,37 @@
@protobuf-ts/plugin
===================
The protocol buffer compiler plugin for TypeScript: [protobuf-ts](https://github.com/timostamm/protobuf-ts)
Installation:
```shell script
# with npm:
npm install -D @protobuf-ts/plugin
# with yarn:
yarn add --dev @protobuf-ts/plugin
```
This will install the plugin as a development dependency.
Basic usage:
```shell script
npx protoc --ts_out . --proto_path protos protos/my.proto
```
With some options:
```shell script
npx protoc \
--ts_out . \
--ts_opt long_type_string \
--ts_opt optimize_code_size \
--proto_path protos \
protos/my.proto
```
`protoc` is the protocol buffer compiler. [protobuf-ts](https://github.com/timostamm/protobuf-ts)
installs it automatically.
Plugin parameters are documented in the [MANUAL](https://github.com/timostamm/protobuf-ts/blob/master/MANUAL.md#the-protoc-plugin).
For a quick overview of [protobuf-ts](https://github.com/timostamm/protobuf-ts), check the repository [README](https://github.com/timostamm/protobuf-ts/blob/master/README.md).

Binary file not shown.

View file

@ -0,0 +1,8 @@
#!/usr/bin/env node
const {DumpPlugin} = require("../build/dump-plugin");
new DumpPlugin().run().catch(_ => {
process.stderr.write('failed to run plugin');
process.exit(1);
});

View file

@ -0,0 +1,9 @@
#!/usr/bin/env node
const {ProtobuftsPlugin} = require("../build/protobufts-plugin");
const pkg = require("../package.json");
new ProtobuftsPlugin(pkg.version).run().catch(_ => {
process.stderr.write('failed to run plugin');
process.exit(1);
});

View file

@ -0,0 +1,48 @@
import * as ts from "typescript";
import { AnyDescriptorProto, DescriptorRegistry } from "@protobuf-ts/plugin-framework";
export declare class CommentGenerator {
private readonly registry;
constructor(registry: DescriptorRegistry);
/**
* Adds comments from the .proto as a JSDoc block.
*
* Looks up comments for the given descriptor in
* the source code info.
*
* Adds `@deprecated` tag if the element is
* marked deprecated. Also adds @deprecated if
* the descriptor is a type (enum, message) and
* the entire .proto file is marked deprecated.
*
* Adds `@generated` tag with source code
* information.
*
* Leading detached comments are added as line
* comments in front of the JSDoc block.
*
* Trailing comments are a bit weird. For .proto
* enums and messages, they sit between open
* bracket and first member. A message seems to
* only ever have a trailing comment if it is
* empty. For a simple solution, trailing
* comments on enums and messages should simply
* be appended to the leading block so that the
* information is not discarded.
*/
addCommentsForDescriptor(node: ts.Node, descriptor: AnyDescriptorProto, trailingCommentsMode: 'appendToLeadingBlock' | 'trailingLines'): void;
/**
* Returns a block of source comments (no leading detached!),
* with @generated tags and @deprecated tag (if applicable).
*/
getCommentBlock(descriptor: AnyDescriptorProto, appendTrailingComments?: boolean): string;
/**
* Returns "@deprecated\n" if explicitly deprecated.
* For top level types, also returns "@deprecated\n" if entire file is deprecated.
* Otherwise, returns "".
*/
makeDeprecatedTag(descriptor: AnyDescriptorProto): "" | "@deprecated\n";
/**
* Creates string like "@generated from protobuf field: string foo = 1;"
*/
makeGeneratedTag(descriptor: AnyDescriptorProto): string;
}

View file

@ -0,0 +1,117 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CommentGenerator = void 0;
const ts = require("typescript");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
class CommentGenerator {
constructor(registry) {
this.registry = registry;
}
/**
* Adds comments from the .proto as a JSDoc block.
*
* Looks up comments for the given descriptor in
* the source code info.
*
* Adds `@deprecated` tag if the element is
* marked deprecated. Also adds @deprecated if
* the descriptor is a type (enum, message) and
* the entire .proto file is marked deprecated.
*
* Adds `@generated` tag with source code
* information.
*
* Leading detached comments are added as line
* comments in front of the JSDoc block.
*
* Trailing comments are a bit weird. For .proto
* enums and messages, they sit between open
* bracket and first member. A message seems to
* only ever have a trailing comment if it is
* empty. For a simple solution, trailing
* comments on enums and messages should simply
* be appended to the leading block so that the
* information is not discarded.
*/
addCommentsForDescriptor(node, descriptor, trailingCommentsMode) {
const source = this.registry.sourceCodeComments(descriptor);
// add leading detached comments as line comments
plugin_framework_1.addCommentBlocksAsLeadingDetachedLines(node, ...source.leadingDetached);
// start with leading block
let leading = this.getCommentBlock(descriptor, trailingCommentsMode === "appendToLeadingBlock");
// add leading block as jsdoc comment block
plugin_framework_1.addCommentBlockAsJsDoc(node, leading);
// add trailing comments as trailing line comments
if (source.trailing && trailingCommentsMode === 'trailingLines') {
let lines = source.trailing.split('\n').map(l => l[0] !== ' ' ? ` ${l}` : l);
for (let line of lines) {
ts.addSyntheticTrailingComment(node, ts.SyntaxKind.SingleLineCommentTrivia, line, true);
}
}
}
/**
* Returns a block of source comments (no leading detached!),
* with @generated tags and @deprecated tag (if applicable).
*/
getCommentBlock(descriptor, appendTrailingComments = false) {
var _a;
const source = this.registry.sourceCodeComments(descriptor);
// start with leading block
let commentBlock = (_a = source.leading) !== null && _a !== void 0 ? _a : '';
// add trailing comments to the leading block
if (source.trailing && appendTrailingComments) {
if (commentBlock.length > 0) {
commentBlock += '\n\n';
}
commentBlock += source.trailing;
}
// if there were any leading comments, we need some space
if (commentBlock.length > 0) {
commentBlock += '\n\n';
}
// add deprecated information to the leading block
commentBlock += this.makeDeprecatedTag(descriptor);
// add source info to the leading block
commentBlock += this.makeGeneratedTag(descriptor);
return commentBlock;
}
/**
* Returns "@deprecated\n" if explicitly deprecated.
* For top level types, also returns "@deprecated\n" if entire file is deprecated.
* Otherwise, returns "".
*/
makeDeprecatedTag(descriptor) {
let deprecated = this.registry.isExplicitlyDeclaredDeprecated(descriptor);
if (!deprecated && plugin_framework_1.isAnyTypeDescriptorProto(descriptor)) {
// an entire .proto file can be marked deprecated.
// this means all types within are deprecated.
// we mark them as deprecated, but dont touch members.
deprecated = this.registry.isExplicitlyDeclaredDeprecated(this.registry.fileOf(descriptor));
}
if (deprecated) {
return '@deprecated\n';
}
return '';
}
/**
* Creates string like "@generated from protobuf field: string foo = 1;"
*/
makeGeneratedTag(descriptor) {
if (plugin_framework_1.OneofDescriptorProto.is(descriptor)) {
return `@generated from protobuf oneof: ${descriptor.name}`;
}
else if (plugin_framework_1.EnumValueDescriptorProto.is(descriptor)) {
return `@generated from protobuf enum value: ${this.registry.formatEnumValueDeclaration(descriptor)}`;
}
else if (plugin_framework_1.FieldDescriptorProto.is(descriptor)) {
return `@generated from protobuf field: ${this.registry.formatFieldDeclaration(descriptor)}`;
}
else if (plugin_framework_1.MethodDescriptorProto.is(descriptor)) {
return `@generated from protobuf rpc: ${this.registry.formatRpcDeclaration(descriptor)}`;
}
else {
return `@generated from protobuf ${this.registry.formatQualifiedName(descriptor)}`;
}
}
}
exports.CommentGenerator = CommentGenerator;

View file

@ -0,0 +1,50 @@
import * as ts from "typescript";
import { DescriptorRegistry, EnumDescriptorProto, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { CommentGenerator } from "./comment-generator";
import { Interpreter } from "../interpreter";
import { GeneratorBase } from "./generator-base";
export declare class EnumGenerator extends GeneratorBase {
private readonly options;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {});
/**
* For the following .proto:
*
* ```proto
* enum MyEnum {
* ANY = 0;
* YES = 1;
* NO = 2;
* }
* ```
*
* We generate the following enum:
*
* ```typescript
* enum MyEnum {
* ANY = 0,
* YES = 1,
* NO = 2
* }
* ```
*
* We drop a shared prefix, for example:
*
* ```proto
* enum MyEnum {
* MY_ENUM_FOO = 0;
* MY_ENUM_BAR = 1;
* }
* ```
*
* Becomes:
*
* ```typescript
* enum MyEnum {
* FOO = 0,
* BAR = 1,
* }
* ```
*
*/
generateEnum(source: TypescriptFile, descriptor: EnumDescriptorProto): ts.EnumDeclaration;
}

View file

@ -0,0 +1,69 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EnumGenerator = void 0;
const ts = require("typescript");
const rt = require("@protobuf-ts/runtime");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const generator_base_1 = require("./generator-base");
class EnumGenerator extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
}
/**
* For the following .proto:
*
* ```proto
* enum MyEnum {
* ANY = 0;
* YES = 1;
* NO = 2;
* }
* ```
*
* We generate the following enum:
*
* ```typescript
* enum MyEnum {
* ANY = 0,
* YES = 1,
* NO = 2
* }
* ```
*
* We drop a shared prefix, for example:
*
* ```proto
* enum MyEnum {
* MY_ENUM_FOO = 0;
* MY_ENUM_BAR = 1;
* }
* ```
*
* Becomes:
*
* ```typescript
* enum MyEnum {
* FOO = 0,
* BAR = 1,
* }
* ```
*
*/
generateEnum(source, descriptor) {
let enumObject = this.interpreter.getEnumInfo(descriptor)[1], builder = new plugin_framework_1.TypescriptEnumBuilder();
for (let ev of rt.listEnumValues(enumObject)) {
let evDescriptor = descriptor.value.find(v => v.number === ev.number);
let comments = evDescriptor
? this.comments.getCommentBlock(evDescriptor, true)
: "@generated synthetic value - protobuf-ts requires all enums to have a 0 value";
builder.add(ev.name, ev.number, comments);
}
let statement = builder.build(this.imports.type(source, descriptor), [ts.createModifier(ts.SyntaxKind.ExportKeyword)]);
// add to our file
source.addStatement(statement);
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
return statement;
}
}
exports.EnumGenerator = EnumGenerator;

View file

@ -0,0 +1,32 @@
import * as rt from "@protobuf-ts/runtime";
import * as ts from "typescript";
import { DescriptorRegistry, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
/**
* Generates TypeScript code for runtime field information,
* from runtime field information.
*/
export declare class FieldInfoGenerator {
private readonly registry;
private readonly imports;
private readonly options;
constructor(registry: DescriptorRegistry, imports: TypeScriptImports, options: {});
createFieldInfoLiterals(source: TypescriptFile, fieldInfos: readonly rt.PartialFieldInfo[]): ts.ArrayLiteralExpression;
createFieldInfoLiteral(source: TypescriptFile, fieldInfo: rt.PartialFieldInfo): ts.ObjectLiteralExpression;
/**
* Creates the interface field / oneof name based on original proto field name and naming options.
*/
static createTypescriptLocalName(name: string, options: {
useProtoFieldName: boolean;
}): string;
/**
* Turn normalized field info returned by normalizeFieldInfo() back into
* the minimized form.
*/
private static denormalizeFieldInfo;
private createMessageT;
private createEnumT;
private createRepeatType;
private createScalarType;
private createLongType;
private createMapV;
}

View file

@ -0,0 +1,159 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FieldInfoGenerator = void 0;
const rt = require("@protobuf-ts/runtime");
const ts = require("typescript");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
/**
* Generates TypeScript code for runtime field information,
* from runtime field information.
*/
class FieldInfoGenerator {
constructor(registry, imports, options) {
this.registry = registry;
this.imports = imports;
this.options = options;
}
createFieldInfoLiterals(source, fieldInfos) {
fieldInfos = fieldInfos.map(fi => FieldInfoGenerator.denormalizeFieldInfo(fi));
return ts.createArrayLiteral(fieldInfos.map(fi => this.createFieldInfoLiteral(source, fi)), true);
}
createFieldInfoLiteral(source, fieldInfo) {
fieldInfo = FieldInfoGenerator.denormalizeFieldInfo(fieldInfo);
let properties = [];
// no: The field number of the .proto field.
// name: The original name of the .proto field.
// kind: discriminator
// localName: The name of the field in the runtime.
// jsonName: The name of the field in JSON.
// oneof: The name of the `oneof` group, if this field belongs to one.
for (let key of ["no", "name", "kind", "localName", "jsonName", "oneof"]) {
if (fieldInfo[key] !== undefined) {
properties.push(ts.createPropertyAssignment(key, plugin_framework_1.typescriptLiteralFromValue(fieldInfo[key])));
}
}
// repeat: Is the field repeated?
if (fieldInfo.repeat !== undefined) {
properties.push(ts.createPropertyAssignment("repeat", this.createRepeatType(fieldInfo.repeat)));
}
// opt: Is the field optional?
if (fieldInfo.opt !== undefined) {
properties.push(ts.createPropertyAssignment("opt", plugin_framework_1.typescriptLiteralFromValue(fieldInfo.opt)));
}
switch (fieldInfo.kind) {
case "scalar":
// T: Scalar field type.
properties.push(ts.createPropertyAssignment("T", this.createScalarType(fieldInfo.T)));
// L?: JavaScript long type
if (fieldInfo.L !== undefined) {
properties.push(ts.createPropertyAssignment("L", this.createLongType(fieldInfo.L)));
}
break;
case "enum":
// T: Return enum field type info.
properties.push(ts.createPropertyAssignment(ts.createIdentifier('T'), this.createEnumT(source, fieldInfo.T())));
break;
case "message":
// T: Return message field type handler.
properties.push(ts.createPropertyAssignment(ts.createIdentifier('T'), this.createMessageT(source, fieldInfo.T())));
break;
case "map":
// K: Map field key type.
properties.push(ts.createPropertyAssignment("K", this.createScalarType(fieldInfo.K)));
// V: Map field value type.
properties.push(ts.createPropertyAssignment("V", this.createMapV(source, fieldInfo.V)));
break;
}
// options:
if (fieldInfo.options) {
properties.push(ts.createPropertyAssignment(ts.createIdentifier('options'), plugin_framework_1.typescriptLiteralFromValue(fieldInfo.options)));
}
return ts.createObjectLiteral(properties, false);
}
/**
* Creates the interface field / oneof name based on original proto field name and naming options.
*/
static createTypescriptLocalName(name, options) {
return options.useProtoFieldName ? name : rt.lowerCamelCase(name);
}
/**
* Turn normalized field info returned by normalizeFieldInfo() back into
* the minimized form.
*/
static denormalizeFieldInfo(info) {
let partial = Object.assign({}, info);
if (info.jsonName === rt.lowerCamelCase(info.name)) {
delete partial.jsonName;
}
if (info.localName === rt.lowerCamelCase(info.name)) {
delete partial.localName;
}
if (info.repeat === rt.RepeatType.NO) {
delete partial.repeat;
}
if (info.opt === false) {
delete partial.opt;
}
else if (info.opt === true && info.kind == "message") {
delete partial.opt;
}
return partial;
}
createMessageT(source, type) {
let descriptor = this.registry.resolveTypeName(type.typeName);
let generatedMessage = this.imports.type(source, descriptor);
return ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createIdentifier(generatedMessage));
}
createEnumT(source, ei) {
let [pbTypeName, , sharedPrefix] = ei, descriptor = this.registry.resolveTypeName(pbTypeName), generatedEnum = this.imports.type(source, descriptor), enumInfoLiteral = [
ts.createStringLiteral(pbTypeName),
ts.createIdentifier(generatedEnum),
];
if (sharedPrefix) {
enumInfoLiteral.push(ts.createStringLiteral(sharedPrefix));
}
return ts.createArrowFunction(undefined, undefined, [], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createArrayLiteral(enumInfoLiteral, false));
}
createRepeatType(type) {
const expr = ts.createNumericLiteral(type.toString());
ts.addSyntheticTrailingComment(expr, ts.SyntaxKind.MultiLineCommentTrivia, `RepeatType.${rt.RepeatType[type]}`);
return expr;
}
createScalarType(type) {
const expr = ts.createNumericLiteral(type.toString());
ts.addSyntheticTrailingComment(expr, ts.SyntaxKind.MultiLineCommentTrivia, `ScalarType.${rt.ScalarType[type]}`);
return expr;
}
createLongType(type) {
const expr = ts.createNumericLiteral(type.toString());
ts.addSyntheticTrailingComment(expr, ts.SyntaxKind.MultiLineCommentTrivia, `LongType.${rt.LongType[type]}`);
return expr;
}
// V: Map field value type.
createMapV(source, mapV) {
let T;
let L = undefined;
switch (mapV.kind) {
case "message":
T = this.createMessageT(source, mapV.T());
break;
case "enum":
T = this.createEnumT(source, mapV.T());
break;
case "scalar":
T = this.createScalarType(mapV.T);
if (mapV.L !== undefined)
L = this.createLongType(mapV.L);
break;
}
const properties = [
ts.createPropertyAssignment(ts.createIdentifier('kind'), ts.createStringLiteral(mapV.kind)),
ts.createPropertyAssignment(ts.createIdentifier('T'), T)
];
if (L) {
properties.push(ts.createPropertyAssignment(ts.createIdentifier('L'), L));
}
return ts.createObjectLiteral(properties);
}
}
exports.FieldInfoGenerator = FieldInfoGenerator;

View file

@ -0,0 +1,11 @@
import { CommentGenerator } from "./comment-generator";
import { DescriptorRegistry, SymbolTable, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { Interpreter } from "../interpreter";
export declare abstract class GeneratorBase {
protected readonly symbols: SymbolTable;
protected readonly registry: DescriptorRegistry;
protected readonly imports: TypeScriptImports;
protected readonly comments: CommentGenerator;
protected readonly interpreter: Interpreter;
protected constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter);
}

View file

@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GeneratorBase = void 0;
class GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter) {
this.symbols = symbols;
this.registry = registry;
this.imports = imports;
this.comments = comments;
this.interpreter = interpreter;
}
}
exports.GeneratorBase = GeneratorBase;

View file

@ -0,0 +1,10 @@
import { AnyTypeDescriptorProto, IDescriptorTree } from "@protobuf-ts/plugin-framework";
/**
* Create a name for an enum, message or service.
* - ignores package
* - nested types get the names merged with '_'
* - reserved words are escaped by adding '$' at the end
* - does *not* prevent clashes, for example clash
* of merged nested name with other message name
*/
export declare function createLocalTypeName(descriptor: AnyTypeDescriptorProto, treeLookup: IDescriptorTree): string;

View file

@ -0,0 +1,46 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createLocalTypeName = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const runtime_1 = require("@protobuf-ts/runtime");
// TODO in generated code, use globalThis for all types in global scope
// rationale: keywords are much less likely to change than objects in the global scope
// TODO move all code creating names into one place (see interpreter.ts for more code)
const reservedKeywords = 'break,case,catch,class,const,continue,debugger,default,delete,do,else,enum,export,extends,false,finally,for,function,if,import,in,instanceof,new,null,return,super,switch,this,throw,true,try,typeof,var,void,while,with,as,implements,interface,let,package,private,protected,public,static,yield,any,boolean,constructor,declare,get,module,require,number,set,string,symbol,type,from,of'.split(',');
const reservedTypeNames = 'object,Uint8Array,array,Array,string,String,number,Number,boolean,Boolean,bigint,BigInt'.split(',');
const escapeCharacter = '$';
/**
* Create a name for an enum, message or service.
* - ignores package
* - nested types get the names merged with '_'
* - reserved words are escaped by adding '$' at the end
* - does *not* prevent clashes, for example clash
* of merged nested name with other message name
*/
function createLocalTypeName(descriptor, treeLookup) {
// build name components for parent types
const components = [];
for (const ancestor of treeLookup.ancestorsOf(descriptor)) {
if (plugin_framework_1.FileDescriptorProto.is(ancestor)) {
continue;
}
const name = ancestor.name;
runtime_1.assert(name !== undefined);
components.push(name);
}
// add name for actual descriptor
const name = descriptor.name;
runtime_1.assert(name !== undefined);
components.push(name);
// join all components with underscore
let fullName = components.join('_');
// escape if reserved
if (reservedKeywords.includes(fullName)) {
fullName = fullName + escapeCharacter;
}
if (reservedTypeNames.includes(fullName)) {
fullName = fullName + escapeCharacter;
}
return fullName;
}
exports.createLocalTypeName = createLocalTypeName;

View file

@ -0,0 +1,65 @@
import * as ts from "typescript";
import * as rt from "@protobuf-ts/runtime";
import { DescriptorProto, DescriptorRegistry, FieldDescriptorProto, OneofDescriptorProto, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { CommentGenerator } from "./comment-generator";
import { Interpreter } from "../interpreter";
import { GeneratorBase } from "./generator-base";
export declare class MessageInterfaceGenerator extends GeneratorBase {
private readonly options;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {
oneofKindDiscriminator: string;
normalLongType: rt.LongType;
});
registerSymbols(source: TypescriptFile, descriptor: DescriptorProto): void;
/**
* `message` as an interface.
*
* For the following .proto:
*
* message MyMessage {
* string str_field = 1;
* }
*
* We generate the following interface:
*
* interface MyMessage {
* strField: string;
* }
*
*/
generateMessageInterface(source: TypescriptFile, descriptor: DescriptorProto): ts.InterfaceDeclaration;
/**
* Create property signature for a protobuf field. Example:
*
* fieldName: number
*
*/
protected createFieldPropertySignature(source: TypescriptFile, fieldDescriptor: FieldDescriptorProto, fieldInfo: rt.FieldInfo): ts.PropertySignature;
/**
* `oneof` as an algebraic data type.
*
* For the following .proto:
*
* oneof result {
* int32 value = 1;
* string error = 2;
* }
*
* We generate the following property signature:
*
* result: { oneofKind: "value"; value: number; }
* | { oneofKind: "error"; error: string; }
* | { oneofKind: undefined; };
*/
protected createOneofADTPropertySignature(source: TypescriptFile, oneofDescriptor: OneofDescriptorProto): ts.PropertySignature;
/**
* Helper to find for a OneofDescriptorProto:
* [0] the message descriptor
* [1] a corresponding message type generated by the interpreter
* [2] the runtime local name of the oneof
*/
private oneofInfo;
private createScalarTypeNode;
private createMessageTypeNode;
private createEnumTypeNode;
}

View file

@ -0,0 +1,221 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageInterfaceGenerator = void 0;
const ts = require("typescript");
const rt = require("@protobuf-ts/runtime");
const runtime_1 = require("@protobuf-ts/runtime");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const generator_base_1 = require("./generator-base");
const local_type_name_1 = require("./local-type-name");
class MessageInterfaceGenerator extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
}
registerSymbols(source, descriptor) {
const name = local_type_name_1.createLocalTypeName(descriptor, this.registry);
this.symbols.register(name, descriptor, source);
}
/**
* `message` as an interface.
*
* For the following .proto:
*
* message MyMessage {
* string str_field = 1;
* }
*
* We generate the following interface:
*
* interface MyMessage {
* strField: string;
* }
*
*/
generateMessageInterface(source, descriptor) {
const interpreterType = this.interpreter.getMessageType(descriptor), processedOneofs = [], // oneof groups already processed
members = []; // the interface members
for (let fieldInfo of interpreterType.fields) {
let fieldDescriptor = descriptor.field.find(fd => fd.number === fieldInfo.no);
runtime_1.assert(fieldDescriptor !== undefined);
if (fieldInfo.oneof) {
if (processedOneofs.includes(fieldInfo.oneof)) {
continue;
}
// create single property for entire oneof group
runtime_1.assert(fieldDescriptor.oneofIndex !== undefined);
let oneofDescriptor = descriptor.oneofDecl[fieldDescriptor.oneofIndex];
runtime_1.assert(oneofDescriptor !== undefined);
members.push(this.createOneofADTPropertySignature(source, oneofDescriptor));
processedOneofs.push(fieldInfo.oneof);
}
else {
// create regular properties
members.push(this.createFieldPropertySignature(source, fieldDescriptor, fieldInfo));
}
}
// export interface MyMessage { ...
const statement = ts.createInterfaceDeclaration(undefined, [ts.createModifier(ts.SyntaxKind.ExportKeyword)], this.imports.type(source, descriptor), undefined, undefined, members);
// add to our file
source.addStatement(statement);
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
return statement;
}
/**
* Create property signature for a protobuf field. Example:
*
* fieldName: number
*
*/
createFieldPropertySignature(source, fieldDescriptor, fieldInfo) {
let type; // the property type, may be made optional or wrapped into array at the end
switch (fieldInfo.kind) {
case "scalar":
type = this.createScalarTypeNode(fieldInfo.T, fieldInfo.L);
break;
case "enum":
type = this.createEnumTypeNode(source, fieldInfo.T());
break;
case "message":
type = this.createMessageTypeNode(source, fieldInfo.T());
break;
case "map":
let keyType = fieldInfo.K === rt.ScalarType.BOOL
? ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
: this.createScalarTypeNode(fieldInfo.K, rt.LongType.STRING);
let valueType;
switch (fieldInfo.V.kind) {
case "scalar":
valueType = this.createScalarTypeNode(fieldInfo.V.T, fieldInfo.V.L);
break;
case "enum":
valueType = this.createEnumTypeNode(source, fieldInfo.V.T());
break;
case "message":
valueType = this.createMessageTypeNode(source, fieldInfo.V.T());
break;
}
type = ts.createTypeLiteralNode([
ts.createIndexSignature(undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier('key'), undefined, keyType, undefined)
], valueType)
]);
break;
default:
throw new Error("unkown kind " + fieldDescriptor.name);
}
// if repeated, wrap type into array type
if (fieldInfo.repeat) {
type = ts.createArrayTypeNode(type);
}
// if optional, add question mark
let questionToken = fieldInfo.opt ? ts.createToken(ts.SyntaxKind.QuestionToken) : undefined;
// create property
const property = ts.createPropertySignature(undefined, ts.createIdentifier(fieldInfo.localName), questionToken, type, undefined);
this.comments.addCommentsForDescriptor(property, fieldDescriptor, 'trailingLines');
return property;
}
/**
* `oneof` as an algebraic data type.
*
* For the following .proto:
*
* oneof result {
* int32 value = 1;
* string error = 2;
* }
*
* We generate the following property signature:
*
* result: { oneofKind: "value"; value: number; }
* | { oneofKind: "error"; error: string; }
* | { oneofKind: undefined; };
*/
createOneofADTPropertySignature(source, oneofDescriptor) {
const oneofCases = [], [messageDescriptor, interpreterType, oneofLocalName] = this.oneofInfo(oneofDescriptor), memberFieldInfos = interpreterType.fields.filter(fi => fi.oneof === oneofLocalName);
runtime_1.assert(oneofDescriptor !== undefined);
// create a type for each selection case
for (let fieldInfo of memberFieldInfos) {
// { oneofKind: 'fieldName' ... } part
const kindProperty = ts.createPropertySignature(undefined, ts.createIdentifier(this.options.oneofKindDiscriminator), undefined, ts.createLiteralTypeNode(ts.createStringLiteral(fieldInfo.localName)), undefined);
// { ..., fieldName: type } part
let fieldDescriptor = messageDescriptor.field.find(fd => fd.number === fieldInfo.no);
runtime_1.assert(fieldDescriptor !== undefined);
let valueProperty = this.createFieldPropertySignature(source, fieldDescriptor, fieldInfo);
// add this case
oneofCases.push(ts.createTypeLiteralNode([kindProperty, valueProperty]));
}
// case for no selection: { oneofKind: undefined; }
oneofCases.push(ts.createTypeLiteralNode([
ts.createPropertySignature(undefined, ts.createIdentifier(this.options.oneofKindDiscriminator), undefined, ts.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword), undefined)
]));
// final property signature for the oneof group, with a union type for all oneof cases
const property = ts.createPropertySignature(undefined, ts.createIdentifier(oneofLocalName), undefined, ts.createUnionTypeNode(oneofCases), undefined);
// add comments
this.comments.addCommentsForDescriptor(property, oneofDescriptor, 'appendToLeadingBlock');
return property;
}
/**
* Helper to find for a OneofDescriptorProto:
* [0] the message descriptor
* [1] a corresponding message type generated by the interpreter
* [2] the runtime local name of the oneof
*/
oneofInfo(oneofDescriptor) {
const messageDescriptor = this.registry.parentOf(oneofDescriptor);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
const interpreterType = this.interpreter.getMessageType(messageDescriptor);
const oneofIndex = messageDescriptor.oneofDecl.indexOf(oneofDescriptor);
runtime_1.assert(oneofIndex !== undefined);
const sampleFieldDescriptor = messageDescriptor.field.find(fd => fd.oneofIndex === oneofIndex);
runtime_1.assert(sampleFieldDescriptor !== undefined);
const sampleFieldInfo = interpreterType.fields.find(fi => fi.no === sampleFieldDescriptor.number);
runtime_1.assert(sampleFieldInfo !== undefined);
const oneofName = sampleFieldInfo.oneof;
runtime_1.assert(oneofName !== undefined);
return [messageDescriptor, interpreterType, oneofName];
}
createScalarTypeNode(scalarType, longType) {
switch (scalarType) {
case rt.ScalarType.BOOL:
return ts.createKeywordTypeNode(ts.SyntaxKind.BooleanKeyword);
case rt.ScalarType.STRING:
return ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
case rt.ScalarType.BYTES:
return ts.createTypeReferenceNode('Uint8Array', undefined);
case rt.ScalarType.DOUBLE:
case rt.ScalarType.FLOAT:
case rt.ScalarType.INT32:
case rt.ScalarType.FIXED32:
case rt.ScalarType.UINT32:
case rt.ScalarType.SFIXED32:
case rt.ScalarType.SINT32:
return ts.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
case rt.ScalarType.SFIXED64:
case rt.ScalarType.INT64:
case rt.ScalarType.UINT64:
case rt.ScalarType.FIXED64:
case rt.ScalarType.SINT64:
switch (longType !== null && longType !== void 0 ? longType : rt.LongType.STRING) {
case rt.LongType.STRING:
return ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
case rt.LongType.NUMBER:
return ts.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword);
case rt.LongType.BIGINT:
return ts.createKeywordTypeNode(ts.SyntaxKind.BigIntKeyword);
}
}
}
createMessageTypeNode(source, type) {
let messageDescriptor = this.registry.resolveTypeName(type.typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
return ts.createTypeReferenceNode(this.imports.type(source, messageDescriptor), undefined);
}
createEnumTypeNode(source, ei) {
let [enumTypeName] = ei;
let enumDescriptor = this.registry.resolveTypeName(enumTypeName);
runtime_1.assert(plugin_framework_1.EnumDescriptorProto.is(enumDescriptor));
return ts.createTypeReferenceNode(this.imports.type(source, enumDescriptor), undefined);
}
}
exports.MessageInterfaceGenerator = MessageInterfaceGenerator;

View file

@ -0,0 +1,49 @@
import * as ts from "typescript";
import { LongType } from "@protobuf-ts/runtime";
import { DescriptorProto, DescriptorRegistry, FileOptions_OptimizeMode as OptimizeMode, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { CommentGenerator } from "./comment-generator";
import { Interpreter } from "../interpreter";
import { GeneratorBase } from "./generator-base";
export interface CustomMethodGenerator {
make(source: TypescriptFile, descriptor: DescriptorProto): ts.MethodDeclaration[];
}
export declare class MessageTypeGenerator extends GeneratorBase {
private readonly options;
private readonly wellKnown;
private readonly googleTypes;
private readonly typeMethodCreate;
private readonly typeMethodInternalBinaryRead;
private readonly typeMethodInternalBinaryWrite;
private readonly fieldInfoGenerator;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {
runtimeImportPath: string;
normalLongType: LongType;
oneofKindDiscriminator: string;
useProtoFieldName: boolean;
});
/**
* Declare a handler for the message. The handler provides
* functions to read / write messages of the specific type.
*
* For the following .proto:
*
* package test;
* message MyMessage {
* string str_field = 1;
* }
*
* We generate the following variable declaration:
*
* import { H } from "R";
* const MyMessage: H<MyMessage> =
* new H<MyMessage>(
* ".test.MyMessage",
* [{ no: 0, name: "str_field", kind: "scalar", T: 9 }]
* );
*
* H is the concrete class imported from runtime R.
* Some field information is passed to the handler's
* constructor.
*/
generateMessageType(source: TypescriptFile, descriptor: DescriptorProto, optimizeFor: OptimizeMode): void;
}

View file

@ -0,0 +1,85 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageTypeGenerator = void 0;
const ts = require("typescript");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const well_known_types_1 = require("../message-type-extensions/well-known-types");
const google_types_1 = require("../message-type-extensions/google-types");
const create_1 = require("../message-type-extensions/create");
const internal_binary_read_1 = require("../message-type-extensions/internal-binary-read");
const internal_binary_write_1 = require("../message-type-extensions/internal-binary-write");
const field_info_generator_1 = require("./field-info-generator");
const generator_base_1 = require("./generator-base");
class MessageTypeGenerator extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
this.fieldInfoGenerator = new field_info_generator_1.FieldInfoGenerator(this.registry, this.imports, this.options);
this.wellKnown = new well_known_types_1.WellKnownTypes(this.registry, this.imports, this.options);
this.googleTypes = new google_types_1.GoogleTypes(this.registry, this.imports, this.options);
this.typeMethodCreate = new create_1.Create(this.registry, this.imports, this.interpreter, this.options);
this.typeMethodInternalBinaryRead = new internal_binary_read_1.InternalBinaryRead(this.registry, this.imports, this.interpreter, this.options);
this.typeMethodInternalBinaryWrite = new internal_binary_write_1.InternalBinaryWrite(this.registry, this.imports, this.interpreter, this.options);
}
/**
* Declare a handler for the message. The handler provides
* functions to read / write messages of the specific type.
*
* For the following .proto:
*
* package test;
* message MyMessage {
* string str_field = 1;
* }
*
* We generate the following variable declaration:
*
* import { H } from "R";
* const MyMessage: H<MyMessage> =
* new H<MyMessage>(
* ".test.MyMessage",
* [{ no: 0, name: "str_field", kind: "scalar", T: 9 }]
* );
*
* H is the concrete class imported from runtime R.
* Some field information is passed to the handler's
* constructor.
*/
generateMessageType(source, descriptor, optimizeFor) {
const
// identifier for the message
MyMessage = this.imports.type(source, descriptor), Message$Type = ts.createIdentifier(this.imports.type(source, descriptor) + '$Type'), MessageType = ts.createIdentifier(this.imports.name(source, "MessageType", this.options.runtimeImportPath)), interpreterType = this.interpreter.getMessageType(descriptor), classDecMembers = [], classDecSuperArgs = [
// arg 0: type name
ts.createStringLiteral(this.registry.makeTypeName(descriptor)),
// arg 1: field infos
this.fieldInfoGenerator.createFieldInfoLiterals(source, interpreterType.fields)
];
// if present, add message options in json format to MessageType CTOR args
if (Object.keys(interpreterType.options).length) {
classDecSuperArgs.push(plugin_framework_1.typescriptLiteralFromValue(interpreterType.options));
}
// "MyMessage$Type" constructor() { super(...) }
classDecMembers.push(ts.createConstructor(undefined, undefined, [], ts.createBlock([ts.createExpressionStatement(ts.createCall(ts.createSuper(), undefined, classDecSuperArgs))], true)));
// "MyMessage$Type" members for supported standard types
classDecMembers.push(...this.wellKnown.make(source, descriptor));
classDecMembers.push(...this.googleTypes.make(source, descriptor));
// "MyMessage$Type" members for optimized binary format
if (optimizeFor === plugin_framework_1.FileOptions_OptimizeMode.SPEED) {
classDecMembers.push(...this.typeMethodCreate.make(source, descriptor), ...this.typeMethodInternalBinaryRead.make(source, descriptor), ...this.typeMethodInternalBinaryWrite.make(source, descriptor));
}
// class "MyMessage$Type" extends "MessageType"<"MyMessage"> {
const classDec = ts.createClassDeclaration(undefined, undefined, Message$Type, undefined, [ts.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ts.createExpressionWithTypeArguments([ts.createTypeReferenceNode(MyMessage, undefined)], MessageType)])], classDecMembers);
// export const "messageId" = new "MessageTypeId"();
const exportConst = ts.createVariableStatement([ts.createModifier(ts.SyntaxKind.ExportKeyword)], ts.createVariableDeclarationList([ts.createVariableDeclaration(MyMessage, undefined, ts.createNew(Message$Type, undefined, []))], ts.NodeFlags.Const));
// add to our file
source.addStatement(classDec);
source.addStatement(exportConst);
// add comments
ts.addSyntheticLeadingComment(classDec, ts.SyntaxKind.SingleLineCommentTrivia, " @generated message type with reflection information, may provide speed optimized methods", false);
let comment = this.comments.makeDeprecatedTag(descriptor);
comment += this.comments.makeGeneratedTag(descriptor).replace("@generated from ", "@generated MessageType for ");
plugin_framework_1.addCommentBlockAsJsDoc(exportConst, comment);
return;
}
}
exports.MessageTypeGenerator = MessageTypeGenerator;

View file

@ -0,0 +1,19 @@
import * as rpc from "@protobuf-ts/runtime-rpc";
import * as ts from "typescript";
import { DescriptorRegistry, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
/**
* Generates TypeScript code for runtime method information,
* from method field information.
*/
export declare class MethodInfoGenerator {
private readonly registry;
private readonly imports;
constructor(registry: DescriptorRegistry, imports: TypeScriptImports);
createMethodInfoLiterals(source: TypescriptFile, methodInfos: readonly rpc.PartialMethodInfo[]): ts.ArrayLiteralExpression;
createMethodInfoLiteral(source: TypescriptFile, methodInfo: rpc.PartialMethodInfo): ts.ObjectLiteralExpression;
/**
* Turn normalized method info returned by normalizeMethodInfo() back into
* the minimized form.
*/
private static denormalizeMethodInfo;
}

View file

@ -0,0 +1,67 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.MethodInfoGenerator = void 0;
const rt = require("@protobuf-ts/runtime");
const ts = require("typescript");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
/**
* Generates TypeScript code for runtime method information,
* from method field information.
*/
class MethodInfoGenerator {
constructor(registry, imports) {
this.registry = registry;
this.imports = imports;
}
createMethodInfoLiterals(source, methodInfos) {
const mi = methodInfos
.map(mi => MethodInfoGenerator.denormalizeMethodInfo(mi))
.map(mi => this.createMethodInfoLiteral(source, mi));
return ts.createArrayLiteral(mi, true);
}
createMethodInfoLiteral(source, methodInfo) {
methodInfo = MethodInfoGenerator.denormalizeMethodInfo(methodInfo);
const properties = [];
// name: The name of the method as declared in .proto
// localName: The name of the method in the runtime.
// idempotency: The idempotency level as specified in .proto.
// serverStreaming: Was the rpc declared with server streaming?
// clientStreaming: Was the rpc declared with client streaming?
// options: Contains custom method options from the .proto source in JSON format.
for (let key of ["name", "localName", "idempotency", "serverStreaming", "clientStreaming", "options"]) {
if (methodInfo[key] !== undefined) {
properties.push(ts.createPropertyAssignment(key, plugin_framework_1.typescriptLiteralFromValue(methodInfo[key])));
}
}
// I: The generated type handler for the input message.
properties.push(ts.createPropertyAssignment(ts.createIdentifier('I'), ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName)))));
// O: The generated type handler for the output message.
properties.push(ts.createPropertyAssignment(ts.createIdentifier('O'), ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName)))));
return ts.createObjectLiteral(properties, false);
}
/**
* Turn normalized method info returned by normalizeMethodInfo() back into
* the minimized form.
*/
static denormalizeMethodInfo(info) {
let partial = Object.assign({}, info);
delete partial.service;
if (info.localName === rt.lowerCamelCase(info.name)) {
delete partial.localName;
}
if (!info.serverStreaming) {
delete partial.serverStreaming;
}
if (!info.clientStreaming) {
delete partial.clientStreaming;
}
if (info.options && Object.keys(info.options).length) {
delete partial.info;
}
if (info.idempotency === undefined) {
delete partial.idempotency;
}
return partial;
}
}
exports.MethodInfoGenerator = MethodInfoGenerator;

View file

@ -0,0 +1,68 @@
import { DescriptorRegistry, ServiceDescriptorProto, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import * as ts from "typescript";
import * as rpc from "@protobuf-ts/runtime-rpc";
import { CommentGenerator } from "./comment-generator";
import { Interpreter } from "../interpreter";
import { GeneratorBase } from "./generator-base";
export declare abstract class ServiceClientGeneratorBase extends GeneratorBase {
protected readonly options: {
runtimeImportPath: string;
runtimeRpcImportPath: string;
};
abstract readonly symbolKindInterface: string;
abstract readonly symbolKindImplementation: string;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {
runtimeImportPath: string;
runtimeRpcImportPath: string;
});
registerSymbols(source: TypescriptFile, descriptor: ServiceDescriptorProto): void;
/**
* For the following .proto:
*
* service SimpleService {
* rpc Get (GetRequest) returns (GetResponse);
* }
*
* We generate the following interface:
*
* interface ISimpleServiceClient {
* get(request: GetRequest, options?: RpcOptions): UnaryCall<ExampleRequest, ExampleResponse>;
* }
*
*/
generateInterface(source: TypescriptFile, descriptor: ServiceDescriptorProto): ts.InterfaceDeclaration;
protected createMethodSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createUnarySignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createServerStreamingSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createClientStreamingSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createDuplexStreamingSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
/**
* For the following .proto:
*
* service SimpleService {
* rpc Get (GetRequest) returns (GetResponse);
* }
*
* We generate:
*
* class SimpleService implements ISimpleService {
* readonly typeName = ".spec.SimpleService";
* readonly methods: MethodInfo[] = [
* {name: 'Get', localName: 'get', I: GetRequest, O: GetResponse}
* ];
* ...
* }
*
*/
generateImplementationClass(source: TypescriptFile, descriptor: ServiceDescriptorProto): ts.ClassDeclaration;
/**
* Create any method type, switching to specific methods.
*/
protected createMethod(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected abstract createUnary(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected abstract createServerStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected abstract createClientStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected abstract createDuplexStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected makeI(source: TypescriptFile, methodInfo: rpc.MethodInfo, isTypeOnly?: boolean): ts.TypeReferenceNode;
protected makeO(source: TypescriptFile, methodInfo: rpc.MethodInfo, isTypeOnly?: boolean): ts.TypeReferenceNode;
}

View file

@ -0,0 +1,164 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceClientGeneratorBase = void 0;
const ts = require("typescript");
const generator_base_1 = require("./generator-base");
const local_type_name_1 = require("./local-type-name");
const runtime_1 = require("@protobuf-ts/runtime");
class ServiceClientGeneratorBase extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
}
registerSymbols(source, descriptor) {
const basename = local_type_name_1.createLocalTypeName(descriptor, this.registry);
const interfaceName = `I${basename}Client`;
const implementationName = `${basename}Client`;
this.symbols.register(interfaceName, descriptor, source, this.symbolKindInterface);
this.symbols.register(implementationName, descriptor, source, this.symbolKindImplementation);
}
/**
* For the following .proto:
*
* service SimpleService {
* rpc Get (GetRequest) returns (GetResponse);
* }
*
* We generate the following interface:
*
* interface ISimpleServiceClient {
* get(request: GetRequest, options?: RpcOptions): UnaryCall<ExampleRequest, ExampleResponse>;
* }
*
*/
generateInterface(source, descriptor) {
const interpreterType = this.interpreter.getServiceType(descriptor), IServiceClient = this.imports.type(source, descriptor, this.symbolKindInterface), signatures = [];
for (let mi of interpreterType.methods) {
const sig = this.createMethodSignatures(source, mi);
// add comment to the first signature
if (sig.length > 0) {
const methodDescriptor = descriptor.method.find(md => md.name === mi.name);
runtime_1.assert(methodDescriptor);
this.comments.addCommentsForDescriptor(sig[0], methodDescriptor, 'appendToLeadingBlock');
}
signatures.push(...sig);
}
// export interface MyService {...
let statement = ts.createInterfaceDeclaration(undefined, [ts.createModifier(ts.SyntaxKind.ExportKeyword)], IServiceClient, undefined, undefined, [...signatures]);
// add to our file
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
source.addStatement(statement);
return statement;
}
createMethodSignatures(source, methodInfo) {
let signatures;
if (methodInfo.serverStreaming && methodInfo.clientStreaming) {
signatures = this.createDuplexStreamingSignatures(source, methodInfo);
}
else if (methodInfo.serverStreaming) {
signatures = this.createServerStreamingSignatures(source, methodInfo);
}
else if (methodInfo.clientStreaming) {
signatures = this.createClientStreamingSignatures(source, methodInfo);
}
else {
signatures = this.createUnarySignatures(source, methodInfo);
}
return signatures;
}
createUnarySignatures(source, methodInfo) {
const method = this.createUnary(source, methodInfo);
return [ts.createMethodSignature(method.typeParameters, method.parameters, method.type, method.name, method.questionToken)];
}
createServerStreamingSignatures(source, methodInfo) {
const method = this.createServerStreaming(source, methodInfo);
return [ts.createMethodSignature(method.typeParameters, method.parameters, method.type, method.name, method.questionToken)];
}
createClientStreamingSignatures(source, methodInfo) {
const method = this.createClientStreaming(source, methodInfo);
return [ts.createMethodSignature(method.typeParameters, method.parameters, method.type, method.name, method.questionToken)];
}
createDuplexStreamingSignatures(source, methodInfo) {
const method = this.createDuplexStreaming(source, methodInfo);
return [ts.createMethodSignature(method.typeParameters, method.parameters, method.type, method.name, method.questionToken)];
}
/**
* For the following .proto:
*
* service SimpleService {
* rpc Get (GetRequest) returns (GetResponse);
* }
*
* We generate:
*
* class SimpleService implements ISimpleService {
* readonly typeName = ".spec.SimpleService";
* readonly methods: MethodInfo[] = [
* {name: 'Get', localName: 'get', I: GetRequest, O: GetResponse}
* ];
* ...
* }
*
*/
generateImplementationClass(source, descriptor) {
const interpreterType = this.interpreter.getServiceType(descriptor), ServiceType = this.imports.type(source, descriptor), ServiceClient = this.imports.type(source, descriptor, this.symbolKindImplementation), IServiceClient = this.imports.type(source, descriptor, this.symbolKindInterface), ServiceInfo = this.imports.name(source, 'ServiceInfo', this.options.runtimeRpcImportPath, true), RpcTransport = this.imports.name(source, 'RpcTransport', this.options.runtimeRpcImportPath, true);
const classDecorators = [];
const constructorDecorators = [];
const members = [
// typeName = Haberdasher.typeName;
ts.createProperty(undefined, undefined, ts.createIdentifier("typeName"), undefined, undefined, ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("typeName"))),
// methods = Haberdasher.methods;
ts.createProperty(undefined, undefined, ts.createIdentifier("methods"), undefined, undefined, ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("methods"))),
// options = Haberdasher.options;
ts.createProperty(undefined, undefined, ts.createIdentifier("options"), undefined, undefined, ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("options"))),
// constructor(@Inject(RPC_TRANSPORT) private readonly _transport: RpcTransport) {}
ts.createConstructor(undefined, undefined, [ts.createParameter(constructorDecorators, [
ts.createModifier(ts.SyntaxKind.PrivateKeyword),
ts.createModifier(ts.SyntaxKind.ReadonlyKeyword)
], undefined, ts.createIdentifier("_transport"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(RpcTransport), undefined), undefined)], ts.createBlock([], true)),
...interpreterType.methods.map(mi => {
const declaration = this.createMethod(source, mi);
const methodDescriptor = descriptor.method.find(md => md.name === mi.name);
runtime_1.assert(methodDescriptor);
this.comments.addCommentsForDescriptor(declaration, methodDescriptor, 'appendToLeadingBlock');
return declaration;
})
];
// export class MyService implements MyService, ServiceInfo
const statement = ts.createClassDeclaration(classDecorators, [ts.createModifier(ts.SyntaxKind.ExportKeyword)], ServiceClient, undefined, [
ts.createHeritageClause(ts.SyntaxKind.ImplementsKeyword, [
ts.createExpressionWithTypeArguments(undefined, ts.createIdentifier(IServiceClient)),
ts.createExpressionWithTypeArguments(undefined, ts.createIdentifier(ServiceInfo)),
]),
], members);
source.addStatement(statement);
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
return statement;
}
/**
* Create any method type, switching to specific methods.
*/
createMethod(source, methodInfo) {
let declaration;
if (methodInfo.serverStreaming && methodInfo.clientStreaming) {
declaration = this.createDuplexStreaming(source, methodInfo);
}
else if (methodInfo.serverStreaming) {
declaration = this.createServerStreaming(source, methodInfo);
}
else if (methodInfo.clientStreaming) {
declaration = this.createClientStreaming(source, methodInfo);
}
else {
declaration = this.createUnary(source, methodInfo);
}
return declaration;
}
makeI(source, methodInfo, isTypeOnly = false) {
return ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName), 'default', isTypeOnly)), undefined);
}
makeO(source, methodInfo, isTypeOnly = false) {
return ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName), 'default', isTypeOnly)), undefined);
}
}
exports.ServiceClientGeneratorBase = ServiceClientGeneratorBase;

View file

@ -0,0 +1,12 @@
import * as ts from "typescript";
import { ServiceClientGeneratorBase } from "./service-client-generator-base";
import * as rpc from "@protobuf-ts/runtime-rpc";
import { TypescriptFile } from "@protobuf-ts/plugin-framework";
export declare class ServiceClientGeneratorGeneric extends ServiceClientGeneratorBase {
readonly symbolKindInterface = "call-client-interface";
readonly symbolKindImplementation = "call-client";
createUnary(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
createServerStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
createClientStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
createDuplexStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
}

View file

@ -0,0 +1,130 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceClientGeneratorGeneric = void 0;
const ts = require("typescript");
const service_client_generator_base_1 = require("./service-client-generator-base");
const runtime_1 = require("@protobuf-ts/runtime");
class ServiceClientGeneratorGeneric extends service_client_generator_base_1.ServiceClientGeneratorBase {
constructor() {
super(...arguments);
this.symbolKindInterface = 'call-client-interface';
this.symbolKindImplementation = 'call-client';
}
createUnary(source, methodInfo) {
let RpcOptions = this.imports.name(source, 'RpcOptions', this.options.runtimeRpcImportPath, true);
let UnaryCall = this.imports.name(source, 'UnaryCall', this.options.runtimeRpcImportPath, true);
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
runtime_1.assert(methodIndex >= 0);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true)),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createIdentifier(RpcOptions), undefined), undefined)
], ts.createTypeReferenceNode(UnaryCall, [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true),
]), ts.createBlock([
// const method = this.methods[0], opt = this._transport.mergeOptions(options);
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([
ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString()))),
ts.createVariableDeclaration(ts.createIdentifier("opt"), undefined, ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")), ts.createIdentifier("mergeOptions")), undefined, [ts.createIdentifier("options")])),
], ts.NodeFlags.Const)),
// return stackIntercept("unary", this._transport, method, opt, input);
ts.createReturn(ts.createCall(ts.createIdentifier(this.imports.name(source, 'stackIntercept', this.options.runtimeRpcImportPath)), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createStringLiteral("unary"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")),
ts.createIdentifier("method"),
ts.createIdentifier("opt"),
ts.createIdentifier("input"),
])),
], true));
}
createServerStreaming(source, methodInfo) {
let RpcOptions = this.imports.name(source, 'RpcOptions', this.options.runtimeRpcImportPath, true);
let ServerStreamingCall = this.imports.name(source, 'ServerStreamingCall', this.options.runtimeRpcImportPath, true);
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
runtime_1.assert(methodIndex >= 0);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true)),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createIdentifier(RpcOptions), undefined), undefined)
], ts.createTypeReferenceNode(ServerStreamingCall, [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true),
]), ts.createBlock([
// const method = this.methods[0], opt = this._transport.mergeOptions(options);
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([
ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString()))),
ts.createVariableDeclaration(ts.createIdentifier("opt"), undefined, ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")), ts.createIdentifier("mergeOptions")), undefined, [ts.createIdentifier("options")])),
], ts.NodeFlags.Const)),
// return stackIntercept("serverStreaming", this._transport, method, opt, i);
ts.createReturn(ts.createCall(ts.createIdentifier(this.imports.name(source, 'stackIntercept', this.options.runtimeRpcImportPath)), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createStringLiteral("serverStreaming"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")),
ts.createIdentifier("method"),
ts.createIdentifier("opt"),
ts.createIdentifier("input"),
])),
], true));
}
createClientStreaming(source, methodInfo) {
let RpcOptions = this.imports.name(source, 'RpcOptions', this.options.runtimeRpcImportPath, true);
let ClientStreamingCall = this.imports.name(source, 'ClientStreamingCall', this.options.runtimeRpcImportPath, true);
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
runtime_1.assert(methodIndex >= 0);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createIdentifier(RpcOptions), undefined), undefined)
], ts.createTypeReferenceNode(ClientStreamingCall, [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true),
]), ts.createBlock([
// const method = this.methods[0], opt = this._transport.mergeOptions(options)
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([
ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString()))),
ts.createVariableDeclaration(ts.createIdentifier("opt"), undefined, ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")), ts.createIdentifier("mergeOptions")), undefined, [ts.createIdentifier("options")]))
], ts.NodeFlags.Const)),
// return stackIntercept("clientStreaming", this._transport, methods, opt);
ts.createReturn(ts.createCall(ts.createIdentifier(this.imports.name(source, 'stackIntercept', this.options.runtimeRpcImportPath)), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createStringLiteral("clientStreaming"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")),
ts.createIdentifier("method"),
ts.createIdentifier("opt")
])),
], true));
}
createDuplexStreaming(source, methodInfo) {
let RpcOptions = this.imports.name(source, 'RpcOptions', this.options.runtimeRpcImportPath, true);
let DuplexStreamingCall = this.imports.name(source, 'DuplexStreamingCall', this.options.runtimeRpcImportPath, true);
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
runtime_1.assert(methodIndex >= 0);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createIdentifier(RpcOptions), undefined), undefined)
], ts.createTypeReferenceNode(DuplexStreamingCall, [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true),
]), ts.createBlock([
// const method = this.methods[0], opt = this._transport.mergeOptions(options)
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([
ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString()))),
ts.createVariableDeclaration(ts.createIdentifier("opt"), undefined, ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")), ts.createIdentifier("mergeOptions")), undefined, [ts.createIdentifier("options")]))
], ts.NodeFlags.Const)),
// return stackIntercept("duplex", this._transport, this, methods, opt);
ts.createReturn(ts.createCall(ts.createIdentifier(this.imports.name(source, 'stackIntercept', this.options.runtimeRpcImportPath)), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createStringLiteral("duplex"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_transport")),
ts.createIdentifier("method"),
ts.createIdentifier("opt")
])),
], true));
}
}
exports.ServiceClientGeneratorGeneric = ServiceClientGeneratorGeneric;

View file

@ -0,0 +1,17 @@
import { ServiceClientGeneratorBase } from "./service-client-generator-base";
import { ServiceDescriptorProto, TypescriptFile } from "@protobuf-ts/plugin-framework";
import * as ts from "typescript";
import * as rpc from "@protobuf-ts/runtime-rpc";
export declare class ServiceClientGeneratorGrpc extends ServiceClientGeneratorBase {
readonly symbolKindInterface = "grpc1-client-interface";
readonly symbolKindImplementation = "grpc1-client";
generateImplementationClass(source: TypescriptFile, descriptor: ServiceDescriptorProto): ts.ClassDeclaration;
protected createUnarySignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createServerStreamingSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createClientStreamingSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createDuplexStreamingSignatures(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodSignature[];
protected createUnary(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected createServerStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected createClientStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
protected createDuplexStreaming(source: TypescriptFile, methodInfo: rpc.MethodInfo): ts.MethodDeclaration;
}

View file

@ -0,0 +1,371 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceClientGeneratorGrpc = void 0;
const service_client_generator_base_1 = require("./service-client-generator-base");
const ts = require("typescript");
const runtime_1 = require("@protobuf-ts/runtime");
class ServiceClientGeneratorGrpc extends service_client_generator_base_1.ServiceClientGeneratorBase {
constructor() {
super(...arguments);
this.symbolKindInterface = 'grpc1-client-interface';
this.symbolKindImplementation = 'grpc1-client';
}
generateImplementationClass(source, descriptor) {
const interpreterType = this.interpreter.getServiceType(descriptor), ServiceClient = this.imports.type(source, descriptor, this.symbolKindImplementation), IServiceClient = this.imports.type(source, descriptor, this.symbolKindInterface), BinaryReadOptions = this.imports.name(source, 'BinaryReadOptions', this.options.runtimeImportPath, true), BinaryWriteOptions = this.imports.name(source, 'BinaryWriteOptions', this.options.runtimeImportPath, true), grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
const members = [
// private readonly _binaryOptions: Partial<BinaryReadOptions & BinaryWriteOptions>;
ts.createProperty(undefined, [
ts.createModifier(ts.SyntaxKind.PrivateKeyword),
ts.createModifier(ts.SyntaxKind.ReadonlyKeyword)
], ts.createIdentifier("_binaryOptions"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("Partial"), [ts.createIntersectionTypeNode([
ts.createTypeReferenceNode(ts.createIdentifier(BinaryReadOptions), undefined),
ts.createTypeReferenceNode(ts.createIdentifier(BinaryWriteOptions), undefined)
])]), undefined),
//
ts.createConstructor(undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("address"), undefined, ts.createKeywordTypeNode(ts.SyntaxKind.StringKeyword), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("credentials"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ChannelCredentials")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientOptions")), undefined), ts.createObjectLiteral([], false)),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("binaryOptions"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("Partial"), [ts.createIntersectionTypeNode([
ts.createTypeReferenceNode(ts.createIdentifier(BinaryReadOptions), undefined),
ts.createTypeReferenceNode(ts.createIdentifier(BinaryWriteOptions), undefined)
])]), ts.createObjectLiteral([], false))
], ts.createBlock([
ts.createExpressionStatement(ts.createCall(ts.createSuper(), undefined, [
ts.createIdentifier("address"),
ts.createIdentifier("credentials"),
ts.createIdentifier("options")
])),
ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions")), ts.createToken(ts.SyntaxKind.EqualsToken), ts.createIdentifier("binaryOptions")))
], true)),
...interpreterType.methods.map(mi => {
const declaration = this.createMethod(source, mi);
const methodDescriptor = descriptor.method.find(md => md.name === mi.name);
runtime_1.assert(methodDescriptor);
this.comments.addCommentsForDescriptor(declaration, methodDescriptor, 'appendToLeadingBlock');
return declaration;
})
];
// export class MyService implements MyService, ServiceInfo
const statement = ts.createClassDeclaration(undefined, [ts.createModifier(ts.SyntaxKind.ExportKeyword)], ServiceClient, undefined, [
ts.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ts.createExpressionWithTypeArguments(undefined, ts.createPropertyAccess(ts.createIdentifier(grpc), ts.createIdentifier("Client")))]),
ts.createHeritageClause(ts.SyntaxKind.ImplementsKeyword, [ts.createExpressionWithTypeArguments(undefined, ts.createIdentifier(IServiceClient))])
], members);
source.addStatement(statement);
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
return statement;
}
createUnarySignatures(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
return [
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientUnaryCall")), undefined), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientUnaryCall")), undefined), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientUnaryCall")), undefined), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientUnaryCall")), undefined), ts.createIdentifier(methodInfo.localName), undefined)
];
}
createServerStreamingSignatures(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
return [
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientReadableStream")), [this.makeO(source, methodInfo, true)]), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientReadableStream")), [this.makeO(source, methodInfo, true)]), ts.createIdentifier(methodInfo.localName), undefined)
];
}
createClientStreamingSignatures(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
return [
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientWritableStream")), [this.makeI(source, methodInfo, true)]), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientWritableStream")), [this.makeI(source, methodInfo, true)]), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientWritableStream")), [
this.makeI(source, methodInfo, true),
]), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), undefined, ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)), undefined)], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientWritableStream")), [
this.makeI(source, methodInfo, true),
]), ts.createIdentifier(methodInfo.localName), undefined)
];
}
createDuplexStreamingSignatures(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
return [
ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientDuplexStream")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true),
]), ts.createIdentifier(methodInfo.localName), undefined),
ts.createMethodSignature(undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined)], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientDuplexStream")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true),
]), ts.createIdentifier(methodInfo.localName), undefined)
];
}
createUnary(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
let ServiceType = this.imports.type(source, this.registry.resolveTypeName(methodInfo.service.typeName));
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined),
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined),
ts.createParenthesizedType(ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)))
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined),
ts.createParenthesizedType(ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)))
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createParenthesizedType(ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword))), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientUnaryCall")), undefined), ts.createBlock([
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString())))], ts.NodeFlags.Const)),
ts.createReturn(ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("makeUnaryRequest")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createTemplateExpression(ts.createTemplateHead("/", "/"), [
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("typeName")), ts.createTemplateMiddle("/", "/")),
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("name")), ts.createTemplateTail("", ""))
]),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, this.makeI(source, methodInfo, true), undefined)], ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Buffer"), ts.createIdentifier("from")), undefined, [ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("I")), ts.createIdentifier("toBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])])),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), undefined)], this.makeO(source, methodInfo, true), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("O")), ts.createIdentifier("fromBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])),
ts.createIdentifier("input"),
ts.createAsExpression(ts.createIdentifier("metadata"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createAsExpression(ts.createIdentifier("options"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createAsExpression(ts.createIdentifier("callback"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))
]))
], true));
}
createServerStreaming(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
let ServiceType = this.imports.type(source, this.registry.resolveTypeName(methodInfo.service.typeName));
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("input"), undefined, this.makeI(source, methodInfo, true), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined),
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientReadableStream")), [this.makeO(source, methodInfo, true)]), ts.createBlock([
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString())))], ts.NodeFlags.Const)),
ts.createReturn(ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("makeServerStreamRequest")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createTemplateExpression(ts.createTemplateHead("/", "/"), [
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("typeName")), ts.createTemplateMiddle("/", "/")),
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("name")), ts.createTemplateTail("", ""))
]),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, this.makeI(source, methodInfo, true), undefined)], ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Buffer"), ts.createIdentifier("from")), undefined, [ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("I")), ts.createIdentifier("toBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])])),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), undefined)], this.makeO(source, methodInfo, true), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("O")), ts.createIdentifier("fromBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])),
ts.createIdentifier("input"),
ts.createAsExpression(ts.createIdentifier("metadata"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createIdentifier("options")
]))
], true));
}
createClientStreaming(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
let ServiceType = this.imports.type(source, this.registry.resolveTypeName(methodInfo.service.typeName));
let methodIndex = methodInfo.service.methods.indexOf(methodInfo);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined),
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined),
ts.createParenthesizedType(ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)))
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined),
ts.createParenthesizedType(ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)))
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("callback"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createParenthesizedType(ts.createFunctionTypeNode(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("err"), undefined, ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceError")), undefined),
ts.createKeywordTypeNode(ts.SyntaxKind.NullKeyword)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), this.makeO(source, methodInfo, true), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword))), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientWritableStream")), [this.makeI(source, methodInfo, true)]), ts.createBlock([
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("methods")), ts.createNumericLiteral(methodIndex.toString())))], ts.NodeFlags.Const)),
ts.createReturn(ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("makeClientStreamRequest")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createTemplateExpression(ts.createTemplateHead("/", "/"), [
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("typeName")), ts.createTemplateMiddle("/", "/")),
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("name")), ts.createTemplateTail("", ""))
]),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, this.makeI(source, methodInfo, true), undefined)], ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Buffer"), ts.createIdentifier("from")), undefined, [ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("I")), ts.createIdentifier("toBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])])),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), undefined)], this.makeO(source, methodInfo, true), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("O")), ts.createIdentifier("fromBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])),
ts.createAsExpression(ts.createIdentifier("metadata"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createAsExpression(ts.createIdentifier("options"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createAsExpression(ts.createIdentifier("callback"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))
]))
], true));
}
createDuplexStreaming(source, methodInfo) {
let grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js');
let ServiceType = this.imports.type(source, this.registry.resolveTypeName(methodInfo.service.typeName));
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier(methodInfo.localName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("metadata"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createUnionTypeNode([
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("Metadata")), undefined),
ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined)
]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("CallOptions")), undefined), undefined)
], ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ClientDuplexStream")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
]), ts.createBlock([
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("method"), undefined, ts.createElementAccess(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("methods")), ts.createNumericLiteral(methodInfo.service.methods.indexOf(methodInfo).toString())))], ts.NodeFlags.Const)),
ts.createReturn(ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("makeBidiStreamRequest")), [
this.makeI(source, methodInfo, true),
this.makeO(source, methodInfo, true)
], [
ts.createTemplateExpression(ts.createTemplateHead("/", "/"), [
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier(ServiceType), ts.createIdentifier("typeName")), ts.createTemplateMiddle("/", "/")),
ts.createTemplateSpan(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("name")), ts.createTemplateTail("", ""))
]),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, this.makeI(source, methodInfo, true), undefined)], ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Buffer"), ts.createIdentifier("from")), undefined, [ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("I")), ts.createIdentifier("toBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])])),
ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("Buffer"), undefined), undefined)], this.makeO(source, methodInfo, true), ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("method"), ts.createIdentifier("O")), ts.createIdentifier("fromBinary")), undefined, [
ts.createIdentifier("value"),
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("_binaryOptions"))
])),
ts.createAsExpression(ts.createIdentifier("metadata"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createIdentifier("options")
]))
], true));
}
}
exports.ServiceClientGeneratorGrpc = ServiceClientGeneratorGrpc;

View file

@ -0,0 +1,18 @@
import { GeneratorBase } from "./generator-base";
import { DescriptorRegistry, ServiceDescriptorProto, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { Interpreter } from "../interpreter";
import * as ts from "typescript";
import { CommentGenerator } from "./comment-generator";
export declare class ServiceServerGeneratorGeneric extends GeneratorBase {
private readonly options;
private readonly symbolKindInterface;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {
runtimeRpcImportPath: string;
});
registerSymbols(source: TypescriptFile, descriptor: ServiceDescriptorProto): void;
generateInterface(source: TypescriptFile, descriptor: ServiceDescriptorProto): ts.InterfaceDeclaration;
private createUnary;
private createServerStreaming;
private createClientStreaming;
private createBidi;
}

View file

@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceServerGeneratorGeneric = void 0;
const generator_base_1 = require("./generator-base");
const ts = require("typescript");
const runtime_1 = require("@protobuf-ts/runtime");
const local_type_name_1 = require("./local-type-name");
class ServiceServerGeneratorGeneric extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
this.symbolKindInterface = 'generic-server-interface';
}
registerSymbols(source, descriptor) {
const basename = local_type_name_1.createLocalTypeName(descriptor, this.registry);
const interfaceName = `I${basename}`;
this.symbols.register(interfaceName, descriptor, source, this.symbolKindInterface);
}
generateInterface(source, descriptor) {
const interpreterType = this.interpreter.getServiceType(descriptor), IGenericServer = this.imports.type(source, descriptor, this.symbolKindInterface), ServerCallContext = this.imports.name(source, "ServerCallContext", this.options.runtimeRpcImportPath);
const statement = ts.createInterfaceDeclaration(undefined, [ts.createModifier(ts.SyntaxKind.ExportKeyword)], ts.createIdentifier(IGenericServer), [
ts.createTypeParameterDeclaration("T", undefined, ts.createTypeReferenceNode(ts.createIdentifier(ServerCallContext), undefined))
], undefined, interpreterType.methods.map(mi => {
const methodDescriptor = descriptor.method.find(md => md.name === mi.name);
runtime_1.assert(methodDescriptor);
let signature;
if (mi.serverStreaming && mi.clientStreaming) {
signature = this.createBidi(source, mi);
}
else if (mi.serverStreaming) {
signature = this.createServerStreaming(source, mi);
}
else if (mi.clientStreaming) {
signature = this.createClientStreaming(source, mi);
}
else {
signature = this.createUnary(source, mi);
}
this.comments.addCommentsForDescriptor(signature, methodDescriptor, 'appendToLeadingBlock');
return signature;
}));
// add to our file
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
source.addStatement(statement);
return statement;
}
createUnary(source, methodInfo) {
const I = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName))), undefined), O = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName))), undefined);
return ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("request"), undefined, I, undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("context"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("T"), undefined), undefined)
], ts.createTypeReferenceNode(ts.createIdentifier("Promise"), [O]), ts.createIdentifier(methodInfo.localName), undefined);
}
createServerStreaming(source, methodInfo) {
const I = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName))), undefined), O = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName))), undefined), RpcInputStream = this.imports.name(source, 'RpcInputStream', this.options.runtimeRpcImportPath);
return ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("request"), undefined, I, undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("responses"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(RpcInputStream), [O]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("context"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("T"), undefined), undefined)
], ts.createTypeReferenceNode(ts.createIdentifier("Promise"), [ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)]), ts.createIdentifier(methodInfo.localName), undefined);
}
createClientStreaming(source, methodInfo) {
const I = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName))), undefined), O = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName))), undefined), RpcOutputStream = this.imports.name(source, 'RpcOutputStream', this.options.runtimeRpcImportPath);
return ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("requests"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(RpcOutputStream), [I]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("context"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("T"), undefined), undefined)
], ts.createTypeReferenceNode(ts.createIdentifier("Promise"), [O]), ts.createIdentifier(methodInfo.localName), undefined);
}
createBidi(source, methodInfo) {
const I = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName))), undefined), O = ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName))), undefined), RpcOutputStream = this.imports.name(source, 'RpcOutputStream', this.options.runtimeRpcImportPath), RpcInputStream = this.imports.name(source, 'RpcInputStream', this.options.runtimeRpcImportPath);
return ts.createMethodSignature(undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("requests"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(RpcOutputStream), [I]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("responses"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(RpcInputStream), [O]), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("context"), undefined, ts.createTypeReferenceNode(ts.createIdentifier("T"), undefined), undefined)
], ts.createTypeReferenceNode(ts.createIdentifier("Promise"), [ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)]), ts.createIdentifier(methodInfo.localName), undefined);
}
}
exports.ServiceServerGeneratorGeneric = ServiceServerGeneratorGeneric;

View file

@ -0,0 +1,16 @@
import { GeneratorBase } from "./generator-base";
import { DescriptorRegistry, ServiceDescriptorProto, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { Interpreter } from "../interpreter";
import * as ts from "typescript";
import { CommentGenerator } from "./comment-generator";
export declare class ServiceServerGeneratorGrpc extends GeneratorBase {
private readonly options;
private readonly symbolKindInterface;
private readonly symbolKindDefinition;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {});
registerSymbols(source: TypescriptFile, descriptor: ServiceDescriptorProto): void;
generateInterface(source: TypescriptFile, descriptor: ServiceDescriptorProto): ts.InterfaceDeclaration;
private createMethodPropertySignature;
generateDefinition(source: TypescriptFile, descriptor: ServiceDescriptorProto): ts.VariableStatement;
private makeDefinitionProperty;
}

View file

@ -0,0 +1,89 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceServerGeneratorGrpc = void 0;
const generator_base_1 = require("./generator-base");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const ts = require("typescript");
const runtime_1 = require("@protobuf-ts/runtime");
const local_type_name_1 = require("./local-type-name");
class ServiceServerGeneratorGrpc extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
this.symbolKindInterface = 'grpc-server-interface';
this.symbolKindDefinition = 'grpc-server-definition';
}
registerSymbols(source, descriptor) {
const basename = local_type_name_1.createLocalTypeName(descriptor, this.registry);
const interfaceName = `I${basename}`;
const definitionName = `${basename[0].toLowerCase()}${basename.substring(1)}Definition`;
this.symbols.register(interfaceName, descriptor, source, this.symbolKindInterface);
this.symbols.register(definitionName, descriptor, source, this.symbolKindDefinition);
}
generateInterface(source, descriptor) {
const interpreterType = this.interpreter.getServiceType(descriptor), IGrpcServer = this.imports.type(source, descriptor, this.symbolKindInterface), grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js', true);
const statement = ts.createInterfaceDeclaration(undefined, [ts.createModifier(ts.SyntaxKind.ExportKeyword)], ts.createIdentifier(IGrpcServer), undefined, [ts.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ts.createExpressionWithTypeArguments(undefined, ts.createPropertyAccess(ts.createIdentifier(grpc), ts.createIdentifier("UntypedServiceImplementation")))])], interpreterType.methods.map(mi => {
const methodDescriptor = descriptor.method.find(md => md.name === mi.name);
runtime_1.assert(methodDescriptor);
return this.createMethodPropertySignature(source, mi, methodDescriptor);
}));
// add to our file
this.comments.addCommentsForDescriptor(statement, descriptor, 'appendToLeadingBlock');
source.addStatement(statement);
return statement;
}
createMethodPropertySignature(source, methodInfo, methodDescriptor) {
const grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js', true);
let handler;
if (methodInfo.serverStreaming && methodInfo.clientStreaming) {
handler = 'handleBidiStreamingCall';
}
else if (methodInfo.serverStreaming) {
handler = 'handleServerStreamingCall';
}
else if (methodInfo.clientStreaming) {
handler = 'handleClientStreamingCall';
}
else {
handler = 'handleUnaryCall';
}
const signature = ts.createPropertySignature(undefined, ts.createIdentifier(methodInfo.localName), undefined, ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier(handler)), [
ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName))), undefined),
ts.createTypeReferenceNode(ts.createIdentifier(this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName))), undefined),
]), undefined);
this.comments.addCommentsForDescriptor(signature, methodDescriptor, 'appendToLeadingBlock');
return signature;
}
generateDefinition(source, descriptor) {
const grpcServerDefinition = this.imports.type(source, descriptor, this.symbolKindDefinition), IGrpcServer = this.imports.type(source, descriptor, this.symbolKindInterface), interpreterType = this.interpreter.getServiceType(descriptor), grpc = this.imports.namespace(source, 'grpc', '@grpc/grpc-js', true);
const statement = ts.createVariableStatement([ts.createModifier(ts.SyntaxKind.ExportKeyword)], ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier(grpcServerDefinition), ts.createTypeReferenceNode(ts.createQualifiedName(ts.createIdentifier(grpc), ts.createIdentifier("ServiceDefinition")), [ts.createTypeReferenceNode(ts.createIdentifier(IGrpcServer), undefined)]), ts.createObjectLiteral(interpreterType.methods.map(mi => this.makeDefinitionProperty(source, mi)), true))], ts.NodeFlags.Const));
// add to our file
const doc = `@grpc/grpc-js definition for the protobuf ${this.registry.formatQualifiedName(descriptor)}.\n` +
`\n` +
`Usage: Implement the interface ${IGrpcServer} and add to a grpc server.\n` +
`\n` +
'```typescript\n' +
`const server = new grpc.Server();\n` +
`const service: ${IGrpcServer} = ...\n` +
`server.addService(${grpcServerDefinition}, service);\n` +
'```';
plugin_framework_1.addCommentBlockAsJsDoc(statement, doc);
source.addStatement(statement);
return statement;
}
makeDefinitionProperty(source, methodInfo) {
const I = this.imports.type(source, this.registry.resolveTypeName(methodInfo.I.typeName));
const O = this.imports.type(source, this.registry.resolveTypeName(methodInfo.O.typeName));
return ts.createPropertyAssignment(ts.createIdentifier(methodInfo.localName), ts.createObjectLiteral([
ts.createPropertyAssignment(ts.createIdentifier("path"), ts.createStringLiteral(`/${methodInfo.service.typeName}/${methodInfo.name}`)),
ts.createPropertyAssignment(ts.createIdentifier("originalName"), ts.createStringLiteral(methodInfo.name)),
ts.createPropertyAssignment(ts.createIdentifier("requestStream"), methodInfo.clientStreaming ? ts.createTrue() : ts.createFalse()),
ts.createPropertyAssignment(ts.createIdentifier("responseStream"), methodInfo.serverStreaming ? ts.createTrue() : ts.createFalse()),
ts.createPropertyAssignment(ts.createIdentifier("responseDeserialize"), ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("bytes"), undefined, undefined, undefined)], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier(O), ts.createIdentifier("fromBinary")), undefined, [ts.createIdentifier("bytes")]))),
ts.createPropertyAssignment(ts.createIdentifier("requestDeserialize"), ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("bytes"), undefined, undefined, undefined)], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier(I), ts.createIdentifier("fromBinary")), undefined, [ts.createIdentifier("bytes")]))),
ts.createPropertyAssignment(ts.createIdentifier("responseSerialize"), ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, undefined, undefined)], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Buffer"), ts.createIdentifier("from")), undefined, [ts.createCall(ts.createPropertyAccess(ts.createIdentifier(O), ts.createIdentifier("toBinary")), undefined, [ts.createIdentifier("value")])]))),
ts.createPropertyAssignment(ts.createIdentifier("requestSerialize"), ts.createArrowFunction(undefined, undefined, [ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), undefined, undefined, undefined)], undefined, ts.createToken(ts.SyntaxKind.EqualsGreaterThanToken), ts.createCall(ts.createPropertyAccess(ts.createIdentifier("Buffer"), ts.createIdentifier("from")), undefined, [ts.createCall(ts.createPropertyAccess(ts.createIdentifier(I), ts.createIdentifier("toBinary")), undefined, [ts.createIdentifier("value")])])))
], true));
}
}
exports.ServiceServerGeneratorGrpc = ServiceServerGeneratorGrpc;

View file

@ -0,0 +1,12 @@
import { DescriptorRegistry, ServiceDescriptorProto, SymbolTable, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import { Interpreter } from "../interpreter";
import { CommentGenerator } from "./comment-generator";
import { GeneratorBase } from "./generator-base";
export declare class ServiceTypeGenerator extends GeneratorBase {
private readonly options;
private readonly methodInfoGenerator;
constructor(symbols: SymbolTable, registry: DescriptorRegistry, imports: TypeScriptImports, comments: CommentGenerator, interpreter: Interpreter, options: {
runtimeRpcImportPath: string;
});
generateServiceType(source: TypescriptFile, descriptor: ServiceDescriptorProto): void;
}

View file

@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ServiceTypeGenerator = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const ts = require("typescript");
const method_info_generator_1 = require("./method-info-generator");
const generator_base_1 = require("./generator-base");
class ServiceTypeGenerator extends generator_base_1.GeneratorBase {
constructor(symbols, registry, imports, comments, interpreter, options) {
super(symbols, registry, imports, comments, interpreter);
this.options = options;
this.methodInfoGenerator = new method_info_generator_1.MethodInfoGenerator(this.registry, this.imports);
}
// export const Haberdasher = new ServiceType("spec.haberdasher.Haberdasher", [
// { name: "MakeHat", localName: "makeHat", I: Size, O: Hat },
// ], {});
generateServiceType(source, descriptor) {
const
// identifier for the service
MyService = this.imports.type(source, descriptor), ServiceType = this.imports.name(source, "ServiceType", this.options.runtimeRpcImportPath), interpreterType = this.interpreter.getServiceType(descriptor);
const args = [
ts.createStringLiteral(interpreterType.typeName),
this.methodInfoGenerator.createMethodInfoLiterals(source, interpreterType.methods)
];
if (Object.keys(interpreterType.options).length) {
args.push(plugin_framework_1.typescriptLiteralFromValue(interpreterType.options));
}
const exportConst = ts.createVariableStatement([ts.createModifier(ts.SyntaxKind.ExportKeyword)], ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier(MyService), undefined, ts.createNew(ts.createIdentifier(ServiceType), undefined, args))], ts.NodeFlags.Const));
// add to our file
source.addStatement(exportConst);
// add comments
let comment = this.comments.makeDeprecatedTag(descriptor);
comment += this.comments.makeGeneratedTag(descriptor).replace("@generated from ", "@generated ServiceType for ");
plugin_framework_1.addCommentBlockAsJsDoc(exportConst, comment);
return;
}
}
exports.ServiceTypeGenerator = ServiceTypeGenerator;

View file

@ -0,0 +1,6 @@
import { CodeGeneratorRequest, CodeGeneratorResponse_Feature, GeneratedFile, PluginBase } from "@protobuf-ts/plugin-framework";
export declare class DumpPlugin extends PluginBase<GeneratedFile> {
generate(request: CodeGeneratorRequest): GeneratedFile[];
private static mkdir;
protected getSupportedFeatures: () => CodeGeneratorResponse_Feature[];
}

View file

@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DumpPlugin = void 0;
const fs_1 = require("fs");
const path = require("path");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const BIN_SUFFIX = '.codegenreq';
const JSON_SUFFIX = '.json';
const USAGE = `protoc-gen-dump can be run in 2 ways, depending on the given parameter (--dump_opt=<parameter>)
1) parameter ending in ${BIN_SUFFIX}
Dumps a 'CodeGeneratorRequest' in binary format.
The request is dumped to the path specified by the parameter.
Example:
protoc --plugin node_modules/.bin/protoc-gen-dump --dump_opt my-dump.bin --dump_out . -I protos/ protos/*.proto
2) parameter ending in ${JSON_SUFFIX}
Dumps a 'CodeGeneratorRequest' in JSON format.
The request is dumped to the path specified by the parameter.
Example:
protoc --plugin node_modules/.bin/protoc-gen-dump --dump_opt my-dump.json --dump_out . -I protos/ protos/*.proto
`;
class DumpPlugin extends plugin_framework_1.PluginBase {
constructor() {
super(...arguments);
// we support proto3-optionals, so we let protoc know
this.getSupportedFeatures = () => [plugin_framework_1.CodeGeneratorResponse_Feature.PROTO3_OPTIONAL];
}
generate(request) {
const parameter = request.parameter;
if (parameter === null || parameter === void 0 ? void 0 : parameter.endsWith(JSON_SUFFIX)) {
DumpPlugin.mkdir(parameter);
fs_1.writeFileSync(parameter, plugin_framework_1.CodeGeneratorRequest.toJsonString(request, { prettySpaces: 2 }));
}
else if (parameter === null || parameter === void 0 ? void 0 : parameter.endsWith(BIN_SUFFIX)) {
DumpPlugin.mkdir(parameter);
let bytes = plugin_framework_1.CodeGeneratorRequest.toBinary(request);
fs_1.writeFileSync(parameter, bytes);
try {
plugin_framework_1.CodeGeneratorRequest.fromBinary(bytes);
}
catch (e) {
throw new Error("Sanity check failed: " + e);
}
}
else {
throw USAGE;
}
return [];
}
static mkdir(file) {
if (!fs_1.existsSync(path.dirname(file))) {
fs_1.mkdirSync(path.dirname(file), { recursive: true });
}
}
}
exports.DumpPlugin = DumpPlugin;

View file

@ -0,0 +1,31 @@
import { FileDescriptorProto } from "@protobuf-ts/plugin-framework";
export declare class FileTable {
private readonly entries;
private readonly clashResolveMaxTries;
private readonly clashResolver;
constructor(clashResolver?: ClashResolver);
register(requestedName: string, descriptor: FileDescriptorProto, kind?: string): string;
protected hasName: (name: string) => boolean;
/**
* Find a symbol (of the given kind) for the given descriptor.
* Return `undefined` if not found.
*/
find(descriptor: FileDescriptorProto, kind?: string): FileTableEntry | undefined;
/**
* Find a symbol (of the given kind) for the given descriptor.
* Raises error if not found.
*/
get(descriptor: FileDescriptorProto, kind?: string): FileTableEntry;
/**
* Is a name (of the given kind) registered for the the given descriptor?
*/
has(descriptor: FileDescriptorProto, kind?: string): boolean;
static defaultClashResolver(descriptor: FileDescriptorProto, requestedName: string, kind: string, tryCount: number): string;
}
interface FileTableEntry {
descriptor: FileDescriptorProto;
name: string;
kind: string;
}
declare type ClashResolver = (descriptor: FileDescriptorProto, requestedName: string, kind: string, tryCount: number, failedName: string) => string;
export {};

View file

@ -0,0 +1,72 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileTable = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
class FileTable {
constructor(clashResolver) {
this.entries = [];
this.clashResolveMaxTries = 100;
this.hasName = (name) => this.entries.some(e => e.name === name);
this.clashResolver = clashResolver !== null && clashResolver !== void 0 ? clashResolver : FileTable.defaultClashResolver;
}
register(requestedName, descriptor, kind = 'default') {
// Only one symbol per kind can be registered for a descriptor.
if (this.has(descriptor, kind)) {
let { name } = this.get(descriptor, kind);
let msg = `Cannot register name "${requestedName}" of kind "${kind}" for ${plugin_framework_1.StringFormat.formatName(descriptor)}. `
+ `The descriptor is already registered with name "${name}". `
+ `Use a different 'kind' to register multiple symbols for a descriptor.`;
throw new Error(msg);
}
// find a free name within the file
let name = requestedName;
let count = 0;
while (this.hasName(name) && count < this.clashResolveMaxTries) {
name = this.clashResolver(descriptor, requestedName, kind, ++count, name);
}
if (this.hasName(name)) {
let msg = `Failed to register name "${requestedName}" for ${plugin_framework_1.StringFormat.formatName(descriptor)}. `
+ `Gave up finding alternative name after ${this.clashResolveMaxTries} tries. `
+ `There is something wrong with the clash resolver.`;
throw new Error(msg);
}
// add the entry and return name
this.entries.push({ descriptor, kind, name });
return name;
}
/**
* Find a symbol (of the given kind) for the given descriptor.
* Return `undefined` if not found.
*/
find(descriptor, kind = 'default') {
return this.entries.find(e => e.descriptor === descriptor && e.kind === kind);
}
/**
* Find a symbol (of the given kind) for the given descriptor.
* Raises error if not found.
*/
get(descriptor, kind = 'default') {
const found = this.find(descriptor, kind);
if (!found) {
let msg = `Failed to find name for ${plugin_framework_1.StringFormat.formatName(descriptor)} of kind "${kind}". `
+ `Searched in ${this.entries.length} files.`;
throw new Error(msg);
}
return found;
}
/**
* Is a name (of the given kind) registered for the the given descriptor?
*/
has(descriptor, kind = 'default') {
return !!this.find(descriptor, kind);
}
static defaultClashResolver(descriptor, requestedName, kind, tryCount) {
const lastDotI = requestedName.lastIndexOf('.');
let basename = lastDotI > 0 ? requestedName.substring(0, lastDotI) : requestedName;
const suffix = lastDotI > 0 ? requestedName.substring(lastDotI) : '';
basename = basename.endsWith('$') ? basename.substring(1) : basename;
basename = basename + '$' + tryCount;
return basename + suffix;
}
}
exports.FileTable = FileTable;

View file

@ -0,0 +1,122 @@
import { DescriptorProto, DescriptorRegistry, EnumDescriptorProto, FieldDescriptorProto, FieldOptions_JSType, FileDescriptorProto, MethodDescriptorProto, ServiceDescriptorProto } from "@protobuf-ts/plugin-framework";
import * as rt from "@protobuf-ts/runtime";
import * as rpc from "@protobuf-ts/runtime-rpc";
import { OurFileOptions, OurServiceOptions } from "./our-options";
declare type JsonOptionsMap = {
[extensionName: string]: rt.JsonValue;
};
/**
* The protobuf-ts plugin generates code for message types from descriptor
* protos. This class also creates message types from descriptor protos, but
* but instead of generating code, it creates the type in-memory.
*
* This means that it is possible, for example, to read a message from binary
* data without any generated code.
*
* The protobuf-ts plugin uses the interpreter to read custom options at
* compile time and convert them to JSON.
*
* Since the interpreter creates fully functional message types including
* reflection information, the protobuf-ts plugin uses the interpreter as
* single source of truth for generating message interfaces and reflection
* information.
*/
export declare class Interpreter {
private readonly registry;
private readonly options;
private readonly serviceTypes;
private readonly messageTypes;
private readonly enumInfos;
constructor(registry: DescriptorRegistry, options: {
normalLongType: rt.LongType;
oneofKindDiscriminator: string;
synthesizeEnumZeroValue: string | false;
forceExcludeAllOptions: boolean;
keepEnumPrefix: boolean;
useProtoFieldName: boolean;
});
/**
* Returns a map of custom options for the provided descriptor.
* The map is an object indexed by the extension field name.
* The value of the extension field is provided in JSON format.
*
* This works by:
* - searching for option extensions for the given descriptor proto
* in the registry.
* - for example, providing a google.protobuf.FieldDescriptorProto
* searches for all extensions on google.protobuf.FieldOption.
* - extensions are just fields, so we build a synthetic message
* type with all the (extension) fields.
* - the field names are created by DescriptorRegistry.getExtensionName(),
* which produces for example "spec.option_name", where "spec" is
* the package and "option_name" is the field name.
* - then we concatenate all unknown field data of the option and
* read the data with our synthetic message type
* - the read message is then simply converted to JSON
*
* The optional "optionBlacklist" will exclude matching options.
* The blacklist can contain exact extension names, or use the wildcard
* character `*` to match a namespace or even all options.
*
* Note that options on options (google.protobuf.*Options) are not
* supported.
*/
readOptions(descriptor: FieldDescriptorProto | MethodDescriptorProto | FileDescriptorProto | ServiceDescriptorProto | DescriptorProto, excludeOptions: readonly string[]): JsonOptionsMap | undefined;
/**
* Read the custom file options declared in protobuf-ts.proto
*/
readOurFileOptions(file: FileDescriptorProto): OurFileOptions;
/**
* Read the custom service options declared in protobuf-ts.proto
*/
readOurServiceOptions(service: ServiceDescriptorProto): OurServiceOptions;
/**
* Get a runtime type for the given message type name or message descriptor.
* Creates the type if not created previously.
*
* Honors our file option "ts.exclude_options".
*/
getMessageType(descriptorOrTypeName: string | DescriptorProto): rt.IMessageType<rt.UnknownMessage>;
/**
* Get a runtime type for the given service type name or service descriptor.
* Creates the type if not created previously.
*
* Honors our file option "ts.exclude_options".
*/
getServiceType(descriptorOrTypeName: string | ServiceDescriptorProto): rpc.ServiceType;
/**
* Get runtime information for an enum.
* Creates the info if not created previously.
*/
getEnumInfo(descriptorOrTypeName: string | EnumDescriptorProto): rt.EnumInfo;
private static createTypescriptNameForMethod;
private buildServiceType;
private buildMethodInfo;
/**
* Create a name for a field or a oneof.
* - use lowerCamelCase unless useProtoFieldName option is enabled
* - escape reserved object property names by
* adding '$' at the end
* - don't have to escape reserved keywords
*/
private createTypescriptNameForField;
private buildFieldInfos;
private buildFieldInfo;
protected buildEnumInfo(descriptor: EnumDescriptorProto): rt.EnumInfo;
protected determineNonDefaultLongType(scalarType: rt.ScalarType, jsTypeOption?: FieldOptions_JSType): rt.LongType | undefined;
/**
* Is this a 64 bit integral or fixed type?
*/
static isLongValueType(type: rt.ScalarType): boolean;
}
/**
* Builds a typescript enum lookup object,
* compatible with enums generated by @protobuf-ts/plugin.
*/
export declare class RuntimeEnumBuilder {
private readonly values;
add(name: string, number: number): void;
isValid(): boolean;
build(): rt.EnumInfo[1];
}
export {};

View file

@ -0,0 +1,526 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.RuntimeEnumBuilder = exports.Interpreter = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const rt = require("@protobuf-ts/runtime");
const runtime_1 = require("@protobuf-ts/runtime");
const rpc = require("@protobuf-ts/runtime-rpc");
const field_info_generator_1 = require("./code-gen/field-info-generator");
const our_options_1 = require("./our-options");
/**
* The protobuf-ts plugin generates code for message types from descriptor
* protos. This class also creates message types from descriptor protos, but
* but instead of generating code, it creates the type in-memory.
*
* This means that it is possible, for example, to read a message from binary
* data without any generated code.
*
* The protobuf-ts plugin uses the interpreter to read custom options at
* compile time and convert them to JSON.
*
* Since the interpreter creates fully functional message types including
* reflection information, the protobuf-ts plugin uses the interpreter as
* single source of truth for generating message interfaces and reflection
* information.
*/
class Interpreter {
constructor(registry, options) {
this.registry = registry;
this.options = options;
this.serviceTypes = new Map();
this.messageTypes = new Map();
this.enumInfos = new Map();
}
/**
* Returns a map of custom options for the provided descriptor.
* The map is an object indexed by the extension field name.
* The value of the extension field is provided in JSON format.
*
* This works by:
* - searching for option extensions for the given descriptor proto
* in the registry.
* - for example, providing a google.protobuf.FieldDescriptorProto
* searches for all extensions on google.protobuf.FieldOption.
* - extensions are just fields, so we build a synthetic message
* type with all the (extension) fields.
* - the field names are created by DescriptorRegistry.getExtensionName(),
* which produces for example "spec.option_name", where "spec" is
* the package and "option_name" is the field name.
* - then we concatenate all unknown field data of the option and
* read the data with our synthetic message type
* - the read message is then simply converted to JSON
*
* The optional "optionBlacklist" will exclude matching options.
* The blacklist can contain exact extension names, or use the wildcard
* character `*` to match a namespace or even all options.
*
* Note that options on options (google.protobuf.*Options) are not
* supported.
*/
readOptions(descriptor, excludeOptions) {
// the option to force exclude all options takes precedence
if (this.options.forceExcludeAllOptions) {
return undefined;
}
// if options message not present, there cannot be any extension options
if (!descriptor.options) {
return undefined;
}
// if no unknown fields present, can exit early
let unknownFields = rt.UnknownFieldHandler.list(descriptor.options);
if (!unknownFields.length) {
return undefined;
}
let optionsTypeName;
if (plugin_framework_1.FieldDescriptorProto.is(descriptor) && plugin_framework_1.DescriptorProto.is(this.registry.parentOf(descriptor))) {
optionsTypeName = 'google.protobuf.FieldOptions';
}
else if (plugin_framework_1.MethodDescriptorProto.is(descriptor)) {
optionsTypeName = 'google.protobuf.MethodOptions';
}
else if (this.registry.fileOf(descriptor) === descriptor) {
optionsTypeName = 'google.protobuf.FileOptions';
}
else if (plugin_framework_1.ServiceDescriptorProto.is(descriptor)) {
optionsTypeName = 'google.protobuf.ServiceOptions';
}
else if (plugin_framework_1.DescriptorProto.is(descriptor)) {
optionsTypeName = 'google.protobuf.MessageOptions';
}
else {
throw new Error("interpreter expected field or method descriptor");
}
// create a synthetic type that has all extension fields for field options
const typeName = `$synthetic.${optionsTypeName}`;
let type = this.messageTypes.get(typeName);
if (!type) {
type = new rt.MessageType(typeName, this.buildFieldInfos(this.registry.extensionsFor(optionsTypeName)), {});
this.messageTypes.set(typeName, type);
}
// concat all unknown field data
const unknownWriter = new rt.BinaryWriter();
for (let { no, wireType, data } of unknownFields) {
unknownWriter.tag(no, wireType).raw(data);
}
const unknownBytes = unknownWriter.finish();
// read data, to json
const json = type.toJson(type.fromBinary(unknownBytes, { readUnknownField: false }));
runtime_1.assert(rt.isJsonObject(json));
// apply blacklist
if (excludeOptions) {
// we distinguish between literal blacklist (no wildcard)
let literals = excludeOptions.filter(str => !str.includes("*"));
// and wildcard, which we turn into RE
let wildcards = excludeOptions.filter(str => str.includes("*"))
.map(str => str.replace(/[.+\-?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*'));
// then we delete the blacklisted options
for (let key of Object.keys(json)) {
for (let str of literals)
if (key === str)
delete json[key];
for (let re of wildcards)
if (key.match(re))
delete json[key];
}
}
// were *all* options blacklisted?
if (!Object.keys(json).length) {
return undefined;
}
return json;
}
/**
* Read the custom file options declared in protobuf-ts.proto
*/
readOurFileOptions(file) {
return our_options_1.readOurFileOptions(file);
}
/**
* Read the custom service options declared in protobuf-ts.proto
*/
readOurServiceOptions(service) {
return our_options_1.readOurServiceOptions(service);
}
/**
* Get a runtime type for the given message type name or message descriptor.
* Creates the type if not created previously.
*
* Honors our file option "ts.exclude_options".
*/
getMessageType(descriptorOrTypeName) {
let descriptor = typeof descriptorOrTypeName === "string"
? this.registry.resolveTypeName(descriptorOrTypeName)
: descriptorOrTypeName;
let typeName = this.registry.makeTypeName(descriptor);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(descriptor));
let type = this.messageTypes.get(typeName);
if (!type) {
// Create and store the message type
const optionsPlaceholder = {};
type = new rt.MessageType(typeName, this.buildFieldInfos(descriptor.field), optionsPlaceholder);
this.messageTypes.set(typeName, type);
const ourFileOptions = this.readOurFileOptions(this.registry.fileOf(descriptor));
// add message options *after* storing, so that the option can refer to itself
const messageOptions = this.readOptions(descriptor, ourFileOptions["ts.exclude_options"]);
if (messageOptions) {
for (let key of Object.keys(messageOptions)) {
optionsPlaceholder[key] = messageOptions[key];
}
}
// same for field options
for (let i = 0; i < type.fields.length; i++) {
const fd = descriptor.field[i];
const fi = type.fields[i];
fi.options = this.readOptions(fd, ourFileOptions["ts.exclude_options"]);
}
}
return type;
}
/**
* Get a runtime type for the given service type name or service descriptor.
* Creates the type if not created previously.
*
* Honors our file option "ts.exclude_options".
*/
getServiceType(descriptorOrTypeName) {
let descriptor = typeof descriptorOrTypeName === "string"
? this.registry.resolveTypeName(descriptorOrTypeName)
: descriptorOrTypeName;
let typeName = this.registry.makeTypeName(descriptor);
runtime_1.assert(plugin_framework_1.ServiceDescriptorProto.is(descriptor));
let type = this.serviceTypes.get(typeName);
if (!type) {
const ourFileOptions = this.readOurFileOptions(this.registry.fileOf(descriptor));
type = this.buildServiceType(typeName, descriptor.method, ourFileOptions["ts.exclude_options"].concat("ts.client"));
this.serviceTypes.set(typeName, type);
}
return type;
}
/**
* Get runtime information for an enum.
* Creates the info if not created previously.
*/
getEnumInfo(descriptorOrTypeName) {
var _a;
let descriptor = typeof descriptorOrTypeName === "string"
? this.registry.resolveTypeName(descriptorOrTypeName)
: descriptorOrTypeName;
let typeName = this.registry.makeTypeName(descriptor);
runtime_1.assert(plugin_framework_1.EnumDescriptorProto.is(descriptor));
let enumInfo = (_a = this.enumInfos.get(typeName)) !== null && _a !== void 0 ? _a : this.buildEnumInfo(descriptor);
this.enumInfos.set(typeName, enumInfo);
return enumInfo;
}
static createTypescriptNameForMethod(descriptor) {
let escapeCharacter = '$';
let reservedClassProperties = [
// js built in
"__proto__", "toString", "name", "constructor",
// generic clients
"methods", "typeName", "options", "_transport",
// @grpc/grpc-js clients
"close", "getChannel", "waitForReady", "makeUnaryRequest", "makeClientStreamRequest", "makeServerStreamRequest", "makeBidiStreamRequest"
];
let name = descriptor.name;
runtime_1.assert(name !== undefined);
name = rt.lowerCamelCase(name);
if (reservedClassProperties.includes(name)) {
name = name + escapeCharacter;
}
return name;
}
buildServiceType(typeName, methods, excludeOptions) {
let desc = this.registry.resolveTypeName(typeName);
runtime_1.assert(plugin_framework_1.ServiceDescriptorProto.is(desc));
return new rpc.ServiceType(typeName, methods.map(m => this.buildMethodInfo(m, excludeOptions)), this.readOptions(desc, excludeOptions));
}
buildMethodInfo(methodDescriptor, excludeOptions) {
runtime_1.assert(methodDescriptor.name);
runtime_1.assert(methodDescriptor.inputType);
runtime_1.assert(methodDescriptor.outputType);
let info = {};
// name: The name of the method as declared in .proto
info.name = methodDescriptor.name;
// localName: The name of the method in the runtime.
let localName = Interpreter.createTypescriptNameForMethod(methodDescriptor);
if (localName !== rt.lowerCamelCase(methodDescriptor.name)) {
info.localName = localName;
}
// idempotency: The idempotency level as specified in .proto.
if (methodDescriptor.options) {
let idem = methodDescriptor.options.idempotencyLevel;
if (idem !== undefined && idem !== plugin_framework_1.MethodOptions_IdempotencyLevel.IDEMPOTENCY_UNKNOWN) {
info.idempotency = plugin_framework_1.MethodOptions_IdempotencyLevel[idem];
}
}
// serverStreaming: Was the rpc declared with server streaming?
if (methodDescriptor.serverStreaming) {
info.serverStreaming = true;
}
// clientStreaming: Was the rpc declared with client streaming?
if (methodDescriptor.clientStreaming) {
info.clientStreaming = true;
}
// I: The generated type handler for the input message.
info.I = this.getMessageType(methodDescriptor.inputType);
// O: The generated type handler for the output message.
info.O = this.getMessageType(methodDescriptor.outputType);
// options: Contains custom method options from the .proto source in JSON format.
info.options = this.readOptions(methodDescriptor, excludeOptions);
return info;
}
/**
* Create a name for a field or a oneof.
* - use lowerCamelCase unless useProtoFieldName option is enabled
* - escape reserved object property names by
* adding '$' at the end
* - don't have to escape reserved keywords
*/
createTypescriptNameForField(descriptor, escapeCharacter = '$') {
const reservedObjectProperties = '__proto__,toString'.split(',');
let name = descriptor.name;
runtime_1.assert(name !== undefined);
name = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName(name, this.options);
if (reservedObjectProperties.includes(name)) {
name = name + escapeCharacter;
}
if (this.options.oneofKindDiscriminator.split(',').includes(name)) {
name = name + escapeCharacter;
}
return name;
}
// skips GROUP field type
buildFieldInfos(fieldDescriptors) {
const result = [];
for (const fd of fieldDescriptors) {
if (this.registry.isGroupField(fd)) {
// We ignore groups.
// Note that groups are deprecated and not supported in proto3.
continue;
}
const fi = this.buildFieldInfo(fd);
if (fi) {
result.push(fi);
}
}
return result;
}
// throws on unexpected field types, notably GROUP
buildFieldInfo(fieldDescriptor) {
var _a, _b;
runtime_1.assert(fieldDescriptor.number);
runtime_1.assert(fieldDescriptor.name);
let info = {};
// no: The field number of the .proto field.
info.no = fieldDescriptor.number;
// name: The original name of the .proto field.
info.name = fieldDescriptor.name;
// kind: discriminator
info.kind = undefined;
// localName: The name of the field in the runtime.
let localName = this.createTypescriptNameForField(fieldDescriptor);
if (localName !== rt.lowerCamelCase(fieldDescriptor.name)) {
info.localName = localName;
}
// jsonName: The name of the field in JSON.
const jsonName = this.registry.getFieldCustomJsonName(fieldDescriptor);
if (jsonName !== undefined) {
info.jsonName = jsonName;
}
// oneof: The name of the `oneof` group, if this field belongs to one.
if (this.registry.isUserDeclaredOneof(fieldDescriptor)) {
runtime_1.assert(fieldDescriptor.oneofIndex !== undefined);
const parentDescriptor = this.registry.parentOf(fieldDescriptor);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(parentDescriptor));
const ooDecl = parentDescriptor.oneofDecl[fieldDescriptor.oneofIndex];
info.oneof = this.createTypescriptNameForField(ooDecl);
}
// repeat: Is the field repeated?
if (this.registry.isUserDeclaredRepeated(fieldDescriptor)) {
let packed = this.registry.shouldBePackedRepeated(fieldDescriptor);
info.repeat = packed ? rt.RepeatType.PACKED : rt.RepeatType.UNPACKED;
}
// opt: Is the field optional?
if (this.registry.isScalarField(fieldDescriptor) || this.registry.isEnumField(fieldDescriptor)) {
if (this.registry.isUserDeclaredOptional(fieldDescriptor)) {
info.opt = true;
}
}
// jsonName: The name for JSON serialization / deserialization.
if (fieldDescriptor.jsonName) {
info.jsonName = fieldDescriptor.jsonName;
}
if (this.registry.isScalarField(fieldDescriptor)) {
// kind:
info.kind = "scalar";
// T: Scalar field type.
info.T = this.registry.getScalarFieldType(fieldDescriptor);
// L?: JavaScript long type
let L = this.determineNonDefaultLongType(info.T, (_a = fieldDescriptor.options) === null || _a === void 0 ? void 0 : _a.jstype);
if (L !== undefined) {
info.L = L;
}
}
else if (this.registry.isEnumField(fieldDescriptor)) {
// kind:
info.kind = "enum";
// T: Return enum field type info.
info.T = () => this.getEnumInfo(this.registry.getEnumFieldEnum(fieldDescriptor));
}
else if (this.registry.isMessageField(fieldDescriptor)) {
// kind:
info.kind = "message";
// T: Return message field type handler.
info.T = () => this.getMessageType(this.registry.getMessageFieldMessage(fieldDescriptor));
}
else if (this.registry.isMapField(fieldDescriptor)) {
// kind:
info.kind = "map";
// K: Map field key type.
info.K = this.registry.getMapKeyType(fieldDescriptor);
// V: Map field value type.
info.V = {};
let mapV = this.registry.getMapValueType(fieldDescriptor);
if (typeof mapV === "number") {
info.V = {
kind: "scalar",
T: mapV
};
let L = this.determineNonDefaultLongType(info.V.T, (_b = fieldDescriptor.options) === null || _b === void 0 ? void 0 : _b.jstype);
if (L !== undefined) {
info.V.L = L;
}
}
else if (plugin_framework_1.DescriptorProto.is(mapV)) {
const messageDescriptor = mapV;
info.V = {
kind: "message",
T: () => this.getMessageType(messageDescriptor)
};
}
else {
const enumDescriptor = mapV;
info.V = {
kind: "enum",
T: () => this.getEnumInfo(enumDescriptor)
};
}
}
else {
throw new Error(`Unexpected field type for ${this.registry.formatQualifiedName(fieldDescriptor)}`);
}
// extension fields are treated differently
if (this.registry.isExtension(fieldDescriptor)) {
let extensionName = this.registry.getExtensionName(fieldDescriptor);
// always optional (unless repeated...)
info.opt = info.repeat === undefined || info.repeat === rt.RepeatType.NO;
info.name = extensionName;
info.localName = extensionName;
info.jsonName = extensionName;
info.oneof = undefined;
}
return info;
}
buildEnumInfo(descriptor) {
let sharedPrefix = this.options.keepEnumPrefix
? undefined
: this.registry.findEnumSharedPrefix(descriptor, `${descriptor.name}`);
let hasZero = descriptor.value.some(v => v.number === 0);
let builder = new RuntimeEnumBuilder();
if (!hasZero && typeof this.options.synthesizeEnumZeroValue == 'string') {
builder.add(this.options.synthesizeEnumZeroValue, 0);
}
for (let enumValueDescriptor of descriptor.value) {
let name = enumValueDescriptor.name;
runtime_1.assert(name !== undefined);
runtime_1.assert(enumValueDescriptor.number !== undefined);
if (sharedPrefix) {
name = name.substring(sharedPrefix.length);
}
builder.add(name, enumValueDescriptor.number);
}
let enumInfo = [
this.registry.makeTypeName(descriptor),
builder.build(),
];
if (sharedPrefix) {
enumInfo = [enumInfo[0], enumInfo[1], sharedPrefix];
}
return enumInfo;
}
determineNonDefaultLongType(scalarType, jsTypeOption) {
if (!Interpreter.isLongValueType(scalarType)) {
return undefined;
}
if (jsTypeOption !== undefined) {
switch (jsTypeOption) {
case plugin_framework_1.FieldOptions_JSType.JS_STRING:
// omitting L equals to STRING
return undefined;
case plugin_framework_1.FieldOptions_JSType.JS_NORMAL:
return rt.LongType.BIGINT;
case plugin_framework_1.FieldOptions_JSType.JS_NUMBER:
return rt.LongType.NUMBER;
}
}
// at this point, there either was no js_type option or it was JS_NORMAL,
// so we use our normal long type
if (this.options.normalLongType === rt.LongType.STRING) {
// since STRING is default, we do not set it
return undefined;
}
return this.options.normalLongType;
}
/**
* Is this a 64 bit integral or fixed type?
*/
static isLongValueType(type) {
switch (type) {
case rt.ScalarType.INT64:
case rt.ScalarType.UINT64:
case rt.ScalarType.FIXED64:
case rt.ScalarType.SFIXED64:
case rt.ScalarType.SINT64:
return true;
default:
return false;
}
}
}
exports.Interpreter = Interpreter;
/**
* Builds a typescript enum lookup object,
* compatible with enums generated by @protobuf-ts/plugin.
*/
class RuntimeEnumBuilder {
constructor() {
this.values = [];
}
add(name, number) {
this.values.push({ name, number });
}
isValid() {
try {
this.build();
}
catch (e) {
return false;
}
return true;
}
build() {
if (this.values.map(v => v.name).some((name, i, a) => a.indexOf(name) !== i)) {
throw new Error("duplicate names");
}
let object = {};
for (let v of this.values) {
object[v.number] = v.name;
object[v.name] = v.number;
}
if (rt.isEnumObject(object)) {
return object;
}
throw new Error("not a typescript enum object");
}
}
exports.RuntimeEnumBuilder = RuntimeEnumBuilder;

View file

@ -0,0 +1,24 @@
import { DescriptorProto, DescriptorRegistry, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import * as ts from "typescript";
import { LongType } from "@protobuf-ts/runtime";
import { Interpreter } from "../interpreter";
import { CustomMethodGenerator } from "../code-gen/message-type-generator";
/**
* Generates a "create()" method for an `IMessageType`
*/
export declare class Create implements CustomMethodGenerator {
private readonly registry;
private readonly imports;
private readonly interpreter;
private readonly options;
constructor(registry: DescriptorRegistry, imports: TypeScriptImports, interpreter: Interpreter, options: {
normalLongType: LongType;
oneofKindDiscriminator: string;
runtimeImportPath: string;
});
make(source: TypescriptFile, descriptor: DescriptorProto): ts.MethodDeclaration[];
makeMethod(source: TypescriptFile, descriptor: DescriptorProto, ...bodyStatements: readonly ts.Statement[]): ts.MethodDeclaration;
makeMessageVariable(): ts.VariableStatement;
makeMessagePropertyAssignments(source: TypescriptFile, descriptor: DescriptorProto): ts.ExpressionStatement[];
makeMergeIf(source: TypescriptFile, descriptor: DescriptorProto): ts.IfStatement;
}

View file

@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Create = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const ts = require("typescript");
/**
* Generates a "create()" method for an `IMessageType`
*/
class Create {
constructor(registry, imports, interpreter, options) {
this.registry = registry;
this.imports = imports;
this.interpreter = interpreter;
this.options = options;
}
// create(value?: PartialMessage<ScalarValuesMessage>): ScalarValuesMessage {
make(source, descriptor) {
// create(value?: PartialMessage<ScalarValuesMessage>): ScalarValuesMessage {
let methodDeclaration = this.makeMethod(source, descriptor,
// const message = globalThis.Object.create(this.messagePrototype);
this.makeMessageVariable(),
// message.boolField = false;
// message.repeatedField = [];
// message.mapField = {};
// ...
...this.makeMessagePropertyAssignments(source, descriptor),
// if (value !== undefined)
// reflectionMergePartial<ScalarValuesMessage>(message, value, this);
this.makeMergeIf(source, descriptor),
// return message;
ts.createReturn(ts.createIdentifier("message")));
return [methodDeclaration];
}
makeMethod(source, descriptor, ...bodyStatements) {
const MessageInterface = this.imports.type(source, descriptor), PartialMessage = this.imports.name(source, 'PartialMessage', this.options.runtimeImportPath, true);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier("create"), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(PartialMessage, [
ts.createTypeReferenceNode((MessageInterface), undefined)
]), undefined)
], ts.createTypeReferenceNode(MessageInterface, undefined), ts.createBlock(bodyStatements, true));
}
makeMessageVariable() {
return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("message"), undefined, ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("globalThis"), ts.createIdentifier("Object")), ts.createIdentifier("create")), undefined, [
ts.createNonNullExpression(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("messagePrototype")))
]))], ts.NodeFlags.Const));
}
makeMessagePropertyAssignments(source, descriptor) {
let messageType = this.interpreter.getMessageType(descriptor);
let defaultMessage = messageType.create();
return Object.entries(defaultMessage).map(([key, value]) => (ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("message"), ts.createIdentifier(key)), ts.createToken(ts.SyntaxKind.EqualsToken), plugin_framework_1.typescriptLiteralFromValue(value)))));
}
makeMergeIf(source, descriptor) {
const MessageInterface = this.imports.type(source, descriptor);
return ts.createIf(ts.createBinary(ts.createIdentifier("value"), ts.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.createIdentifier("undefined")), ts.createExpressionStatement(ts.createCall(ts.createIdentifier(this.imports.name(source, 'reflectionMergePartial', this.options.runtimeImportPath)), [ts.createTypeReferenceNode(MessageInterface, undefined)], [
ts.createThis(),
ts.createIdentifier("message"),
ts.createIdentifier("value"),
])), undefined);
}
}
exports.Create = Create;

View file

@ -0,0 +1,22 @@
import { DescriptorProto, ITypeNameLookup, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import * as ts from "typescript";
import { LongType } from "@protobuf-ts/runtime";
import { CustomMethodGenerator } from "../code-gen/message-type-generator";
export declare class GoogleTypes implements CustomMethodGenerator {
private readonly typeNameLookup;
private readonly imports;
private readonly options;
constructor(typeNameLookup: ITypeNameLookup, imports: TypeScriptImports, options: {
normalLongType: LongType;
runtimeImportPath: string;
useProtoFieldName: boolean;
});
/**
* Create custom methods for the handlers of some google types.
*/
make(source: TypescriptFile, descriptor: DescriptorProto): ts.MethodDeclaration[];
['google.type.Color'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.type.Date'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.type.DateTime'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.type.TimeOfDay'](source: TypescriptFile, descriptor: DescriptorProto): string[];
}

View file

@ -0,0 +1,241 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GoogleTypes = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const runtime_1 = require("@protobuf-ts/runtime");
const field_info_generator_1 = require("../code-gen/field-info-generator");
class GoogleTypes {
constructor(typeNameLookup, imports, options) {
this.typeNameLookup = typeNameLookup;
this.imports = imports;
this.options = options;
}
/**
* Create custom methods for the handlers of some google types.
*/
make(source, descriptor) {
const typeName = this.typeNameLookup.makeTypeName(descriptor), fn = this[typeName];
if (fn) {
let r = fn.apply(this, [source, descriptor]);
if (typeof r == "string") {
return [plugin_framework_1.typescriptMethodFromText(r)];
}
if (Array.isArray(r)) {
return r.map(txt => plugin_framework_1.typescriptMethodFromText(txt));
}
}
return [];
}
['google.type.Color'](source, descriptor) {
const Color = this.imports.type(source, descriptor);
return [
`
/**
* Returns hexadecimal notation of the color: #RRGGBB[AA]
*
* R (red), G (green), B (blue), and A (alpha) are hexadecimal characters
* (09, AF). A is optional. For example, #ff0000 is equivalent to
* #ff0000ff.
*
* See https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#RGB_colors
*/
function toHex(message: ${Color}): string {
let hex = [
message.red.toString(16),
message.green.toString(16),
message.blue.toString(16),
];
if (message.alpha) {
let alpha = Math.max(Math.min(message.alpha.value, 1), 0);
hex.push(Math.round(alpha * 255).toString(16));
}
return '#' + hex.map(i => i.length < 2 ? '0' + i : i).join('');
}
`,
`
/**
* Parses a hexadecimal color notation.
*
* Recognizes the following forms:
* - three-digit (#RGB)
* - six-digit (#RRGGBB)
* - four-digit (#RGBA)
* - eight-digit (#RRGGBBAA)
*/
function fromHex(hex: string): ${Color} {
if (/^#(?:[0-9a-fA-F]{3}){1}$/.test(hex)) {
// #RGB
return {
red: parseInt(hex.substring(1, 2) + hex.substring(1, 2), 16),
green: parseInt(hex.substring(2, 3) + hex.substring(2, 3), 16),
blue: parseInt(hex.substring(3, 4) + hex.substring(3, 4), 16),
};
} else if (/^#(?:[0-9a-fA-F]{3}){2}$/.test(hex)) {
// #RRGGBB
return {
red: parseInt(hex.substring(1, 3), 16),
green: parseInt(hex.substring(3, 5), 16),
blue: parseInt(hex.substring(5, 7), 16),
};
} else if (/^#(?:[0-9a-fA-F]{4}){1}$/.test(hex)) {
// #RGBA
return {
red: parseInt(hex.substring(1, 2) + hex.substring(1, 2), 16),
green: parseInt(hex.substring(2, 3) + hex.substring(2, 3), 16),
blue: parseInt(hex.substring(3, 4) + hex.substring(3, 4), 16),
alpha: {
value: parseInt(hex.substring(4, 5) + hex.substring(4, 5), 16) / 255,
}
};
} else if (/^#(?:[0-9a-fA-F]{4}){2}$/.test(hex)) {
// #RRGGBBAA
return {
red: parseInt(hex.substring(1, 3), 16),
green: parseInt(hex.substring(3, 5), 16),
blue: parseInt(hex.substring(5, 7), 16),
alpha: {
value: parseInt(hex.substring(7, 9), 16) / 255,
}
};
}
throw new Error('invalid hex color');
}
`,
];
}
['google.type.Date'](source, descriptor) {
const Date = this.imports.type(source, descriptor);
return [
`
/**
* Creates a javascript Date object from the message.
*
* If you do not provide the optional parameters for time,
* the current time is used.
*/
function toJsDate(message: ${Date}, hours?: number, minutes?: number, seconds?: number, ms?: number): globalThis.Date {
let now = new globalThis.Date();
return new globalThis.Date(
message.year,
message.month - 1,
message.day,
hours ?? now.getHours(),
minutes ?? now.getMinutes(),
seconds ?? now.getSeconds(),
ms ?? now.getMilliseconds(),
);
}
`, `
/**
* Creates a Date message from a javascript Date object.
*/
function fromJsDate(date: globalThis.Date): ${Date} {
return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
};
}
`,
];
}
['google.type.DateTime'](source, descriptor) {
const DateTime = this.imports.type(source, descriptor);
const PbLong = this.imports.name(source, 'PbLong', this.options.runtimeImportPath);
let longConvertMethod = 'toBigInt';
if (this.options.normalLongType === runtime_1.LongType.NUMBER)
longConvertMethod = 'toNumber';
else if (this.options.normalLongType === runtime_1.LongType.STRING)
longConvertMethod = 'toString';
const utcOffsetField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('utc_offset', this.options), timeOffsetField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('time_offset', this.options), timeZoneField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('time_zone', this.options);
return [
`
/**
* Creates \`DateTime\` for the current time.
*/
function now(): ${DateTime} {
return this.fromJsDate(new globalThis.Date());
}
`, `
/**
* Creates a javascript Date object from the message.
*
* If a the message has a UTC offset, the javascript Date is converted
* into your local time zone, because javascript Dates are always in the
* local time zone.
*
* If the message has an offset given as an IANA timezone id, an error is
* thrown, because javascript has no on-board support for IANA time zone
* ids.
*/
function toJsDate(message: ${DateTime}): globalThis.Date {
let dt = new globalThis.Date(
message.year,
message.month - 1,
message.day,
message.hours,
message.minutes,
message.seconds,
message.nanos / 1000,
),
to = message.${timeOffsetField};
if (to) {
if (to.oneofKind === "${timeZoneField}")
throw new globalThis.Error("IANA time zone not supported");
if (to.oneofKind === "${utcOffsetField}") {
let s = ${PbLong}.from(to.${utcOffsetField}.seconds).toNumber();
dt = new globalThis.Date(dt.getTime() - (s * 1000));
}
}
return dt;
}
`, `
/**
* Creates a Date message from a javascript Date object.
*
* Values are in local time and a proper UTF offset is provided.
*/
function fromJsDate(date: globalThis.Date): ${DateTime} {
return {
year: date.getFullYear(),
month: date.getMonth() + 1,
day: date.getDate(),
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
nanos: date.getMilliseconds() * 1000,
${timeOffsetField}: {
oneofKind: "${utcOffsetField}",
${utcOffsetField}: {
seconds: ${PbLong}.from(date.getTimezoneOffset() * 60).${longConvertMethod}(),
nanos: 0,
}
}
};
}
`,
];
}
['google.type.TimeOfDay'](source, descriptor) {
const TimeOfDay = this.imports.type(source, descriptor);
return [
`
/**
* Creates a TimeOfDay message from a javascript Date object.
*/
function fromJsDate(date: globalThis.Date): ${TimeOfDay} {
return {
hours: date.getHours(),
minutes: date.getMinutes(),
seconds: date.getSeconds(),
nanos: date.getMilliseconds() * 1000,
};
}
`,
];
}
}
exports.GoogleTypes = GoogleTypes;

View file

@ -0,0 +1,67 @@
import * as ts from "typescript";
import { DescriptorProto, DescriptorRegistry, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import * as rt from "@protobuf-ts/runtime";
import { LongType } from "@protobuf-ts/runtime";
import { CustomMethodGenerator } from "../code-gen/message-type-generator";
import { Interpreter } from "../interpreter";
/**
* Generates a "internalBinaryRead()" method for an `IMessageType`
*/
export declare class InternalBinaryRead implements CustomMethodGenerator {
private readonly registry;
private readonly imports;
private readonly interpreter;
private readonly options;
constructor(registry: DescriptorRegistry, imports: TypeScriptImports, interpreter: Interpreter, options: {
normalLongType: LongType;
oneofKindDiscriminator: string;
runtimeImportPath: string;
});
private readonly binaryReadMapEntryMethodName;
make(source: TypescriptFile, descriptor: DescriptorProto): ts.MethodDeclaration[];
makeMethod(source: TypescriptFile, descriptor: DescriptorProto, ...bodyStatements: readonly ts.Statement[]): ts.MethodDeclaration;
makeVariables(): ts.VariableStatement;
makeWhileSwitch(switchCases: ts.CaseClause[], defaultClause: ts.DefaultClause): ts.WhileStatement;
makeCaseClauses(source: TypescriptFile, descriptor: DescriptorProto): ts.CaseClause[];
makeDefaultClause(source: TypescriptFile): ts.DefaultClause;
map(field: rt.FieldInfo & {
kind: "map";
}, fieldPropertyAccess: ts.PropertyAccessExpression): ts.Statement[];
message(source: TypescriptFile, field: rt.FieldInfo & {
kind: "message";
repeat: undefined | rt.RepeatType.NO;
oneof: undefined;
}, fieldPropertyAccess: ts.PropertyAccessExpression): ts.Statement[];
messageOneof(source: TypescriptFile, field: rt.FieldInfo & {
kind: "message";
repeat: undefined | rt.RepeatType.NO;
oneof: string;
}): ts.Statement[];
messageRepeated(source: TypescriptFile, field: rt.FieldInfo & {
kind: "message";
repeat: rt.RepeatType.PACKED | rt.RepeatType.UNPACKED;
oneof: undefined;
}, fieldPropertyAccess: ts.PropertyAccessExpression): ts.Statement[];
scalar(field: rt.FieldInfo & {
kind: "scalar" | "enum";
oneof: undefined;
repeat: undefined | rt.RepeatType.NO;
}, fieldPropertyAccess: ts.PropertyAccessExpression): ts.Statement[];
scalarOneof(field: rt.FieldInfo & {
kind: "scalar" | "enum";
oneof: string;
repeat: undefined | rt.RepeatType.NO;
}): ts.Statement[];
scalarRepeated(source: TypescriptFile, field: rt.FieldInfo & {
kind: "scalar" | "enum";
oneof: undefined;
repeat: rt.RepeatType.PACKED | rt.RepeatType.UNPACKED;
}, fieldPropertyAccess: ts.PropertyAccessExpression): ts.Statement[];
makeMapEntryReadMethod(source: TypescriptFile, messageDescriptor: DescriptorProto, field: rt.FieldInfo & {
kind: "map";
}): ts.MethodDeclaration;
private createMapKeyDefaultValue;
private createMapValueDefaultValue;
private createScalarDefaultValue;
makeReaderCall(readerExpressionOrName: string | ts.Expression, type: rt.ScalarType, longType?: rt.LongType): ts.Expression;
}

View file

@ -0,0 +1,368 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InternalBinaryRead = void 0;
const ts = require("typescript");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const rt = require("@protobuf-ts/runtime");
const runtime_1 = require("@protobuf-ts/runtime");
const interpreter_1 = require("../interpreter");
/**
* Generates a "internalBinaryRead()" method for an `IMessageType`
*/
class InternalBinaryRead {
constructor(registry, imports, interpreter, options) {
this.registry = registry;
this.imports = imports;
this.interpreter = interpreter;
this.options = options;
this.binaryReadMapEntryMethodName = "binaryReadMap";
}
make(source, descriptor) {
const methods = [];
// if the message has no fields, we produce a much shorter body:
// return target ?? this.create();
if (descriptor.field.length === 0) {
return [this.makeMethod(source, descriptor, ts.createReturn(ts.createBinary(ts.createIdentifier("target"), ts.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("create")), undefined, []))))];
}
// internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ${messageInterfaceId}): ${messageInterfaceId} {
let internalBinaryRead = this.makeMethod(source, descriptor,
// let message = target ?? this.create(), end = reader.pos + length;
this.makeVariables(),
// while (reader.pos < end) {
// let [fieldNo, wireType] = reader.tag();
// switch (fieldNo) {
this.makeWhileSwitch(
// case ...:
this.makeCaseClauses(source, descriptor),
// default:
// ...
this.makeDefaultClause(source)),
// return message
ts.createReturn(ts.createIdentifier("message")));
methods.push(internalBinaryRead);
for (let fieldInfo of this.interpreter.getMessageType(descriptor).fields) {
if (fieldInfo.kind == "map") {
methods.push(this.makeMapEntryReadMethod(source, descriptor, fieldInfo));
}
}
return methods;
}
makeMethod(source, descriptor, ...bodyStatements) {
const MessageInterface = this.imports.type(source, descriptor), IBinaryReader = this.imports.name(source, 'IBinaryReader', this.options.runtimeImportPath, true), BinaryReadOptions = this.imports.name(source, 'BinaryReadOptions', this.options.runtimeImportPath, true);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier("internalBinaryRead"), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("reader"), undefined, ts.createTypeReferenceNode(IBinaryReader, undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("length"), undefined, ts.createKeywordTypeNode(ts.SyntaxKind.NumberKeyword), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(BinaryReadOptions, undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("target"), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createTypeReferenceNode(MessageInterface, undefined), undefined)
], ts.createTypeReferenceNode(MessageInterface, undefined), ts.createBlock(bodyStatements, true));
}
makeVariables() {
// let message = target ?? this.create(), end = reader.pos + length;
return ts.createVariableStatement(undefined, ts.createVariableDeclarationList([
ts.createVariableDeclaration(ts.createIdentifier("message"), undefined, ts.createBinary(ts.createIdentifier("target"), ts.createToken(ts.SyntaxKind.QuestionQuestionToken), ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("create")), undefined, []))),
ts.createVariableDeclaration(ts.createIdentifier("end"), undefined, ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("pos")), ts.createToken(ts.SyntaxKind.PlusToken), ts.createIdentifier("length")))
], ts.NodeFlags.Let));
}
makeWhileSwitch(switchCases, defaultClause) {
return ts.createWhile(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("pos")), ts.createToken(ts.SyntaxKind.LessThanToken), ts.createIdentifier("end")), ts.createBlock([
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createArrayBindingPattern([
ts.createBindingElement(undefined, undefined, ts.createIdentifier("fieldNo"), undefined),
ts.createBindingElement(undefined, undefined, ts.createIdentifier("wireType"), undefined)
]), undefined, ts.createCall(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("tag")), undefined, []))], ts.NodeFlags.Let)),
ts.createSwitch(ts.createIdentifier("fieldNo"), ts.createCaseBlock([
...switchCases,
defaultClause
]))
], true));
}
makeCaseClauses(source, descriptor) {
const interpreterType = this.interpreter.getMessageType(descriptor), clauses = [];
for (let fieldInfo of interpreterType.fields) {
let statements, fieldPropertyAccess = ts.createPropertyAccess(ts.createIdentifier("message"), fieldInfo.localName);
switch (fieldInfo.kind) {
case "scalar":
case "enum":
if (fieldInfo.repeat) {
statements = this.scalarRepeated(source, fieldInfo, fieldPropertyAccess);
}
else if (fieldInfo.oneof !== undefined) {
statements = this.scalarOneof(fieldInfo);
}
else {
statements = this.scalar(fieldInfo, fieldPropertyAccess);
}
break;
case "message":
if (fieldInfo.repeat) {
statements = this.messageRepeated(source, fieldInfo, fieldPropertyAccess);
}
else if (fieldInfo.oneof !== undefined) {
statements = this.messageOneof(source, fieldInfo);
}
else {
statements = this.message(source, fieldInfo, fieldPropertyAccess);
}
break;
case "map":
statements = this.map(fieldInfo, fieldPropertyAccess);
break;
}
// case /* double double_field */ 1:
let fieldDescriptor = descriptor.field.find(fd => fd.number === fieldInfo.no);
runtime_1.assert(fieldDescriptor !== undefined);
let fieldNumber = ts.createNumericLiteral(`${fieldInfo.no}`);
ts.addSyntheticLeadingComment(fieldNumber, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + this.registry.formatFieldDeclaration(fieldDescriptor).replace(/= \d+;$/, ''), false);
clauses.push(ts.createCaseClause(fieldNumber, [...statements, ts.createBreak(undefined)]));
}
return clauses;
}
makeDefaultClause(source) {
let UnknownFieldHandler = this.imports.name(source, 'UnknownFieldHandler', this.options.runtimeImportPath);
return ts.createDefaultClause([
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("u"), undefined, ts.createPropertyAccess(ts.createIdentifier("options"), ts.createIdentifier("readUnknownField")))], ts.NodeFlags.Let)),
ts.createIf(ts.createBinary(ts.createIdentifier("u"), ts.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.createStringLiteral("throw")), ts.createThrow(ts.createNew(ts.createPropertyAccess(ts.createIdentifier("globalThis"), ts.createIdentifier("Error")), undefined, [ts.createTemplateExpression(ts.createTemplateHead("Unknown field ", "Unknown field "), [
ts.createTemplateSpan(ts.createIdentifier("fieldNo"), ts.createTemplateMiddle(" (wire type ", " (wire type ")),
ts.createTemplateSpan(ts.createIdentifier("wireType"), ts.createTemplateMiddle(") for ", ") for ")),
ts.createTemplateSpan(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("typeName")), ts.createTemplateTail("", ""))
])])), undefined),
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("d"), undefined, ts.createCall(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("skip")), undefined, [ts.createIdentifier("wireType")]))], ts.NodeFlags.Let)),
ts.createIf(ts.createBinary(ts.createIdentifier("u"), ts.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.createFalse()), ts.createExpressionStatement(ts.createCall(ts.createParen(ts.createConditional(ts.createBinary(ts.createIdentifier("u"), ts.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.createTrue()), ts.createToken(ts.SyntaxKind.QuestionToken), ts.createPropertyAccess(ts.createIdentifier(UnknownFieldHandler), ts.createIdentifier("onRead")), ts.createToken(ts.SyntaxKind.ColonToken), ts.createIdentifier("u"))), undefined, [
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("typeName")),
ts.createIdentifier("message"),
ts.createIdentifier("fieldNo"),
ts.createIdentifier("wireType"),
ts.createIdentifier("d")
])), undefined)
]);
}
// message.int32StrField[reader.skip(0).skipBytes(1).int32()] = reader.skipBytes(1).string();
// message.msgField[reader.skip(0).skipBytes(1).int32()] = OtherMessage.internalBinaryRead(reader, reader.skipBytes(1).uint32(), options);
map(field, fieldPropertyAccess) {
return [ts.createExpressionStatement(ts.createCall(ts.createPropertyAccess(ts.createThis(), ts.createIdentifier(this.binaryReadMapEntryMethodName + field.no)), undefined, [
fieldPropertyAccess,
ts.createIdentifier("reader"),
ts.createIdentifier("options")
]))];
}
// message.field = OtherMessage.internalBinaryRead(reader, reader.uint32(), options, message.field);
message(source, field, fieldPropertyAccess) {
let messageDescriptor = this.registry.resolveTypeName(field.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
let handlerMergeCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryRead")), undefined, [
ts.createIdentifier("reader"),
this.makeReaderCall("reader", rt.ScalarType.UINT32),
ts.createIdentifier("options"),
fieldPropertyAccess
]);
return [ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("message"), field.localName), ts.createToken(ts.SyntaxKind.EqualsToken), handlerMergeCall))];
}
// message.result = {
// oneofKind: "msg",
// msg: OtherMessage.internalBinaryRead(reader, reader.uint32(), options, (message.result as any).msg)
// };
messageOneof(source, field) {
let messageDescriptor = this.registry.resolveTypeName(field.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
let handlerMergeCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryRead")), undefined, [
ts.createIdentifier("reader"),
this.makeReaderCall("reader", rt.ScalarType.UINT32),
ts.createIdentifier("options"),
ts.createPropertyAccess(ts.createParen(ts.createAsExpression(ts.createPropertyAccess(ts.createIdentifier("message"), field.oneof), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))), ts.createIdentifier(field.localName))
]);
return [ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("message"), field.oneof), ts.createToken(ts.SyntaxKind.EqualsToken), ts.createObjectLiteral([
// oneofKind: "msg",
ts.createPropertyAssignment(ts.createIdentifier(this.options.oneofKindDiscriminator), ts.createStringLiteral(field.localName)),
// msg: OtherMessage.internalBinaryRead(reader, reader.uint32(), options, (message.result as any).msg)
ts.createPropertyAssignment(field.localName, handlerMergeCall)
], true)))];
}
// message.field.push(OtherMessage.internalBinaryRead(reader, reader.uint32(), options));
messageRepeated(source, field, fieldPropertyAccess) {
let messageDescriptor = this.registry.resolveTypeName(field.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
let handlerMergeCall = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryRead")), undefined, [
ts.createIdentifier("reader"),
this.makeReaderCall("reader", rt.ScalarType.UINT32),
ts.createIdentifier("options"),
]);
return [ts.createExpressionStatement(ts.createCall(ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("push")), undefined, [handlerMergeCall]))];
}
// message.doubleField = reader.double();
scalar(field, fieldPropertyAccess) {
let type = field.kind == "enum" ? rt.ScalarType.INT32 : field.T;
let longType = field.kind == "enum" ? undefined : field.L;
let readerCall = this.makeReaderCall("reader", type, longType);
return [ts.createExpressionStatement(ts.createBinary(fieldPropertyAccess, ts.createToken(ts.SyntaxKind.EqualsToken), readerCall))];
}
// message.result = {
// oneofKind: "err",
// err: reader.string()
// };
scalarOneof(field) {
let type = field.kind == "enum" ? rt.ScalarType.INT32 : field.T;
let longType = field.kind == "enum" ? undefined : field.L;
return [ts.createExpressionStatement(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("message"), field.oneof), ts.createToken(ts.SyntaxKind.EqualsToken), ts.createObjectLiteral([
// oneofKind: "err",
ts.createPropertyAssignment(ts.createIdentifier(this.options.oneofKindDiscriminator), ts.createStringLiteral(field.localName)),
// err: reader.string()
ts.createPropertyAssignment(field.localName, this.makeReaderCall("reader", type, longType))
], true)))];
}
// if (wireType === WireType.LengthDelimited)
// for (const e = reader.int32() + reader.pos; reader.pos < e;)
// message.doubleField.push(reader.double());
// else
// message.doubleField.push(reader.double());
scalarRepeated(source, field, fieldPropertyAccess) {
let type = field.kind == "enum" ? rt.ScalarType.INT32 : field.T;
let longType = field.kind == "enum" ? undefined : field.L;
switch (type) {
case rt.ScalarType.STRING:
case rt.ScalarType.BYTES:
// never packed
// message.${fieldName}.push(reader.${readerMethod}());
return [ts.createExpressionStatement(ts.createCall(ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("push")), undefined, [this.makeReaderCall('reader', type, longType)]))];
default:
// maybe packed
return [
ts.createIf(ts.createBinary(ts.createIdentifier("wireType"), ts.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.createPropertyAccess(ts.createIdentifier(this.imports.name(source, 'WireType', this.options.runtimeImportPath)), 'LengthDelimited')
// ts.addSyntheticTrailingComment(
// ts.createNumericLiteral(WireType.LengthDelimited.toString()),
// ts.SyntaxKind.MultiLineCommentTrivia, " packed! ", false
// )
), ts.createFor(ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("e"), undefined, ts.createBinary(this.makeReaderCall("reader", rt.ScalarType.INT32), ts.createToken(ts.SyntaxKind.PlusToken), ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("pos"))))], ts.NodeFlags.Let), ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("pos")), ts.createToken(ts.SyntaxKind.LessThanToken), ts.createIdentifier("e")), undefined, ts.createExpressionStatement(ts.createCall(ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("push")), undefined, [this.makeReaderCall("reader", type, longType)]))), ts.createExpressionStatement(ts.createCall(ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("push")), undefined, [this.makeReaderCall("reader", type, longType)]))),
];
}
}
// binaryReadMapEntry<field no>(map: ExampleResponse["<field local name>"], reader: IBinaryReader, options: BinaryReadOptions): void
makeMapEntryReadMethod(source, messageDescriptor, field) {
let methodName = this.binaryReadMapEntryMethodName + field.no, fieldDescriptor = messageDescriptor.field.find(fd => fd.number === field.no), MessageInterface = this.imports.type(source, messageDescriptor), IBinaryReader = this.imports.name(source, 'IBinaryReader', this.options.runtimeImportPath, true), BinaryReadOptions = this.imports.name(source, 'BinaryReadOptions', this.options.runtimeImportPath, true), methodStatements = [];
runtime_1.assert(fieldDescriptor !== undefined);
// let len = reader.uint32(), end = reader.pos + len, key: keyof EnumMapMessage["int64EnuField"] | undefined, val: EnumMapMessage["int64EnuField"][any] | undefined;
methodStatements.push(ts.createVariableStatement(undefined, ts.createVariableDeclarationList([
ts.createVariableDeclaration(ts.createIdentifier("len"), undefined, ts.createCall(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("uint32")), undefined, [])),
ts.createVariableDeclaration(ts.createIdentifier("end"), undefined, ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("pos")), ts.createToken(ts.SyntaxKind.PlusToken), ts.createIdentifier("len"))),
ts.createVariableDeclaration(ts.createIdentifier("key"), ts.createUnionTypeNode([
ts.createTypeOperatorNode(ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(MessageInterface, undefined), ts.createLiteralTypeNode(ts.createStringLiteral(field.localName)))),
ts.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
]), undefined),
ts.createVariableDeclaration(ts.createIdentifier("val"), ts.createUnionTypeNode([
ts.createIndexedAccessTypeNode(ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(MessageInterface, undefined), ts.createLiteralTypeNode(ts.createStringLiteral(field.localName))), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)),
ts.createKeywordTypeNode(ts.SyntaxKind.UndefinedKeyword)
]), undefined)
], ts.NodeFlags.Let)));
// reader.string()
let readKeyExpression = this.makeReaderCall("reader", field.K, rt.LongType.STRING);
if (field.K === rt.ScalarType.BOOL) {
readKeyExpression = ts.createCall(ts.createPropertyAccess(readKeyExpression, ts.createIdentifier("toString")), undefined, []);
}
// reader.bytes()
let readValueExpression;
switch (field.V.kind) {
case "scalar":
readValueExpression = this.makeReaderCall("reader", field.V.T, field.V.L);
break;
case "enum":
readValueExpression = this.makeReaderCall("reader", rt.ScalarType.INT32);
break;
case "message":
let valueMessageDescriptor = this.registry.resolveTypeName(field.V.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(valueMessageDescriptor));
readValueExpression = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, valueMessageDescriptor)), ts.createIdentifier("internalBinaryRead")), undefined, [
ts.createIdentifier("reader"),
this.makeReaderCall("reader", rt.ScalarType.UINT32),
ts.createIdentifier("options")
]);
break;
}
// while (reader.pos < end) {
methodStatements.push(ts.createWhile(ts.createBinary(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("pos")), ts.createToken(ts.SyntaxKind.LessThanToken), ts.createIdentifier("end")), ts.createBlock([
// let [fieldNo, wireType] = reader.tag();
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createArrayBindingPattern([
ts.createBindingElement(undefined, undefined, ts.createIdentifier("fieldNo"), undefined),
ts.createBindingElement(undefined, undefined, ts.createIdentifier("wireType"), undefined)
]), undefined, ts.createCall(ts.createPropertyAccess(ts.createIdentifier("reader"), ts.createIdentifier("tag")), undefined, []))], ts.NodeFlags.Let)),
// switch (fieldNo) {
ts.createSwitch(ts.createIdentifier("fieldNo"), ts.createCaseBlock([
// case 1:
ts.createCaseClause(ts.createNumericLiteral("1"), [
// key = reader....
ts.createExpressionStatement(ts.createBinary(ts.createIdentifier("key"), ts.createToken(ts.SyntaxKind.EqualsToken), readKeyExpression)),
ts.createBreak(undefined)
]),
// case 2:
ts.createCaseClause(ts.createNumericLiteral("2"), [
// value = ...
ts.createExpressionStatement(ts.createBinary(ts.createIdentifier("val"), ts.createToken(ts.SyntaxKind.EqualsToken), readValueExpression)),
ts.createBreak(undefined)
]),
ts.createDefaultClause([ts.createThrow(ts.createNew(ts.createPropertyAccess(ts.createIdentifier("globalThis"), ts.createIdentifier("Error")), undefined, [ts.createStringLiteral("unknown map entry field for " + this.registry.formatQualifiedName(fieldDescriptor))]))])
]))
], true)));
// map[key ?? ""] = val ?? 0;
methodStatements.push(ts.createExpressionStatement(ts.createBinary(ts.createElementAccess(ts.createIdentifier("map"), ts.createBinary(ts.createIdentifier("key"), ts.createToken(ts.SyntaxKind.QuestionQuestionToken), this.createMapKeyDefaultValue(field.K))), ts.createToken(ts.SyntaxKind.EqualsToken), ts.createBinary(ts.createIdentifier("val"), ts.createToken(ts.SyntaxKind.QuestionQuestionToken), this.createMapValueDefaultValue(source, field.V)))));
// private binaryReadMapEntry<field no>(map: ExampleResponse["<field local name>"], reader: IBinaryReader, options: BinaryReadOptions): void
return ts.createMethod(undefined, [ts.createModifier(ts.SyntaxKind.PrivateKeyword)], undefined, ts.createIdentifier(methodName), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("map"), undefined, ts.createIndexedAccessTypeNode(ts.createTypeReferenceNode(ts.createIdentifier(MessageInterface), undefined), ts.createLiteralTypeNode(ts.createStringLiteral(field.localName))), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("reader"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(IBinaryReader), undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(ts.createIdentifier(BinaryReadOptions), undefined), undefined)
], ts.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword), ts.createBlock(methodStatements, true));
}
createMapKeyDefaultValue(type) {
let value = this.createScalarDefaultValue(type);
runtime_1.assert(value !== undefined);
// javascript object key must be number or string
// noinspection SuspiciousTypeOfGuard
if (typeof value !== "number") {
value = value.toString();
}
return plugin_framework_1.typescriptLiteralFromValue(value);
}
createMapValueDefaultValue(source, V) {
switch (V.kind) {
case "scalar":
return plugin_framework_1.typescriptLiteralFromValue(this.createScalarDefaultValue(V.T, V.L));
case "enum":
return plugin_framework_1.typescriptLiteralFromValue(this.createScalarDefaultValue(rt.ScalarType.INT32));
case "message":
let messageDescriptor = this.registry.resolveTypeName(V.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
let MessageInterface = this.imports.type(source, messageDescriptor);
return ts.createCall(ts.createPropertyAccess(ts.createIdentifier(MessageInterface), ts.createIdentifier("create")), undefined, []);
}
}
// noinspection JSMethodCanBeStatic
createScalarDefaultValue(type, longType) {
let syntheticType = new rt.MessageType("$synthetic.InternalBinaryRead", [{
no: 1, name: "syntheticField", localName: "syntheticField", kind: "scalar", T: type, L: longType
}]);
const value = syntheticType.create().syntheticField;
runtime_1.assert(value !== undefined);
return value;
}
// reader.int32().toString()
// reader.int32().toBigInt()
// reader.int32().toNumber()
makeReaderCall(readerExpressionOrName, type, longType) {
let readerMethodName = plugin_framework_1.StringFormat.formatScalarType(type);
let readerMethodProp = ts.createPropertyAccess(typeof readerExpressionOrName == "string" ? ts.createIdentifier(readerExpressionOrName) : readerExpressionOrName, ts.createIdentifier(readerMethodName));
let readerMethodCall = ts.createCall(readerMethodProp, undefined, []);
if (!interpreter_1.Interpreter.isLongValueType(type)) {
return readerMethodCall;
}
let convertMethodProp;
switch (longType !== null && longType !== void 0 ? longType : rt.LongType.STRING) {
case rt.LongType.STRING:
convertMethodProp = ts.createPropertyAccess(readerMethodCall, ts.createIdentifier('toString'));
break;
case rt.LongType.NUMBER:
convertMethodProp = ts.createPropertyAccess(readerMethodCall, ts.createIdentifier('toNumber'));
break;
case rt.LongType.BIGINT:
convertMethodProp = ts.createPropertyAccess(readerMethodCall, ts.createIdentifier('toBigInt'));
break;
}
return ts.createCall(convertMethodProp, undefined, []);
}
}
exports.InternalBinaryRead = InternalBinaryRead;

View file

@ -0,0 +1,63 @@
import * as ts from "typescript";
import { DescriptorProto, DescriptorRegistry, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import * as rt from "@protobuf-ts/runtime";
import { CustomMethodGenerator } from "../code-gen/message-type-generator";
import { Interpreter } from "../interpreter";
/**
* Generates the `internalBinaryWrite` method, which writes a message
* in binary format.
*
* Heads up: The generated code is only very marginally faster than
* the reflection-based one. The gain is less than 3%.
*
*/
export declare class InternalBinaryWrite implements CustomMethodGenerator {
private readonly registry;
private readonly imports;
private readonly interpreter;
private readonly options;
constructor(registry: DescriptorRegistry, imports: TypeScriptImports, interpreter: Interpreter, options: {
oneofKindDiscriminator: string;
runtimeImportPath: string;
});
make(source: TypescriptFile, descriptor: DescriptorProto): ts.MethodDeclaration[];
makeMethod(source: TypescriptFile, descriptor: DescriptorProto, bodyStatements: readonly ts.Statement[]): ts.MethodDeclaration;
makeUnknownFieldsHandler(source: TypescriptFile): ts.Statement[];
makeStatementsForEveryField(source: TypescriptFile, descriptor: DescriptorProto): ts.Statement[];
scalar(source: TypescriptFile, field: rt.FieldInfo & {
kind: "scalar" | "enum";
oneof: undefined;
repeat: undefined | rt.RepeatType.NO;
}, fieldPropertyAccess: ts.PropertyAccessExpression, fieldDeclarationComment: string): ts.Statement[];
scalarRepeated(source: TypescriptFile, field: rt.FieldInfo & {
kind: "scalar" | "enum";
oneof: undefined;
repeat: rt.RepeatType.PACKED | rt.RepeatType.UNPACKED;
}, fieldPropertyAccess: ts.PropertyAccessExpression, fieldDeclarationComment: string): ts.Statement[];
scalarOneof(source: TypescriptFile, field: rt.FieldInfo & {
kind: "scalar" | "enum";
oneof: string;
repeat: undefined | rt.RepeatType.NO;
}, fieldDeclarationComment: string): ts.Statement[];
message(source: TypescriptFile, field: rt.FieldInfo & {
kind: "message";
repeat: undefined | rt.RepeatType.NO;
oneof: undefined;
}, fieldPropertyAccess: ts.PropertyAccessExpression, fieldDeclarationComment: string): ts.Statement[];
messageRepeated(source: TypescriptFile, field: rt.FieldInfo & {
kind: "message";
repeat: rt.RepeatType.PACKED | rt.RepeatType.UNPACKED;
oneof: undefined;
}, fieldPropertyAccess: ts.PropertyAccessExpression, fieldDeclarationComment: string): ts.Statement[];
messageOneof(source: TypescriptFile, field: rt.FieldInfo & {
kind: "message";
repeat: undefined | rt.RepeatType.NO;
oneof: string;
}, fieldDeclarationComment: string): ts.Statement[];
map(source: TypescriptFile, field: rt.FieldInfo & {
kind: "map";
}, fieldPropertyAccess: ts.PropertyAccessExpression, fieldDeclarationComment: string): ts.Statement[];
protected makeWriterCall(writerExpressionOrName: string | ts.Expression, type: rt.ScalarType | 'fork' | 'join', argument?: ts.Expression): ts.Expression;
protected makeWriterTagCall(source: TypescriptFile, writerExpressionOrName: string | ts.Expression, fieldNo: number, wireType: rt.WireType): ts.Expression;
protected wireTypeForSingleScalar(scalarType: rt.ScalarType): rt.WireType;
}

View file

@ -0,0 +1,347 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.InternalBinaryWrite = void 0;
const ts = require("typescript");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const rt = require("@protobuf-ts/runtime");
const runtime_1 = require("@protobuf-ts/runtime");
/**
* Generates the `internalBinaryWrite` method, which writes a message
* in binary format.
*
* Heads up: The generated code is only very marginally faster than
* the reflection-based one. The gain is less than 3%.
*
*/
class InternalBinaryWrite {
constructor(registry, imports, interpreter, options) {
this.registry = registry;
this.imports = imports;
this.interpreter = interpreter;
this.options = options;
}
make(source, descriptor) {
// internalBinaryWrite(message: ScalarValuesMessage, writer: IBinaryWriter, options: BinaryWriteOptions): void {
let internalBinaryWrite = this.makeMethod(source, descriptor, [
...this.makeStatementsForEveryField(source, descriptor),
...this.makeUnknownFieldsHandler(source),
// return writer;
ts.createReturn(ts.createIdentifier("writer"))
]);
return [internalBinaryWrite];
}
makeMethod(source, descriptor, bodyStatements) {
const MessageInterface = this.imports.type(source, descriptor), IBinaryWriter = this.imports.name(source, 'IBinaryWriter', this.options.runtimeImportPath, true), BinaryWriteOptions = this.imports.name(source, 'BinaryWriteOptions', this.options.runtimeImportPath, true);
return ts.createMethod(undefined, undefined, undefined, ts.createIdentifier("internalBinaryWrite"), undefined, undefined, [
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("message"), undefined, ts.createTypeReferenceNode(MessageInterface, undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("writer"), undefined, ts.createTypeReferenceNode(IBinaryWriter, undefined), undefined),
ts.createParameter(undefined, undefined, undefined, ts.createIdentifier("options"), undefined, ts.createTypeReferenceNode(BinaryWriteOptions, undefined), undefined),
], ts.createTypeReferenceNode(IBinaryWriter, undefined), ts.createBlock(bodyStatements, true));
}
makeUnknownFieldsHandler(source) {
let UnknownFieldHandler = this.imports.name(source, 'UnknownFieldHandler', this.options.runtimeImportPath);
return [
ts.createVariableStatement(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("u"), undefined, ts.createPropertyAccess(ts.createIdentifier("options"), ts.createIdentifier("writeUnknownFields")))], ts.NodeFlags.Let)),
ts.createIf(ts.createBinary(ts.createIdentifier("u"), ts.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.createFalse()), ts.createExpressionStatement(ts.createCall(ts.createParen(ts.createConditional(ts.createBinary(ts.createIdentifier("u"), ts.createToken(ts.SyntaxKind.EqualsEqualsToken), ts.createTrue()), ts.createPropertyAccess(ts.createIdentifier(UnknownFieldHandler), ts.createIdentifier("onWrite")), ts.createIdentifier("u"))), undefined, [
ts.createPropertyAccess(ts.createThis(), ts.createIdentifier("typeName")),
ts.createIdentifier("message"),
ts.createIdentifier("writer")
])), undefined)
];
}
makeStatementsForEveryField(source, descriptor) {
const interpreterType = this.interpreter.getMessageType(descriptor), statements = [];
for (let fieldInfo of interpreterType.fields) {
let fieldDescriptor = descriptor.field.find(fd => fd.number === fieldInfo.no);
runtime_1.assert(fieldDescriptor !== undefined);
let fieldDeclarationComment = this.registry.formatFieldDeclaration(fieldDescriptor);
let fieldPropertyAccess = ts.createPropertyAccess(ts.createIdentifier("message"), fieldInfo.localName);
switch (fieldInfo.kind) {
case "scalar":
case "enum":
if (fieldInfo.repeat) {
statements.push(...this.scalarRepeated(source, fieldInfo, fieldPropertyAccess, fieldDeclarationComment));
}
else if (fieldInfo.oneof !== undefined) {
statements.push(...this.scalarOneof(source, fieldInfo, fieldDeclarationComment));
}
else {
statements.push(...this.scalar(source, fieldInfo, fieldPropertyAccess, fieldDeclarationComment));
}
break;
case "message":
if (fieldInfo.repeat) {
statements.push(...this.messageRepeated(source, fieldInfo, fieldPropertyAccess, fieldDeclarationComment));
}
else if (fieldInfo.oneof !== undefined) {
statements.push(...this.messageOneof(source, fieldInfo, fieldDeclarationComment));
}
else {
statements.push(...this.message(source, fieldInfo, fieldPropertyAccess, fieldDeclarationComment));
}
break;
case "map":
statements.push(...this.map(source, fieldInfo, fieldPropertyAccess, fieldDeclarationComment));
break;
}
}
return statements;
}
scalar(source, field, fieldPropertyAccess, fieldDeclarationComment) {
let type = field.kind == "enum" ? rt.ScalarType.INT32 : field.T;
// we only write scalar fields if they have a non-default value
// this is the condition:
let shouldWriteCondition;
if (field.T === rt.ScalarType.BYTES && field.opt) {
// message.bytes !== undefined
shouldWriteCondition = ts.createBinary(fieldPropertyAccess, ts.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), ts.createIdentifier("undefined"));
}
else if (field.T === rt.ScalarType.BYTES && !field.opt) {
// message.bytes.length
shouldWriteCondition = ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("length"));
}
else {
// message.field !== <default value>
// get a default value for the scalar field using the MessageType
let defaultValue = new rt.MessageType("$synthetic.InternalBinaryWrite", [field]).create()[field.localName];
let defaultValueExpression = plugin_framework_1.typescriptLiteralFromValue(defaultValue);
shouldWriteCondition = ts.createBinary(fieldPropertyAccess, ts.createToken(ts.SyntaxKind.ExclamationEqualsEqualsToken), defaultValueExpression);
}
// if ( <shouldWriteCondition> )
let statement = ts.createIf(shouldWriteCondition,
// writer.tag( <field no>, <wire type> ).string(message.stringField)
ts.createExpressionStatement(this.makeWriterCall(this.makeWriterTagCall(source, 'writer', field.no, this.wireTypeForSingleScalar(type)), type, fieldPropertyAccess)), undefined);
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
scalarRepeated(source, field, fieldPropertyAccess, fieldDeclarationComment) {
let statement;
let type = field.kind == "enum" ? rt.ScalarType.INT32 : field.T;
if (field.repeat === rt.RepeatType.PACKED) {
// if (message.int32Field.length) {
statement = ts.createIf(ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("length")), ts.createBlock([
// writer.tag(3, WireType.LengthDelimited).fork();
ts.createExpressionStatement(this.makeWriterCall(this.makeWriterTagCall(source, 'writer', field.no, rt.WireType.LengthDelimited), 'fork')),
// for (let i = 0; i < message.int32Field.length; i++)
ts.createFor(ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("i"), undefined, ts.createNumericLiteral("0"))], ts.NodeFlags.Let), ts.createBinary(ts.createIdentifier("i"), ts.createToken(ts.SyntaxKind.LessThanToken), ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("length"))), ts.createPostfix(ts.createIdentifier("i"), ts.SyntaxKind.PlusPlusToken),
// writer.int32(message.int32Field[i]);
ts.createExpressionStatement(this.makeWriterCall('writer', type, ts.createElementAccess(fieldPropertyAccess, ts.createIdentifier("i"))))),
// writer.join();
ts.createExpressionStatement(this.makeWriterCall('writer', 'join')),
], true), undefined);
}
else {
// never packed
// for (let i = 0; i < message.bytesField.length; i++)
statement = ts.createFor(ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("i"), undefined, ts.createNumericLiteral("0"))], ts.NodeFlags.Let), ts.createBinary(ts.createIdentifier("i"), ts.createToken(ts.SyntaxKind.LessThanToken), ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("length"))), ts.createPostfix(ts.createIdentifier("i"), ts.SyntaxKind.PlusPlusToken),
// writer.tag( <field number>, <wire type> ).bytes( message.bytesField[i] )
ts.createExpressionStatement(this.makeWriterCall(this.makeWriterTagCall(source, "writer", field.no, this.wireTypeForSingleScalar(type)), type, ts.createElementAccess(fieldPropertyAccess, ts.createIdentifier("i")))));
}
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
scalarOneof(source, field, fieldDeclarationComment) {
let type = field.kind == "enum" ? rt.ScalarType.INT32 : field.T;
let groupPropertyAccess = ts.createPropertyAccess(ts.createIdentifier("message"), ts.createIdentifier(field.oneof));
let statement = ts.createIf(
// if (message.result.oneofKind === 'value')
ts.createBinary(ts.createPropertyAccess(groupPropertyAccess, ts.createIdentifier(this.options.oneofKindDiscriminator)), ts.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.createStringLiteral(field.localName)),
// writer.tag( <field no>, <wire type> ).string(message.stringField)
ts.createExpressionStatement(this.makeWriterCall(this.makeWriterTagCall(source, 'writer', field.no, this.wireTypeForSingleScalar(type)), type, ts.createPropertyAccess(groupPropertyAccess, field.localName))), undefined);
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
message(source, field, fieldPropertyAccess, fieldDeclarationComment) {
let messageDescriptor = this.registry.resolveTypeName(field.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
// writer.tag(<field no>, WireType.LengthDelimited).fork();
let writeTagAndFork = this.makeWriterCall(this.makeWriterTagCall(source, 'writer', field.no, rt.WireType.LengthDelimited), 'fork');
// MessageFieldMessage_TestMessage.internalBinaryWrite(message.messageField, <writeTagAndFork>, options);
let binaryWrite = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryWrite")), undefined, [fieldPropertyAccess, writeTagAndFork, ts.createIdentifier("options")]);
// <...>.join()
let binaryWriteAndJoin = this.makeWriterCall(binaryWrite, 'join');
// if (message.messageField) {
let statement = ts.createIf(fieldPropertyAccess, ts.createExpressionStatement(binaryWriteAndJoin), undefined);
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
messageRepeated(source, field, fieldPropertyAccess, fieldDeclarationComment) {
let messageDescriptor = this.registry.resolveTypeName(field.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
// message.repeatedMessageField[i]
let fieldPropI = ts.createElementAccess(fieldPropertyAccess, ts.createIdentifier("i"));
// writer.tag(<field no>, WireType.LengthDelimited).fork();
let writeTagAndFork = this.makeWriterCall(this.makeWriterTagCall(source, 'writer', field.no, rt.WireType.LengthDelimited), 'fork');
// MessageFieldMessage_TestMessage.internalBinaryWrite(message.repeatedMessageField, <writeTagAndFork>, options);
let binaryWrite = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryWrite")), undefined, [fieldPropI, writeTagAndFork, ts.createIdentifier("options")]);
// <...>.join()
let binaryWriteAndJoin = this.makeWriterCall(binaryWrite, 'join');
// for (let i = 0; i < message.repeatedMessageField.length; i++) {
let statement = ts.createFor(ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("i"), undefined, ts.createNumericLiteral("0"))], ts.NodeFlags.Let), ts.createBinary(ts.createIdentifier("i"), ts.createToken(ts.SyntaxKind.LessThanToken), ts.createPropertyAccess(fieldPropertyAccess, ts.createIdentifier("length"))), ts.createPostfix(ts.createIdentifier("i"), ts.SyntaxKind.PlusPlusToken), ts.createExpressionStatement(binaryWriteAndJoin));
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
messageOneof(source, field, fieldDeclarationComment) {
let messageDescriptor = this.registry.resolveTypeName(field.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
// message.<oneof name>
let groupPropertyAccess = ts.createPropertyAccess(ts.createIdentifier("message"), ts.createIdentifier(field.oneof));
// writer.tag(<field no>, WireType.LengthDelimited).fork();
let writeTagAndFork = this.makeWriterCall(this.makeWriterTagCall(source, 'writer', field.no, rt.WireType.LengthDelimited), 'fork');
// MessageFieldMessage_TestMessage.internalBinaryWrite(message.<groupPropertyAccess>.<fieldLocalName>, <writeTagAndFork>, options);
let binaryWrite = ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryWrite")), undefined, [
ts.createPropertyAccess(groupPropertyAccess, field.localName),
writeTagAndFork,
ts.createIdentifier("options")
]);
// <...>.join()
let binaryWriteAndJoin = this.makeWriterCall(binaryWrite, 'join');
// if (message.objects.oneofKind === 'a') {
let statement = ts.createIf(ts.createBinary(ts.createPropertyAccess(groupPropertyAccess, ts.createIdentifier(this.options.oneofKindDiscriminator)), ts.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.createStringLiteral(field.localName)), ts.createExpressionStatement(binaryWriteAndJoin), undefined);
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
map(source, field, fieldPropertyAccess, fieldDeclarationComment) {
// all javascript property keys are strings, need to do some conversion for wire format
let mapEntryKeyRead;
let mapEntryValueRead = ts.createElementAccess(fieldPropertyAccess, ts.createIdentifier("k"));
switch (field.K) {
case rt.ScalarType.BOOL:
// parse bool for writer
mapEntryKeyRead = ts.createBinary(ts.createIdentifier("k"), ts.createToken(ts.SyntaxKind.EqualsEqualsEqualsToken), ts.createStringLiteral("true"));
break;
case rt.ScalarType.INT32:
case rt.ScalarType.SINT32:
case rt.ScalarType.UINT32:
case rt.ScalarType.FIXED32:
case rt.ScalarType.SFIXED32:
// parse int for writer
mapEntryKeyRead = ts.createCall(ts.createIdentifier("parseInt"), undefined, [ts.createIdentifier("k")]);
// convince compiler key works for index type
// message.int32KeyedMap[k as any]
// ^^^^^^^^^^
mapEntryValueRead = ts.createElementAccess(fieldPropertyAccess, ts.createAsExpression(ts.createIdentifier("k"), ts.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)));
break;
default:
// writer method accepts string for all other cases, no need to modify
mapEntryKeyRead = ts.createIdentifier("k");
break;
}
// loop body for every map entry. looks different for messages.
let forBody;
if (field.V.kind == "message") {
let messageDescriptor = this.registry.resolveTypeName(field.V.T().typeName);
runtime_1.assert(plugin_framework_1.DescriptorProto.is(messageDescriptor));
forBody = ts.createBlock([
// same as for scalar maps
ts.createExpressionStatement(this.makeWriterCall(
// this.makeWriterCall(
this.makeWriterTagCall(source, this.makeWriterCall(this.makeWriterTagCall(source, "writer", field.no, rt.WireType.LengthDelimited),
// .fork // start length delimited for the MapEntry
'fork'), 1, this.wireTypeForSingleScalar(field.K)),
// .string(message.strStrField[k]) // MapEntry key value
field.K, mapEntryKeyRead)),
//
ts.createExpressionStatement(this.makeWriterCall(this.makeWriterTagCall(source, 'writer', 2, rt.WireType.LengthDelimited),
// start length delimited for the message
'fork')),
// MessageMapMessage_MyItem.internalBinaryWrite(message.strMsgField[k], writer, options);
ts.createExpressionStatement(ts.createCall(ts.createPropertyAccess(ts.createIdentifier(this.imports.type(source, messageDescriptor)), ts.createIdentifier("internalBinaryWrite")), undefined, [
mapEntryValueRead,
ts.createIdentifier("writer"),
ts.createIdentifier("options")
])),
// end message and end map entry
ts.createExpressionStatement(this.makeWriterCall(this.makeWriterCall('writer', 'join'), 'join')),
], true);
}
else {
// handle enum as INT32
let mapEntryValueScalarType = field.V.kind == "enum" ? rt.ScalarType.INT32 : field.V.T;
// *rolleyes*
forBody = ts.createExpressionStatement(this.makeWriterCall(this.makeWriterCall(this.makeWriterTagCall(source, this.makeWriterCall(this.makeWriterTagCall(source, this.makeWriterCall(this.makeWriterTagCall(source, 'writer',
// tag for our field
field.no, rt.WireType.LengthDelimited),
// .fork // start length delimited for the MapEntry
'fork'),
// MapEntry key field tag
1, this.wireTypeForSingleScalar(field.K)),
// .string(message.strStrField[k]) // MapEntry key value
field.K, mapEntryKeyRead),
// MapEntry value field tag
2, this.wireTypeForSingleScalar(mapEntryValueScalarType)),
// .string(message.strStrField[k]) // MapEntry value value
mapEntryValueScalarType, mapEntryValueRead), 'join'));
}
// for (let k of Object.keys(message.strStrField))
let statement = ts.createForOf(undefined, ts.createVariableDeclarationList([ts.createVariableDeclaration(ts.createIdentifier("k"), undefined, undefined)], ts.NodeFlags.Let), ts.createCall(ts.createPropertyAccess(ts.createPropertyAccess(ts.createIdentifier("globalThis"), ts.createIdentifier("Object")), ts.createIdentifier("keys")), undefined, [fieldPropertyAccess]), forBody);
ts.addSyntheticLeadingComment(statement, ts.SyntaxKind.MultiLineCommentTrivia, ' ' + fieldDeclarationComment + ' ', true);
return [statement];
}
makeWriterCall(writerExpressionOrName, type, argument) {
let methodName = typeof type == "string" ? type : plugin_framework_1.StringFormat.formatScalarType(type);
let writerExpression = typeof writerExpressionOrName == "string" ? ts.createIdentifier(writerExpressionOrName) : writerExpressionOrName;
let methodProp = ts.createPropertyAccess(writerExpression, ts.createIdentifier(methodName));
return ts.createCall(methodProp, undefined, argument ? [argument] : undefined);
}
makeWriterTagCall(source, writerExpressionOrName, fieldNo, wireType) {
let writerExpression = typeof writerExpressionOrName == "string" ? ts.createIdentifier(writerExpressionOrName) : writerExpressionOrName;
let methodProp = ts.createPropertyAccess(writerExpression, ts.createIdentifier("tag"));
let wireTypeName;
switch (wireType) {
case rt.WireType.LengthDelimited:
wireTypeName = "LengthDelimited";
break;
case rt.WireType.Bit64:
wireTypeName = "Bit64";
break;
case rt.WireType.Bit32:
wireTypeName = "Bit32";
break;
case rt.WireType.Varint:
wireTypeName = "Varint";
break;
case rt.WireType.EndGroup:
wireTypeName = "EndGroup";
break;
case rt.WireType.StartGroup:
wireTypeName = "StartGroup";
break;
}
let wireTypeAccess = ts.createPropertyAccess(ts.createIdentifier(this.imports.name(source, 'WireType', this.options.runtimeImportPath)), wireTypeName);
return ts.createCall(methodProp, undefined, [
ts.createNumericLiteral(fieldNo.toString()),
wireTypeAccess
]);
}
wireTypeForSingleScalar(scalarType) {
let wireType;
switch (scalarType) {
case rt.ScalarType.BOOL:
case rt.ScalarType.INT32:
case rt.ScalarType.UINT32:
case rt.ScalarType.SINT32:
case rt.ScalarType.INT64:
case rt.ScalarType.UINT64:
case rt.ScalarType.SINT64:
wireType = rt.WireType.Varint;
break;
case rt.ScalarType.BYTES:
case rt.ScalarType.STRING:
wireType = rt.WireType.LengthDelimited;
break;
case rt.ScalarType.DOUBLE:
case rt.ScalarType.FIXED64:
case rt.ScalarType.SFIXED64:
wireType = rt.WireType.Bit64;
break;
case rt.ScalarType.FLOAT:
case rt.ScalarType.FIXED32:
case rt.ScalarType.SFIXED32:
wireType = rt.WireType.Bit32;
break;
}
return wireType;
}
}
exports.InternalBinaryWrite = InternalBinaryWrite;

View file

@ -0,0 +1,41 @@
import { DescriptorProto, ITypeNameLookup, TypescriptFile, TypeScriptImports } from "@protobuf-ts/plugin-framework";
import * as ts from "typescript";
import { LongType } from "@protobuf-ts/runtime";
import { CustomMethodGenerator } from "../code-gen/message-type-generator";
export declare class WellKnownTypes implements CustomMethodGenerator {
private readonly typeNameLookup;
private readonly imports;
private readonly options;
static readonly protoFilenames: string[];
constructor(typeNameLookup: ITypeNameLookup, imports: TypeScriptImports, options: {
normalLongType: LongType;
runtimeImportPath: string;
useProtoFieldName: boolean;
});
/**
* Create custom methods for the handlers of well known types.
*
* Well known types have a custom JSON representation and we
* also add some convenience methods, for example to convert a
* `google.protobuf.Timestamp` to a javascript Date.
*/
make(source: TypescriptFile, descriptor: DescriptorProto): ts.MethodDeclaration[];
['google.protobuf.Empty'](): void;
['google.protobuf.Any'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.Timestamp'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.Duration'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.FieldMask'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.Struct'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.Value'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.NullValue'](): void;
['google.protobuf.ListValue'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.BoolValue'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.StringValue'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.DoubleValue'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.FloatValue'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.Int32Value'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.UInt32Value'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.Int64Value'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.UInt64Value'](source: TypescriptFile, descriptor: DescriptorProto): string[];
['google.protobuf.BytesValue'](source: TypescriptFile, descriptor: DescriptorProto): string[];
}

View file

@ -0,0 +1,681 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WellKnownTypes = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const runtime_1 = require("@protobuf-ts/runtime");
const field_info_generator_1 = require("../code-gen/field-info-generator");
class WellKnownTypes {
constructor(typeNameLookup, imports, options) {
this.typeNameLookup = typeNameLookup;
this.imports = imports;
this.options = options;
}
/**
* Create custom methods for the handlers of well known types.
*
* Well known types have a custom JSON representation and we
* also add some convenience methods, for example to convert a
* `google.protobuf.Timestamp` to a javascript Date.
*/
make(source, descriptor) {
const typeName = this.typeNameLookup.makeTypeName(descriptor), fn = this[typeName];
if (fn) {
let r = fn.apply(this, [source, descriptor]);
if (typeof r == "string") {
return [plugin_framework_1.typescriptMethodFromText(r)];
}
if (Array.isArray(r)) {
return r.map(txt => plugin_framework_1.typescriptMethodFromText(txt));
}
}
return [];
}
['google.protobuf.Empty']( /*source: TypescriptFile, descriptor: DescriptorProto*/) {
// that´s ok, Empty already has the required JSON representation by default
}
['google.protobuf.Any'](source, descriptor) {
const Any = this.imports.type(source, descriptor), IMessageType = this.imports.name(source, 'IMessageType', this.options.runtimeImportPath, true), BinaryReadOptions = this.imports.name(source, 'BinaryReadOptions', this.options.runtimeImportPath, true), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), jsonWriteOptions = this.imports.name(source, 'jsonWriteOptions', this.options.runtimeImportPath), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath), isJsonObject = this.imports.name(source, 'isJsonObject', this.options.runtimeImportPath), typeUrlField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('type_url', this.options);
return [
`
/**
* Pack the message into a new \`Any\`.
*
* Uses 'type.googleapis.com/full.type.name' as the type URL.
*/
function pack<T extends object>(message: T, type: ${IMessageType}<T>): ${Any} {
return {
${typeUrlField}: this.typeNameToUrl(type.typeName),
value: type.toBinary(message),
};
}
`, `
/**
* Unpack the message from the \`Any\`.
*/
function unpack<T extends object>(any: ${Any}, type: ${IMessageType}<T>, options?: Partial<${BinaryReadOptions}>): T {
if (!this.contains(any, type))
throw new Error("Cannot unpack google.protobuf.Any with ${typeUrlField} '" + any.${typeUrlField} + "' as " + type.typeName + ".");
return type.fromBinary(any.value, options);
}
`, `
/**
* Does the given \`Any\` contain a packed message of the given type?
*/
function contains(any: ${Any}, type: ${IMessageType}<any> | string): boolean {
if (!any.${typeUrlField}.length)
return false;
let wants = typeof type == "string" ? type : type.typeName;
let has = this.typeUrlToName(any.${typeUrlField});
return wants === has;
}
`, `
/**
* Convert the message to canonical JSON value.
*
* You have to provide the \`typeRegistry\` option so that the
* packed message can be converted to JSON.
*
* The \`typeRegistry\` option is also required to read
* \`google.protobuf.Any\` from JSON format.
*/
function internalJsonWrite(any: ${Any}, options: ${JsonWriteOptions}): ${JsonValue} {
if (any.${typeUrlField} === "")
return {};
let typeName = this.typeUrlToName(any.${typeUrlField});
let opt = ${jsonWriteOptions}(options);
let type = opt.typeRegistry?.find(t => t.typeName === typeName);
if (!type)
throw new globalThis.Error("Unable to convert google.protobuf.Any with typeUrl '" + any.${typeUrlField} + "' to JSON. The specified type " + typeName + " is not available in the type registry.");
let value = type.fromBinary(any.value, {readUnknownField: false});
let json = type.internalJsonWrite(value, opt);
if (typeName.startsWith("google.protobuf.") || !${isJsonObject}(json))
json = {value: json};
json['@type'] = any.${typeUrlField};
return json;
}
`, `
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Any}): ${Any} {
if (!${isJsonObject}(json))
throw new globalThis.Error("Unable to parse google.protobuf.Any from JSON " + ${typeofJsonValue}(json) + ".");
if (typeof json['@type'] != "string" || json['@type'] == '')
return this.create();
let typeName = this.typeUrlToName(json["@type"]);
let type = options?.typeRegistry?.find(t => t.typeName == typeName);
if (!type)
throw new globalThis.Error("Unable to parse google.protobuf.Any from JSON. The specified type " + typeName + " is not available in the type registry.");
let value;
if (typeName.startsWith('google.protobuf.') && json.hasOwnProperty('value'))
value = type.fromJson(json['value'], options);
else {
let copy = Object.assign({}, json);
delete copy['@type'];
value = type.fromJson(copy, options);
}
if (target === undefined)
target = this.create();
target.${typeUrlField} = json['@type'];
target.value = type.toBinary(value);
return target;
}
`, `
function typeNameToUrl(name: string): string {
if (!name.length)
throw new Error('invalid type name: ' + name);
return "type.googleapis.com/" + name;
}
`, `
function typeUrlToName(url: string): string {
if (!url.length)
throw new Error('invalid type url: ' + url);
let slash = url.lastIndexOf("/");
let name = slash > 0 ? url.substring(slash + 1) : url;
if (!name.length)
throw new Error('invalid type url: ' + url);
return name;
}
`
];
}
['google.protobuf.Timestamp'](source, descriptor) {
const Timestamp = this.imports.type(source, descriptor), PbLong = this.imports.name(source, 'PbLong', this.options.runtimeImportPath), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath);
let longConvertMethod = 'toBigInt';
if (this.options.normalLongType === runtime_1.LongType.NUMBER)
longConvertMethod = 'toNumber';
else if (this.options.normalLongType === runtime_1.LongType.STRING)
longConvertMethod = 'toString';
return [
`
/**
* Creates a new \`Timestamp\` for the current time.
*/
function now(): ${Timestamp} {
const msg = this.create();
const ms = Date.now();
msg.seconds = ${PbLong}.from(Math.floor(ms / 1000)).${longConvertMethod}();
msg.nanos = (ms % 1000) * 1000000;
return msg;
}
`, `
/**
* Converts a \`Timestamp\` to a JavaScript Date.
*/
function toDate(message: ${Timestamp}): Date {
return new Date(${PbLong}.from(message.seconds).toNumber() * 1000 + Math.ceil(message.nanos / 1000000));
}
`, `
/**
* Converts a JavaScript Date to a \`Timestamp\`.
*/
function fromDate(date: Date): ${Timestamp} {
const msg = this.create();
const ms = date.getTime();
msg.seconds = PbLong.from(Math.floor(ms / 1000)).${longConvertMethod}();
msg.nanos = (ms % 1000) * 1000000;
return msg;
}
`, `
/**
* In JSON format, the \`Timestamp\` type is encoded as a string
* in the RFC 3339 format.
*/
function internalJsonWrite(message: ${Timestamp}, options: ${JsonWriteOptions}): ${JsonValue} {
let ms = PbLong.from(message.seconds).toNumber() * 1000;
if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z"))
throw new Error("Unable to encode Timestamp to JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.");
if (message.nanos < 0)
throw new Error("Unable to encode invalid Timestamp to JSON. Nanos must not be negative.");
let z = "Z";
if (message.nanos > 0) {
let nanosStr = (message.nanos + 1000000000).toString().substring(1);
if (nanosStr.substring(3) === "000000")
z = "." + nanosStr.substring(0, 3) + "Z";
else if (nanosStr.substring(6) === "000")
z = "." + nanosStr.substring(0, 6) + "Z";
else
z = "." + nanosStr + "Z";
}
return new Date(ms).toISOString().replace(".000Z", z)
}
`, `
/**
* In JSON format, the \`Timestamp\` type is encoded as a string
* in the RFC 3339 format.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Timestamp}): ${Timestamp} {
if (typeof json !== "string")
throw new Error("Unable to parse Timestamp from JSON " + ${typeofJsonValue}(json) + ".");
// RFC 3339 with "Z" (UTC) or offset like "+08:00" and optional fractions
// match[7] optional fractions, 3 to 9 digits
// match[8] offset like "-08:00", if undefined date is UTC
let matches = json.match(/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(?:Z|\\.([0-9]{3,9})Z|([+-][0-9][0-9]:[0-9][0-9]))$/);
if (!matches)
throw new Error("Unable to parse Timestamp from JSON. Invalid format.");
let ms = Date.parse(matches[1] + "-" + matches[2] + "-" + matches[3] + "T" + matches[4] + ":" + matches[5] + ":" + matches[6] + (matches[8] ? matches[8] : "Z"));
if (Number.isNaN(ms))
throw new Error("Unable to parse Timestamp from JSON. Invalid value.");
if (ms < Date.parse("0001-01-01T00:00:00Z") || ms > Date.parse("9999-12-31T23:59:59Z"))
throw new globalThis.Error("Unable to parse Timestamp from JSON. Must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.");
if (!target)
target = this.create();
target.seconds = PbLong.from(ms / 1000).${longConvertMethod}();
target.nanos = 0;
if (matches[7])
target.nanos = (parseInt("1" + matches[7] + "0".repeat(9 - matches[7].length)) - 1000000000);
return target;
}
`,
];
}
['google.protobuf.Duration'](source, descriptor) {
const Duration = this.imports.type(source, descriptor), PbLong = this.imports.name(source, 'PbLong', this.options.runtimeImportPath), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath);
let longConvertMethod = 'toBigInt';
if (this.options.normalLongType === runtime_1.LongType.NUMBER)
longConvertMethod = 'toNumber';
else if (this.options.normalLongType === runtime_1.LongType.STRING)
longConvertMethod = 'toString';
return [
`
/**
* Encode \`Duration\` to JSON string like "3.000001s".
*/
function internalJsonWrite(message: ${Duration}, options: ${JsonWriteOptions}): ${JsonValue} {
let s = ${PbLong}.from(message.seconds).toNumber();
if (s > 315576000000 || s < -315576000000)
throw new Error("Duration value out of range.");
let text = message.seconds.toString();
if (s === 0 && message.nanos < 0)
text = "-" + text;
if (message.nanos !== 0) {
let nanosStr = Math.abs(message.nanos).toString();
nanosStr = "0".repeat(9 - nanosStr.length) + nanosStr;
if (nanosStr.substring(3) === "000000")
nanosStr = nanosStr.substring(0, 3);
else if (nanosStr.substring(6) === "000")
nanosStr = nanosStr.substring(0, 6);
text += "." + nanosStr;
}
return text + "s";
}
`, `
/**
* Decode \`Duration\` from JSON string like "3.000001s"
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Duration}): ${Duration} {
if (typeof json !== "string")
throw new Error("Unable to parse Duration from JSON " + ${typeofJsonValue}(json) + ". Expected string.");
let match = json.match(/^(-?)([0-9]+)(?:\\.([0-9]+))?s/);
if (match === null)
throw new Error("Unable to parse Duration from JSON string. Invalid format.");
if (!target)
target = this.create();
let [, sign, secs, nanos] = match;
let longSeconds = ${PbLong}.from(sign + secs);
if (longSeconds.toNumber() > 315576000000 || longSeconds.toNumber() < -315576000000)
throw new Error("Unable to parse Duration from JSON string. Value out of range.");
target.seconds = longSeconds.${longConvertMethod}();
if (typeof nanos == "string") {
let nanosStr = sign + nanos + "0".repeat(9 - nanos.length);
target.nanos = parseInt(nanosStr);
}
return target;
}
`,
];
}
['google.protobuf.FieldMask'](source, descriptor) {
const FieldMask = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), lowerCamelCase = this.imports.name(source, 'lowerCamelCase', this.options.runtimeImportPath), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON object.
*/
function internalJsonWrite(message: ${FieldMask}, options: ${JsonWriteOptions}): ${JsonValue} {
const invalidFieldMaskJsonRegex = /[A-Z]|(_([.0-9_]|$))/g;
return message.paths.map(p => {
if (invalidFieldMaskJsonRegex.test(p))
throw new Error("Unable to encode FieldMask to JSON. lowerCamelCase of path name \\""+p+"\\" is irreversible.");
return ${lowerCamelCase}(p);
}).join(",");
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON object.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${FieldMask}): ${FieldMask} {
if (typeof json !== "string")
throw new Error("Unable to parse FieldMask from JSON " + ${typeofJsonValue}(json) + ". Expected string.");
if (!target)
target = this.create();
if (json === "")
return target;
let camelToSnake = (str: string) => {
if (str.includes('_'))
throw new Error("Unable to parse FieldMask from JSON. Path names must be lowerCamelCase.");
let sc = str.replace(/[A-Z]/g, letter => "_" + letter.toLowerCase());
return sc;
};
target.paths = json.split(",").map(camelToSnake);
return target;
}
`,
];
}
['google.protobuf.Struct'](source, descriptor) {
const Struct = this.imports.type(source, descriptor), JsonObject = this.imports.name(source, 'JsonObject', this.options.runtimeImportPath, true), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath), isJsonObject = this.imports.name(source, 'isJsonObject', this.options.runtimeImportPath);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON object.
*/
function internalJsonWrite(message: ${Struct}, options: ${JsonWriteOptions}): ${JsonValue} {
let json: ${JsonObject} = {};
for (let [k, v] of Object.entries(message.fields)) {
json[k] = Value.toJson(v);
}
return json;
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON object.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Struct}): ${Struct} {
if (!${isJsonObject}(json))
throw new globalThis.Error("Unable to parse message " + this.typeName + " from JSON " + ${typeofJsonValue}(json) + ".");
if (!target)
target = this.create();
for (let [k, v] of globalThis.Object.entries(json)) {
target.fields[k] = Value.fromJson(v);
}
return target;
}
`,
];
}
['google.protobuf.Value'](source, descriptor) {
const Value = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath), nullValueField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('null_value', this.options), boolValueField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('bool_value', this.options), numberValueField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('number_value', this.options), stringValueField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('string_value', this.options), listValueField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('list_value', this.options), structValueField = field_info_generator_1.FieldInfoGenerator.createTypescriptLocalName('struct_value', this.options);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON value.
*/
function internalJsonWrite(message: ${Value}, options: ${JsonWriteOptions}): ${JsonValue} {
if (message.kind.oneofKind === undefined) throw new globalThis.Error();
switch (message.kind.oneofKind) {
case undefined:
throw new globalThis.Error();
case "${boolValueField}":
return message.kind.${boolValueField};
case "${nullValueField}":
return null;
case "${numberValueField}":
let numberValue = message.kind.${numberValueField};
if (typeof numberValue == "number" && !Number.isFinite(numberValue)) throw new globalThis.Error();
return numberValue;
case "${stringValueField}":
return message.kind.${stringValueField};
case "${listValueField}":
let listValueField = this.fields.find(f => f.no === 6);
if (listValueField?.kind !== 'message') throw new globalThis.Error();
return listValueField.T().toJson(message.kind.${listValueField});
case "${structValueField}":
let structValueField = this.fields.find(f => f.no === 5);
if (structValueField?.kind !== 'message') throw new globalThis.Error();
return structValueField.T().toJson(message.kind.${structValueField});
}
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON value.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Value}): ${Value} {
if (!target)
target = this.create();
switch (typeof json) {
case "number":
target.kind = {oneofKind: "${numberValueField}", ${numberValueField}: json};
break;
case "string":
target.kind = {oneofKind: "${stringValueField}", ${stringValueField}: json};
break;
case "boolean":
target.kind = {oneofKind: "${boolValueField}", ${boolValueField}: json};
break;
case "object":
if (json === null) {
target.kind = {oneofKind: "${nullValueField}", ${nullValueField}: NullValue.NULL_VALUE};
} else if (globalThis.Array.isArray(json)) {
target.kind = {oneofKind: "${listValueField}", ${listValueField}: ListValue.fromJson(json)};
} else {
target.kind = {oneofKind: "${structValueField}", ${structValueField}: Struct.fromJson(json)};
}
break;
default:
throw new globalThis.Error('Unable to parse ' + this.typeName + ' from JSON ' + ${typeofJsonValue}(json));
}
return target;
}
`,
];
}
['google.protobuf.NullValue']( /*source: TypescriptFile, descriptor: DescriptorProto*/) {
// that´s ok, NullValue is actually an enum, and special JSON representation is handled by the reflection json reader
}
['google.protobuf.ListValue'](source, descriptor) {
const ListValue = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), typeofJsonValue = this.imports.name(source, 'typeofJsonValue', this.options.runtimeImportPath);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON array.
*/
function internalJsonWrite(message: ${ListValue}, options: ${JsonWriteOptions}): ${JsonValue} {
return message.values.map(v => Value.toJson(v));
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON array.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${ListValue}): ${ListValue} {
if (! globalThis.Array.isArray(json)) throw new globalThis.Error('Unable to parse ' + this.typeName + ' from JSON ' + ${typeofJsonValue}(json));
if (!target)
target = this.create();
let values = json.map(v => Value.fromJson(v));
target.values.push(...values);
return target;
}
`,
];
}
['google.protobuf.BoolValue'](source, descriptor) {
const BoolValue = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON bool.
*/
function internalJsonWrite(message: ${BoolValue}, options: ${JsonWriteOptions}): ${JsonValue} {
return message.value;
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON bool.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${BoolValue}): ${BoolValue} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.BOOL}, undefined, "value") as boolean;
return target;
}
`,
];
}
['google.protobuf.StringValue'](source, descriptor) {
const StringValue = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON string.
*/
function internalJsonWrite(message: ${StringValue}, options: ${JsonWriteOptions}): ${JsonValue} {
return message.value;
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON string.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${StringValue}): ${StringValue} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.STRING}, undefined, "value") as string;
return target;
}
`,
];
}
['google.protobuf.DoubleValue'](source, descriptor) {
const DoubleValue = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON number.
*/
function internalJsonWrite(message: ${DoubleValue}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${plugin_framework_1.FieldDescriptorProto_Type.FLOAT}, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON number.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${DoubleValue}): ${DoubleValue} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.DOUBLE}, undefined, "value") as number;
return target;
}
`,
];
}
['google.protobuf.FloatValue'](source, descriptor) {
const FloatValue = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON number.
*/
function internalJsonWrite(message: ${FloatValue}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${plugin_framework_1.FieldDescriptorProto_Type.DOUBLE}, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON number.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${FloatValue}): ${FloatValue} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.DOUBLE}, undefined, "value") as number;
return target;
}
`,
];
}
['google.protobuf.Int32Value'](source, descriptor) {
const Int32Value = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON string.
*/
function internalJsonWrite(message: ${Int32Value}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${plugin_framework_1.FieldDescriptorProto_Type.INT32}, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON string.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Int32Value}): ${Int32Value} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.INT32}, undefined, "value") as number;
return target;
}
`,
];
}
['google.protobuf.UInt32Value'](source, descriptor) {
const UInt32Value = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON string.
*/
function internalJsonWrite(message: ${UInt32Value}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${plugin_framework_1.FieldDescriptorProto_Type.UINT32}, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON string.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${UInt32Value}): ${UInt32Value} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.UINT32}, undefined, "value") as number;
return target;
}
`,
];
}
['google.protobuf.Int64Value'](source, descriptor) {
const Int64Value = this.imports.type(source, descriptor), iLongType = this.imports.name(source, 'LongType', this.options.runtimeImportPath), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), ScalarType = this.imports.name(source, 'ScalarType', this.options.runtimeImportPath);
let longTypeEnumValue = 'BIGINT';
if (this.options.normalLongType === runtime_1.LongType.NUMBER)
longTypeEnumValue = 'NUMBER';
else if (this.options.normalLongType === runtime_1.LongType.STRING)
longTypeEnumValue = 'STRING';
return [
`
/**
* Encode \`${descriptor.name}\` to JSON string.
*/
function internalJsonWrite(message: ${Int64Value}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${ScalarType}.INT64, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON string.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${Int64Value}): ${Int64Value} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${ScalarType}.INT64, ${iLongType}.${longTypeEnumValue}, "value") as any;
return target;
}
`,
];
}
['google.protobuf.UInt64Value'](source, descriptor) {
const UInt64Value = this.imports.type(source, descriptor), iLongType = this.imports.name(source, 'LongType', this.options.runtimeImportPath), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true), ScalarType = this.imports.name(source, 'ScalarType', this.options.runtimeImportPath);
let longTypeEnumValue = 'BIGINT';
if (this.options.normalLongType === runtime_1.LongType.NUMBER)
longTypeEnumValue = 'NUMBER';
else if (this.options.normalLongType === runtime_1.LongType.STRING)
longTypeEnumValue = 'STRING';
return [
`
/**
* Encode \`${descriptor.name}\` to JSON string.
*/
function internalJsonWrite(message: ${UInt64Value}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${ScalarType}.UINT64, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON string.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${UInt64Value}): ${UInt64Value} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${ScalarType}.UINT64, ${iLongType}.${longTypeEnumValue}, "value") as any;
return target;
}
`,
];
}
['google.protobuf.BytesValue'](source, descriptor) {
const BytesValue = this.imports.type(source, descriptor), JsonWriteOptions = this.imports.name(source, 'JsonWriteOptions', this.options.runtimeImportPath, true), JsonReadOptions = this.imports.name(source, 'JsonReadOptions', this.options.runtimeImportPath, true), JsonValue = this.imports.name(source, 'JsonValue', this.options.runtimeImportPath, true);
return [
`
/**
* Encode \`${descriptor.name}\` to JSON string.
*/
function internalJsonWrite(message: ${BytesValue}, options: ${JsonWriteOptions}): ${JsonValue} {
return this.refJsonWriter.scalar(${plugin_framework_1.FieldDescriptorProto_Type.BYTES}, message.value, "value", false, true);
}
`, `
/**
* Decode \`${descriptor.name}\` from JSON string.
*/
function internalJsonRead(json: ${JsonValue}, options: ${JsonReadOptions}, target?: ${BytesValue}): ${BytesValue} {
if (!target)
target = this.create();
target.value = this.refJsonReader.scalar(json, ${plugin_framework_1.FieldDescriptorProto_Type.BYTES}, undefined, "value") as Uint8Array;
return target;
}
`,
];
}
}
exports.WellKnownTypes = WellKnownTypes;
WellKnownTypes.protoFilenames = [
"google/protobuf/any.proto",
"google/protobuf/api.proto",
"google/protobuf/descriptor.proto",
"google/protobuf/duration.proto",
"google/protobuf/empty.proto",
"google/protobuf/field_mask.proto",
"google/protobuf/source_context.proto",
"google/protobuf/struct.proto",
"google/protobuf/timestamp.proto",
"google/protobuf/type.proto",
"google/protobuf/wrappers.proto",
"google/protobuf/compiler/plugin.proto",
"google/protobuf/any.proto",
];

View file

@ -0,0 +1,159 @@
/**
* Custom file options interpreted by @protobuf-ts/plugin
*/
import * as rt from "@protobuf-ts/runtime";
import { FileDescriptorProto, FileOptions_OptimizeMode as OptimizeMode, IStringFormat, ServiceDescriptorProto } from "@protobuf-ts/plugin-framework";
import { Interpreter } from "./interpreter";
import * as ts from "typescript";
/**
* Custom file options interpreted by @protobuf-ts/plugin
* The extensions are declared in protobuf-ts.proto
*/
export interface OurFileOptions {
/**
* Exclude field or method options from being emitted in reflection data.
*
* For example, to stop the data of the "google.api.http" method option
* from being exported in the reflection information, set the following
* file option:
*
* ```proto
* option (ts.exclude_options) = "google.api.http";
* ```
*
* The option can be set multiple times.
* `*` serves as a wildcard and will greedily match anything.
*/
readonly ["ts.exclude_options"]: readonly string[];
}
/**
* Custom service options interpreted by @protobuf-ts/plugin
*/
export interface OurServiceOptions {
/**
* Generate a client for this service with this style.
* Can be set multiple times to generate several styles.
*/
readonly ["ts.client"]: ClientStyle[];
/**
* Generate a server for this service with this style.
* Can be set multiple times to generate several styles.
*/
readonly ["ts.server"]: ServerStyle[];
}
/**
* Read the custom file options declared in protobuf-ts.proto
*/
export declare function readOurFileOptions(file: FileDescriptorProto): OurFileOptions;
/**
* Read the custom service options declared in protobuf-ts.proto
*/
export declare function readOurServiceOptions(service: ServiceDescriptorProto): OurServiceOptions;
/**
* The available client styles from @protobuf-ts/plugin
* The extensions are declared in protobuf-ts.proto
*/
export declare enum ClientStyle {
/**
* Do not emit a client for this service.
*/
NO_CLIENT = 0,
/**
* Use the call implementations of @protobuf-ts/runtime-rpc.
* This is the default behaviour.
*/
GENERIC_CLIENT = 1,
/**
* Generate a client using @grpc/grpc-js (major version 1).
*/
GRPC1_CLIENT = 4
}
/**
* The available server styles from @protobuf-ts/plugin
* The extensions are declared in protobuf-ts.proto
*/
export declare enum ServerStyle {
/**
* Do not emit a server for this service.
* This is the default behaviour.
*/
NO_SERVER = 0,
/**
* Generate a generic server interface.
* Adapters be used to serve the service, for example @protobuf-ts/grpc-backend
* for gRPC.
*/
GENERIC_SERVER = 1,
/**
* Generate a server for @grpc/grpc-js (major version 1).
*/
GRPC1_SERVER = 2
}
/**
* Internal settings for the file generation.
*/
export interface InternalOptions {
readonly generateDependencies: boolean;
readonly pluginCredit?: string;
readonly normalLongType: rt.LongType;
readonly normalOptimizeMode: OptimizeMode;
readonly forcedOptimizeMode: OptimizeMode | undefined;
readonly normalServerStyle: ServerStyle;
readonly forcedServerStyle: ServerStyle | undefined;
readonly normalClientStyle: ClientStyle;
readonly forcedClientStyle: ClientStyle | undefined;
readonly synthesizeEnumZeroValue: string | false;
readonly oneofKindDiscriminator: string;
readonly runtimeRpcImportPath: string;
readonly runtimeImportPath: string;
readonly forceExcludeAllOptions: boolean;
readonly keepEnumPrefix: boolean;
readonly useProtoFieldName: boolean;
readonly tsNoCheck: boolean;
readonly esLintDisable: boolean;
readonly transpileTarget: ts.ScriptTarget | undefined;
readonly transpileModule: ts.ModuleKind;
readonly forceDisableServices: boolean;
readonly addPbSuffix: boolean;
}
export declare function makeInternalOptions(params?: {
generate_dependencies: boolean;
long_type_string: boolean;
long_type_number: boolean;
force_exclude_all_options: boolean;
keep_enum_prefix: boolean;
use_proto_field_name: boolean;
ts_nocheck: boolean;
eslint_disable: boolean;
force_optimize_code_size: boolean;
force_optimize_speed: boolean;
optimize_code_size: boolean;
force_server_none: boolean;
server_none: boolean;
server_generic: boolean;
server_grpc1: boolean;
force_client_none: boolean;
client_generic: boolean;
client_none: boolean;
client_grpc1: boolean;
add_pb_suffix: boolean;
force_disable_services: boolean;
output_typescript: boolean;
output_javascript: boolean;
output_javascript_es2015: boolean;
output_javascript_es2016: boolean;
output_javascript_es2017: boolean;
output_javascript_es2018: boolean;
output_javascript_es2019: boolean;
output_javascript_es2020: boolean;
output_legacy_commonjs: boolean;
}, pluginCredit?: string): InternalOptions;
export declare class OptionResolver {
private readonly interpreter;
private readonly stringFormat;
private readonly options;
constructor(interpreter: Interpreter, stringFormat: IStringFormat, options: InternalOptions);
getOptimizeMode(file: FileDescriptorProto): OptimizeMode;
getClientStyles(descriptor: ServiceDescriptorProto): ClientStyle[];
getServerStyles(descriptor: ServiceDescriptorProto): ServerStyle[];
}

View file

@ -0,0 +1,276 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OptionResolver = exports.makeInternalOptions = exports.ServerStyle = exports.ClientStyle = exports.readOurServiceOptions = exports.readOurFileOptions = void 0;
/**
* Custom file options interpreted by @protobuf-ts/plugin
*/
const rt = require("@protobuf-ts/runtime");
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const ts = require("typescript");
/**
* Read the custom file options declared in protobuf-ts.proto
*/
function readOurFileOptions(file) {
return read(file.options, emptyFileOptions, OurFileOptions);
}
exports.readOurFileOptions = readOurFileOptions;
/**
* Read the custom service options declared in protobuf-ts.proto
*/
function readOurServiceOptions(service) {
return read(service.options, emptyServiceOptions, OurServiceOptions);
}
exports.readOurServiceOptions = readOurServiceOptions;
function read(options, defaults, type) {
if (!options) {
return defaults;
}
let unknownFields = rt.UnknownFieldHandler.list(options);
if (!unknownFields.length) {
return defaults;
}
// concat all unknown field data
let unknownWriter = new rt.BinaryWriter();
for (let { no, wireType, data } of unknownFields)
unknownWriter.tag(no, wireType).raw(data);
let unknownBytes = unknownWriter.finish();
return type.fromBinary(unknownBytes, { readUnknownField: false });
}
const OurFileOptions = new rt.MessageType("$synthetic.OurFileOptions", [
{
no: 777701,
name: "ts.exclude_options", localName: "ts.exclude_options", jsonName: "ts.exclude_options",
kind: "scalar",
T: rt.ScalarType.STRING,
repeat: rt.RepeatType.PACKED
}
]);
const OurServiceOptions = new rt.MessageType("$synthetic.OurServiceOptions", [
{
no: 777701,
name: "ts.client", localName: "ts.client", jsonName: "ts.client",
kind: "enum",
T: () => ["ts.ClientStyle", ClientStyle],
repeat: rt.RepeatType.UNPACKED,
},
{
no: 777702,
name: "ts.server", localName: "ts.server", jsonName: "ts.server",
kind: "enum",
T: () => ["ts.ServerStyle", ServerStyle],
repeat: rt.RepeatType.UNPACKED,
}
]);
/**
* The available client styles from @protobuf-ts/plugin
* The extensions are declared in protobuf-ts.proto
*/
var ClientStyle;
(function (ClientStyle) {
/**
* Do not emit a client for this service.
*/
ClientStyle[ClientStyle["NO_CLIENT"] = 0] = "NO_CLIENT";
/**
* Use the call implementations of @protobuf-ts/runtime-rpc.
* This is the default behaviour.
*/
ClientStyle[ClientStyle["GENERIC_CLIENT"] = 1] = "GENERIC_CLIENT";
/**
* Generate a client using @grpc/grpc-js (major version 1).
*/
ClientStyle[ClientStyle["GRPC1_CLIENT"] = 4] = "GRPC1_CLIENT";
})(ClientStyle = exports.ClientStyle || (exports.ClientStyle = {}));
/**
* The available server styles from @protobuf-ts/plugin
* The extensions are declared in protobuf-ts.proto
*/
var ServerStyle;
(function (ServerStyle) {
/**
* Do not emit a server for this service.
* This is the default behaviour.
*/
ServerStyle[ServerStyle["NO_SERVER"] = 0] = "NO_SERVER";
/**
* Generate a generic server interface.
* Adapters be used to serve the service, for example @protobuf-ts/grpc-backend
* for gRPC.
*/
ServerStyle[ServerStyle["GENERIC_SERVER"] = 1] = "GENERIC_SERVER";
/**
* Generate a server for @grpc/grpc-js (major version 1).
*/
ServerStyle[ServerStyle["GRPC1_SERVER"] = 2] = "GRPC1_SERVER";
})(ServerStyle = exports.ServerStyle || (exports.ServerStyle = {}));
const emptyFileOptions = OurFileOptions.create();
const emptyServiceOptions = OurServiceOptions.create();
function makeInternalOptions(params, pluginCredit) {
const o = Object.assign({}, {
generateDependencies: false,
normalLongType: rt.LongType.BIGINT,
normalOptimizeMode: plugin_framework_1.FileOptions_OptimizeMode.SPEED,
forcedOptimizeMode: undefined,
normalClientStyle: ClientStyle.GENERIC_CLIENT,
forcedClientStyle: undefined,
normalServerStyle: ServerStyle.NO_SERVER,
forcedServerStyle: undefined,
synthesizeEnumZeroValue: 'UNSPECIFIED$',
oneofKindDiscriminator: 'oneofKind',
runtimeRpcImportPath: '@protobuf-ts/runtime-rpc',
runtimeImportPath: '@protobuf-ts/runtime',
forceExcludeAllOptions: false,
keepEnumPrefix: false,
useProtoFieldName: false,
tsNoCheck: false,
esLintDisable: false,
transpileTarget: undefined,
transpileModule: ts.ModuleKind.ES2015,
forceDisableServices: false,
addPbSuffix: false,
});
if (pluginCredit) {
o.pluginCredit = pluginCredit;
}
if (params === null || params === void 0 ? void 0 : params.generate_dependencies) {
o.generateDependencies = true;
}
if (params === null || params === void 0 ? void 0 : params.force_exclude_all_options) {
o.forceExcludeAllOptions = true;
}
if (params === null || params === void 0 ? void 0 : params.keep_enum_prefix) {
o.keepEnumPrefix = true;
}
if (params === null || params === void 0 ? void 0 : params.use_proto_field_name) {
o.useProtoFieldName = true;
}
if (params === null || params === void 0 ? void 0 : params.ts_nocheck) {
o.tsNoCheck = true;
}
if (params === null || params === void 0 ? void 0 : params.eslint_disable) {
o.esLintDisable = true;
}
if (params === null || params === void 0 ? void 0 : params.long_type_string) {
o.normalLongType = rt.LongType.STRING;
}
if (params === null || params === void 0 ? void 0 : params.long_type_number) {
o.normalLongType = rt.LongType.NUMBER;
}
if (params === null || params === void 0 ? void 0 : params.optimize_code_size) {
o.normalOptimizeMode = plugin_framework_1.FileOptions_OptimizeMode.CODE_SIZE;
}
if (params === null || params === void 0 ? void 0 : params.force_optimize_speed) {
o.forcedOptimizeMode = plugin_framework_1.FileOptions_OptimizeMode.SPEED;
}
if (params === null || params === void 0 ? void 0 : params.force_optimize_code_size) {
o.forcedOptimizeMode = plugin_framework_1.FileOptions_OptimizeMode.CODE_SIZE;
}
if (params === null || params === void 0 ? void 0 : params.client_none) {
o.normalClientStyle = ClientStyle.NO_CLIENT;
}
if (params === null || params === void 0 ? void 0 : params.client_grpc1) {
o.normalClientStyle = ClientStyle.GRPC1_CLIENT;
}
if (params === null || params === void 0 ? void 0 : params.force_client_none) {
o.forcedClientStyle = ClientStyle.NO_CLIENT;
}
if (params === null || params === void 0 ? void 0 : params.server_generic) {
o.normalServerStyle = ServerStyle.GENERIC_SERVER;
}
if (params === null || params === void 0 ? void 0 : params.server_grpc1) {
o.normalServerStyle = ServerStyle.GRPC1_SERVER;
}
if (params === null || params === void 0 ? void 0 : params.force_server_none) {
o.forcedServerStyle = ServerStyle.NO_SERVER;
}
if (params === null || params === void 0 ? void 0 : params.add_pb_suffix) {
o.addPbSuffix = true;
}
if (params === null || params === void 0 ? void 0 : params.force_disable_services) {
o.forceDisableServices = true;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript) {
o.transpileTarget = ts.ScriptTarget.ES2020;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript_es2015) {
o.transpileTarget = ts.ScriptTarget.ES2015;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript_es2016) {
o.transpileTarget = ts.ScriptTarget.ES2016;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript_es2017) {
o.transpileTarget = ts.ScriptTarget.ES2017;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript_es2018) {
o.transpileTarget = ts.ScriptTarget.ES2018;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript_es2019) {
o.transpileTarget = ts.ScriptTarget.ES2019;
}
if (params === null || params === void 0 ? void 0 : params.output_javascript_es2020) {
o.transpileTarget = ts.ScriptTarget.ES2020;
}
if (params === null || params === void 0 ? void 0 : params.output_legacy_commonjs) {
o.transpileModule = ts.ModuleKind.CommonJS;
}
return o;
}
exports.makeInternalOptions = makeInternalOptions;
class OptionResolver {
constructor(interpreter, stringFormat, options) {
this.interpreter = interpreter;
this.stringFormat = stringFormat;
this.options = options;
}
getOptimizeMode(file) {
var _a;
if (this.options.forcedOptimizeMode !== undefined) {
return this.options.forcedOptimizeMode;
}
if (((_a = file.options) === null || _a === void 0 ? void 0 : _a.optimizeFor) !== undefined) {
return file.options.optimizeFor;
}
return this.options.normalOptimizeMode;
}
getClientStyles(descriptor) {
const opt = this.interpreter.readOurServiceOptions(descriptor)["ts.client"];
// always check service options valid
if (opt.includes(ClientStyle.NO_CLIENT) && opt.some(s => s !== ClientStyle.NO_CLIENT)) {
let err = new Error(`You provided invalid options for ${this.stringFormat.formatQualifiedName(descriptor, true)}. If you set (ts.client) = NO_CLIENT, you cannot set additional client styles.`);
err.name = `PluginMessageError`;
throw err;
}
if (this.options.forcedClientStyle !== undefined) {
return [this.options.forcedClientStyle];
}
// look for service options
if (opt.length) {
return opt
.filter(s => s !== ClientStyle.NO_CLIENT)
.filter((value, index, array) => array.indexOf(value) === index);
}
// fall back to normal style set by option
return [this.options.normalClientStyle];
}
getServerStyles(descriptor) {
const opt = this.interpreter.readOurServiceOptions(descriptor)["ts.server"];
// always check service options valid
if (opt.includes(ServerStyle.NO_SERVER) && opt.some(s => s !== ServerStyle.NO_SERVER)) {
let err = new Error(`You provided invalid options for ${this.stringFormat.formatQualifiedName(descriptor, true)}. If you set (ts.server) = NO_SERVER, you cannot set additional server styles.`);
err.name = `PluginMessageError`;
throw err;
}
if (this.options.forcedServerStyle !== undefined) {
return [this.options.forcedServerStyle];
}
// look for service options
if (opt.length) {
return opt
.filter(s => s !== ServerStyle.NO_SERVER)
.filter((value, index, array) => array.indexOf(value) === index);
}
// fall back to normal style set by option
return [this.options.normalServerStyle];
}
}
exports.OptionResolver = OptionResolver;

View file

@ -0,0 +1,15 @@
import { DescriptorRegistry, FileDescriptorProto, GeneratedFile, TypescriptFile } from "@protobuf-ts/plugin-framework";
import { InternalOptions } from "./our-options";
/**
* A protobuf-ts output file.
*/
export declare class OutFile extends TypescriptFile implements GeneratedFile {
readonly fileDescriptor: FileDescriptorProto;
private readonly registry;
private readonly options;
private header;
constructor(name: string, fileDescriptor: FileDescriptorProto, registry: DescriptorRegistry, options: InternalOptions);
getContent(): string;
getHeader(): string;
private makeHeader;
}

View file

@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.OutFile = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
/**
* A protobuf-ts output file.
*/
class OutFile extends plugin_framework_1.TypescriptFile {
constructor(name, fileDescriptor, registry, options) {
super(name);
this.fileDescriptor = fileDescriptor;
this.registry = registry;
this.options = options;
}
getContent() {
if (this.isEmpty()) {
return "";
}
return this.getHeader() + super.getContent();
}
getHeader() {
if (this.isEmpty()) {
return "";
}
if (!this.header) {
this.header = this.makeHeader();
}
return this.header;
}
makeHeader() {
var _a;
let props = [];
if (this.fileDescriptor.package) {
props.push('package "' + this.fileDescriptor.package + '"');
}
props.push('syntax ' + ((_a = this.fileDescriptor.syntax) !== null && _a !== void 0 ? _a : 'proto2'));
const header = [];
if (this.options.esLintDisable) {
header.push(`/* eslint-disable */`);
}
header.push(...[
`// @generated ${this.options.pluginCredit}`,
`// @generated from protobuf file "${this.fileDescriptor.name}" (${props.join(', ')})`,
`// tslint:disable`
]);
if (this.options.tsNoCheck) {
header.push(`// @ts-nocheck`);
}
if (this.registry.isExplicitlyDeclaredDeprecated(this.fileDescriptor)) {
header.push('// @deprecated');
}
[
...this.registry.sourceCodeComments(this.fileDescriptor, plugin_framework_1.FileDescriptorProtoFields.syntax).leadingDetached,
...this.registry.sourceCodeComments(this.fileDescriptor, plugin_framework_1.FileDescriptorProtoFields.package).leadingDetached
].every(block => header.push('//', ...block.split('\n').map(l => '//' + l), '//'));
let head = header.join('\n');
if (head.length > 0 && !head.endsWith('\n')) {
head += '\n';
}
return head;
}
}
exports.OutFile = OutFile;

View file

@ -0,0 +1,142 @@
import { CodeGeneratorRequest, CodeGeneratorResponse_Feature, GeneratedFile, PluginBase } from "@protobuf-ts/plugin-framework";
import { OutFile } from "./out-file";
import { InternalOptions } from "./our-options";
export declare class ProtobuftsPlugin extends PluginBase {
private readonly version;
parameters: {
long_type_string: {
description: string;
excludes: string[];
};
long_type_number: {
description: string;
excludes: string[];
};
long_type_bigint: {
description: string;
excludes: string[];
};
generate_dependencies: {
description: string;
};
force_exclude_all_options: {
description: string;
};
keep_enum_prefix: {
description: string;
};
use_proto_field_name: {
description: string;
};
ts_nocheck: {
description: string;
excludes: string[];
};
disable_ts_nocheck: {
description: string;
excludes: string[];
};
eslint_disable: {
description: string;
excludes: string[];
};
no_eslint_disable: {
description: string;
excludes: string[];
};
add_pb_suffix: {
description: string;
};
output_typescript: {
description: string;
excludes: string[];
};
output_javascript: {
description: string;
excludes: string[];
};
output_javascript_es2015: {
description: string;
excludes: string[];
};
output_javascript_es2016: {
description: string;
excludes: string[];
};
output_javascript_es2017: {
description: string;
excludes: string[];
};
output_javascript_es2018: {
description: string;
excludes: string[];
};
output_javascript_es2019: {
description: string;
excludes: string[];
};
output_javascript_es2020: {
description: string;
excludes: string[];
};
output_legacy_commonjs: {
description: string;
excludes: string[];
};
client_none: {
description: string;
excludes: string[];
};
client_generic: {
description: string;
excludes: string[];
};
client_grpc1: {
description: string;
excludes: string[];
};
force_client_none: {
description: string;
excludes: string[];
};
server_none: {
description: string;
excludes: string[];
};
server_generic: {
description: string;
excludes: string[];
};
server_grpc1: {
description: string;
excludes: string[];
};
force_server_none: {
description: string;
};
force_disable_services: {
description: string;
excludes: string[];
};
optimize_speed: {
description: string;
excludes: string[];
};
optimize_code_size: {
description: string;
excludes: string[];
};
force_optimize_code_size: {
description: string;
excludes: string[];
};
force_optimize_speed: {
description: string;
excludes: string[];
};
};
constructor(version: string);
generate(request: CodeGeneratorRequest): GeneratedFile[];
protected transpile(tsFiles: OutFile[], options: InternalOptions): GeneratedFile[];
protected getSupportedFeatures: () => CodeGeneratorResponse_Feature[];
}

View file

@ -0,0 +1,357 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProtobuftsPlugin = void 0;
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
const out_file_1 = require("./out-file");
const local_type_name_1 = require("./code-gen/local-type-name");
const interpreter_1 = require("./interpreter");
const our_options_1 = require("./our-options");
const service_server_generator_grpc_1 = require("./code-gen/service-server-generator-grpc");
const comment_generator_1 = require("./code-gen/comment-generator");
const message_interface_generator_1 = require("./code-gen/message-interface-generator");
const message_type_generator_1 = require("./code-gen/message-type-generator");
const enum_generator_1 = require("./code-gen/enum-generator");
const service_type_generator_1 = require("./code-gen/service-type-generator");
const service_client_generator_generic_1 = require("./code-gen/service-client-generator-generic");
const file_table_1 = require("./file-table");
const service_server_generator_generic_1 = require("./code-gen/service-server-generator-generic");
const service_client_generator_grpc_1 = require("./code-gen/service-client-generator-grpc");
const ts = require("typescript");
const runtime_1 = require("@protobuf-ts/runtime");
const well_known_types_1 = require("./message-type-extensions/well-known-types");
class ProtobuftsPlugin extends plugin_framework_1.PluginBase {
constructor(version) {
super();
this.version = version;
this.parameters = {
// @formatter:off
// long type
long_type_string: {
description: "Sets jstype = JS_STRING for message fields with 64 bit integral values. \n" +
"The default behaviour is to use native `bigint`. \n" +
"Only applies to fields that do *not* use the option `jstype`.",
excludes: ["long_type_number", "long_type_bigint"],
},
long_type_number: {
description: "Sets jstype = JS_NUMBER for message fields with 64 bit integral values. \n" +
"The default behaviour is to use native `bigint`. \n" +
"Only applies to fields that do *not* use the option `jstype`.",
excludes: ["long_type_string", "long_type_bigint"],
},
long_type_bigint: {
description: "Sets jstype = JS_NORMAL for message fields with 64 bit integral values. \n" +
"This is the default behavior. \n" +
"Only applies to fields that do *not* use the option `jstype`.",
excludes: ["long_type_string", "long_type_number"],
},
// misc
generate_dependencies: {
description: "By default, only the PROTO_FILES passed as input to protoc are generated, \n" +
"not the files they import (with the exception of well-known types, which are \n" +
"always generated when imported). \n" +
"Set this option to generate code for dependencies too.",
},
force_exclude_all_options: {
description: "By default, custom options are included in the metadata and can be blacklisted \n" +
"with our option (ts.exclude_options). Set this option if you are certain you \n" +
"do not want to include any options at all.",
},
keep_enum_prefix: {
description: "By default, if all enum values share a prefix that corresponds with the enum's \n" +
"name, the prefix is dropped from the value names. Set this option to disable \n" +
"this behavior.",
},
use_proto_field_name: {
description: "By default interface fields use lowerCamelCase names by transforming proto field\n" +
"names to follow common style convention for TypeScript. Set this option to preserve\n" +
"original proto field names in generated interfaces.",
},
ts_nocheck: {
description: "Generate a @ts-nocheck annotation at the top of each file. This will become the \n" +
"default behaviour in the next major release.",
excludes: ['disable_ts_nocheck'],
},
disable_ts_nocheck: {
description: "Do not generate a @ts-nocheck annotation at the top of each file. Since this is \n" +
"the default behaviour, this option has no effect.",
excludes: ['ts_nocheck'],
},
eslint_disable: {
description: "Generate a eslint-disable comment at the top of each file. This will become the \n" +
"default behaviour in the next major release.",
excludes: ['no_eslint_disable'],
},
no_eslint_disable: {
description: "Do not generate a eslint-disable comment at the top of each file. Since this is \n" +
"the default behaviour, this option has no effect.",
excludes: ['eslint_disable'],
},
add_pb_suffix: {
description: "Adds the suffix `_pb` to the names of all generated files. This will become the \n" +
"default behaviour in the next major release.",
},
// output types
output_typescript: {
description: "Output TypeScript files. This is the default behavior.",
excludes: ["output_javascript", "output_javascript_es2015", "output_javascript_es2016", "output_javascript_es2017", "output_javascript_es2018", "output_javascript_es2019", "output_javascript_es2020"]
},
output_javascript: {
description: "Output JavaScript for the currently recommended target ES2020. The target may \n" +
"change with a major release of protobuf-ts. \n" +
"Along with JavaScript files, this always outputs TypeScript declaration files.",
excludes: ["output_typescript", "output_javascript_es2015", "output_javascript_es2016", "output_javascript_es2017", "output_javascript_es2018", "output_javascript_es2019", "output_javascript_es2020"]
},
output_javascript_es2015: {
description: "Output JavaScript for the ES2015 target.",
excludes: ["output_typescript", "output_javascript_es2016", "output_javascript_es2017", "output_javascript_es2018", "output_javascript_es2019", "output_javascript_es2020"]
},
output_javascript_es2016: {
description: "Output JavaScript for the ES2016 target.",
excludes: ["output_typescript", "output_javascript_es2015", "output_javascript_es2017", "output_javascript_es2018", "output_javascript_es2019", "output_javascript_es2020"]
},
output_javascript_es2017: {
description: "Output JavaScript for the ES2017 target.",
excludes: ["output_typescript", "output_javascript_es2015", "output_javascript_es2016", "output_javascript_es2018", "output_javascript_es2019", "output_javascript_es2020"]
},
output_javascript_es2018: {
description: "Output JavaScript for the ES2018 target.",
excludes: ["output_typescript", "output_javascript_es2015", "output_javascript_es2016", "output_javascript_es2017", "output_javascript_es2019", "output_javascript_es2020"]
},
output_javascript_es2019: {
description: "Output JavaScript for the ES2019 target.",
excludes: ["output_typescript", "output_javascript_es2015", "output_javascript_es2016", "output_javascript_es2017", "output_javascript_es2018", "output_javascript_es2020"]
},
output_javascript_es2020: {
description: "Output JavaScript for the ES2020 target.",
excludes: ["output_typescript", "output_javascript_es2015", "output_javascript_es2016", "output_javascript_es2017", "output_javascript_es2018", "output_javascript_es2019"]
},
output_legacy_commonjs: {
description: "Use CommonJS instead of the default ECMAScript module system.",
excludes: ["output_typescript"]
},
// client
client_none: {
description: "Do not generate rpc clients. \n" +
"Only applies to services that do *not* use the option `ts.client`. \n" +
"If you do not want rpc clients at all, use `force_client_none`.",
excludes: ['client_generic', 'client_grpc1'],
},
client_generic: {
description: "Only applies to services that do *not* use the option `ts.client`. \n" +
"Since GENERIC_CLIENT is the default, this option has no effect.",
excludes: ['client_none', 'client_grpc1', 'force_client_none', 'force_disable_services'],
},
client_grpc1: {
description: "Generate a client using @grpc/grpc-js (major version 1). \n" +
"Only applies to services that do *not* use the option `ts.client`.",
excludes: ['client_none', 'client_generic', 'force_client_none', 'force_disable_services'],
},
force_client_none: {
description: "Do not generate rpc clients, ignore options in proto files.",
excludes: ['client_none', 'client_generic', 'client_grpc1'],
},
// server
server_none: {
description: "Do not generate rpc servers. \n" +
"This is the default behaviour, but only applies to services that do \n" +
"*not* use the option `ts.server`. \n" +
"If you do not want servers at all, use `force_server_none`.",
excludes: ['server_grpc1'],
},
server_generic: {
description: "Generate a generic server interface. Adapters are used to serve the service, \n" +
"for example @protobuf-ts/grpc-backend for gRPC. \n" +
"Note that this is an experimental feature and may change with a minor release. \n" +
"Only applies to services that do *not* use the option `ts.server`.",
excludes: ['server_none', 'force_server_none', 'force_disable_services'],
},
server_grpc1: {
description: "Generate a server interface and definition for use with @grpc/grpc-js \n" +
"(major version 1). \n" +
"Only applies to services that do *not* use the option `ts.server`.",
excludes: ['server_none', 'force_server_none', 'force_disable_services'],
},
force_server_none: {
description: "Do not generate rpc servers, ignore options in proto files.",
},
force_disable_services: {
description: "Do not generate anything for service definitions, and ignore options in proto \n" +
"files. This is the same as setting both options `force_server_none` and \n" +
"`force_client_none`, but also stops generating service metadata.",
excludes: ['client_generic', 'client_grpc1', 'server_generic', 'server_grpc1']
},
// optimization
optimize_speed: {
description: "Sets optimize_for = SPEED for proto files that have no file option \n" +
"'option optimize_for'. Since SPEED is the default, this option has no effect.",
excludes: ['force_optimize_speed'],
},
optimize_code_size: {
description: "Sets optimize_for = CODE_SIZE for proto files that have no file option \n" +
"'option optimize_for'.",
excludes: ['force_optimize_speed'],
},
force_optimize_code_size: {
description: "Forces optimize_for = CODE_SIZE for all proto files, ignore file options.",
excludes: ['optimize_code_size', 'force_optimize_speed']
},
force_optimize_speed: {
description: "Forces optimize_for = SPEED for all proto files, ignore file options.",
excludes: ['optimize_code_size', 'force_optimize_code_size']
},
};
// we support proto3-optionals, so we let protoc know
this.getSupportedFeatures = () => [plugin_framework_1.CodeGeneratorResponse_Feature.PROTO3_OPTIONAL];
this.version = version;
}
generate(request) {
const options = our_options_1.makeInternalOptions(this.parseOptions(this.parameters, request.parameter), `by protobuf-ts ${this.version}` + (request.parameter ? ` with parameter ${request.parameter}` : '')), registry = plugin_framework_1.DescriptorRegistry.createFrom(request), symbols = new plugin_framework_1.SymbolTable(), fileTable = new file_table_1.FileTable(), imports = new plugin_framework_1.TypeScriptImports(symbols), comments = new comment_generator_1.CommentGenerator(registry), interpreter = new interpreter_1.Interpreter(registry, options), optionResolver = new our_options_1.OptionResolver(interpreter, registry, options), genMessageInterface = new message_interface_generator_1.MessageInterfaceGenerator(symbols, registry, imports, comments, interpreter, options), genEnum = new enum_generator_1.EnumGenerator(symbols, registry, imports, comments, interpreter, options), genMessageType = new message_type_generator_1.MessageTypeGenerator(symbols, registry, imports, comments, interpreter, options), genServiceType = new service_type_generator_1.ServiceTypeGenerator(symbols, registry, imports, comments, interpreter, options), genServerGeneric = new service_server_generator_generic_1.ServiceServerGeneratorGeneric(symbols, registry, imports, comments, interpreter, options), genServerGrpc = new service_server_generator_grpc_1.ServiceServerGeneratorGrpc(symbols, registry, imports, comments, interpreter, options), genClientGeneric = new service_client_generator_generic_1.ServiceClientGeneratorGeneric(symbols, registry, imports, comments, interpreter, options), genClientGrpc = new service_client_generator_grpc_1.ServiceClientGeneratorGrpc(symbols, registry, imports, comments, interpreter, options);
let tsFiles = [];
// ensure unique file names
for (let fileDescriptor of registry.allFiles()) {
const base = fileDescriptor.name.replace('.proto', '') + (options.addPbSuffix ? "_pb" : "");
fileTable.register(base + '.ts', fileDescriptor);
}
for (let fileDescriptor of registry.allFiles()) {
const base = fileDescriptor.name.replace('.proto', '') + (options.addPbSuffix ? "_pb" : "");
fileTable.register(base + '.server.ts', fileDescriptor, 'generic-server');
fileTable.register(base + '.grpc-server.ts', fileDescriptor, 'grpc1-server');
fileTable.register(base + '.client.ts', fileDescriptor, 'client');
fileTable.register(base + '.promise-client.ts', fileDescriptor, 'promise-client');
fileTable.register(base + '.rx-client.ts', fileDescriptor, 'rx-client');
fileTable.register(base + '.grpc-client.ts', fileDescriptor, 'grpc1-client');
}
for (let fileDescriptor of registry.allFiles()) {
const outMain = new out_file_1.OutFile(fileTable.get(fileDescriptor).name, fileDescriptor, registry, options), outServerGeneric = new out_file_1.OutFile(fileTable.get(fileDescriptor, 'generic-server').name, fileDescriptor, registry, options), outServerGrpc = new out_file_1.OutFile(fileTable.get(fileDescriptor, 'grpc1-server').name, fileDescriptor, registry, options), outClientCall = new out_file_1.OutFile(fileTable.get(fileDescriptor, 'client').name, fileDescriptor, registry, options), outClientPromise = new out_file_1.OutFile(fileTable.get(fileDescriptor, 'promise-client').name, fileDescriptor, registry, options), outClientRx = new out_file_1.OutFile(fileTable.get(fileDescriptor, 'rx-client').name, fileDescriptor, registry, options), outClientGrpc = new out_file_1.OutFile(fileTable.get(fileDescriptor, 'grpc1-client').name, fileDescriptor, registry, options);
tsFiles.push(outMain, outServerGeneric, outServerGrpc, outClientCall, outClientPromise, outClientRx, outClientGrpc);
registry.visitTypes(fileDescriptor, descriptor => {
// we are not interested in synthetic types like map entry messages
if (registry.isSyntheticElement(descriptor))
return;
// register all symbols, regardless whether they are going to be used - we want stable behaviour
symbols.register(local_type_name_1.createLocalTypeName(descriptor, registry), descriptor, outMain);
if (plugin_framework_1.ServiceDescriptorProto.is(descriptor)) {
genClientGeneric.registerSymbols(outClientCall, descriptor);
genClientGrpc.registerSymbols(outClientGrpc, descriptor);
genServerGeneric.registerSymbols(outServerGeneric, descriptor);
genServerGrpc.registerSymbols(outServerGrpc, descriptor);
}
});
registry.visitTypes(fileDescriptor, descriptor => {
// we are not interested in synthetic types like map entry messages
if (registry.isSyntheticElement(descriptor))
return;
if (plugin_framework_1.DescriptorProto.is(descriptor)) {
genMessageInterface.generateMessageInterface(outMain, descriptor);
}
if (plugin_framework_1.EnumDescriptorProto.is(descriptor)) {
genEnum.generateEnum(outMain, descriptor);
}
});
registry.visitTypes(fileDescriptor, descriptor => {
// still not interested in synthetic types like map entry messages
if (registry.isSyntheticElement(descriptor))
return;
if (plugin_framework_1.DescriptorProto.is(descriptor)) {
genMessageType.generateMessageType(outMain, descriptor, optionResolver.getOptimizeMode(fileDescriptor));
}
if (!options.forceDisableServices) {
if (plugin_framework_1.ServiceDescriptorProto.is(descriptor)) {
// service type
genServiceType.generateServiceType(outMain, descriptor);
// clients
const clientStyles = optionResolver.getClientStyles(descriptor);
if (clientStyles.includes(our_options_1.ClientStyle.GENERIC_CLIENT)) {
genClientGeneric.generateInterface(outClientCall, descriptor);
genClientGeneric.generateImplementationClass(outClientCall, descriptor);
}
if (clientStyles.includes(our_options_1.ClientStyle.GRPC1_CLIENT)) {
genClientGrpc.generateInterface(outClientGrpc, descriptor);
genClientGrpc.generateImplementationClass(outClientGrpc, descriptor);
}
// servers
const serverStyles = optionResolver.getServerStyles(descriptor);
if (serverStyles.includes(our_options_1.ServerStyle.GENERIC_SERVER)) {
genServerGeneric.generateInterface(outServerGeneric, descriptor);
}
if (serverStyles.includes(our_options_1.ServerStyle.GRPC1_SERVER)) {
genServerGrpc.generateInterface(outServerGrpc, descriptor);
genServerGrpc.generateDefinition(outServerGrpc, descriptor);
}
}
}
});
}
// plugins should only return files requested to generate
// unless our option "generate_dependencies" is set.
// We always return well-known types, because we do not
// maintain them in a package - they are always generated
// on demand.
if (!options.generateDependencies) {
tsFiles = tsFiles.filter(file => {
const protoFilename = file.fileDescriptor.name;
runtime_1.assert(protoFilename);
if (request.fileToGenerate.includes(protoFilename)) {
return true;
}
if (well_known_types_1.WellKnownTypes.protoFilenames.includes(protoFilename)) {
return true;
}
return false;
});
}
// if a proto file is imported to use custom options, or if a proto file declares custom options,
// we do not to emit it. unless it was explicitly requested.
const outFileDescriptors = tsFiles.map(of => of.fileDescriptor);
tsFiles = tsFiles.filter(of => request.fileToGenerate.includes(of.fileDescriptor.name)
|| registry.isFileUsed(of.fileDescriptor, outFileDescriptors));
return this.transpile(tsFiles, options);
}
transpile(tsFiles, options) {
if (options.transpileTarget === undefined) {
return tsFiles;
}
const opt = {
moduleResolution: ts.ModuleResolutionKind.NodeJs,
skipLibCheck: true,
declaration: true,
module: options.transpileModule,
target: options.transpileTarget,
};
const [program,] = plugin_framework_1.setupCompiler(opt, tsFiles, tsFiles.map(f => f.getFilename()));
const results = [];
let err;
program.emit(undefined, (fileName, data, writeByteOrderMark, onError, sourceFiles) => {
// We have to go through some hoops here because the header we add to each file
// is not part of the AST. So we find the TypeScript file we generated for each
// emitted file and add the header to each output ourselves.
if (!sourceFiles) {
err = new Error(`unable to map emitted file "${fileName}" to a source file: missing source files`);
return;
}
if (sourceFiles.length !== 1) {
err = new Error(`unable to map emitted file "${fileName}" to a source file: expected 1 source file, got ${sourceFiles.length}`);
return;
}
const tsFile = tsFiles.find(x => sourceFiles[0].fileName === x.getFilename());
if (!tsFile) {
err = new Error(`unable to map emitted file "${fileName}" to a source file: not found`);
return;
}
const content = tsFile.getHeader() + data;
results.push({
getFilename() {
return fileName;
},
getContent() {
return content;
}
});
});
if (err) {
throw err;
}
return results;
}
}
exports.ProtobuftsPlugin = ProtobuftsPlugin;

View file

@ -0,0 +1 @@
../typescript/bin/tsc

View file

@ -0,0 +1 @@
../typescript/bin/tsserver

View file

@ -0,0 +1,480 @@
TypeScript is authored by:
- 0verk1ll
- Abubaker Bashir
- Adam Freidin
- Adam Postma
- Adi Dahiya
- Aditya Daflapurkar
- Adnan Chowdhury
- Adrian Leonhard
- Adrien Gibrat
- Ahmad Farid
- Ajay Poshak
- Alan Agius
- Alan Pierce
- Alessandro Vergani
- Alex Chugaev
- Alex Eagle
- Alex Khomchenko
- Alex Ryan
- Alexander
- Alexander Kuvaev
- Alexander Rusakov
- Alexander Tarasyuk
- Ali Sabzevari
- Aluan Haddad
- amaksimovich2
- Anatoly Ressin
- Anders Hejlsberg
- Anders Kaseorg
- Andre Sutherland
- Andreas Martin
- Andrej Baran
- Andrew
- Andrew Branch
- Andrew Casey
- Andrew Faulkner
- Andrew Ochsner
- Andrew Stegmaier
- Andrew Z Allen
- Andrey Roenko
- Andrii Dieiev
- András Parditka
- Andy Hanson
- Anil Anar
- Anix
- Anton Khlynovskiy
- Anton Tolmachev
- Anubha Mathur
- AnyhowStep
- Armando Aguirre
- Arnaud Tournier
- Arnav Singh
- Arpad Borsos
- Artem Tyurin
- Arthur Ozga
- Asad Saeeduddin
- Austin Cummings
- Avery Morin
- Aziz Khambati
- Basarat Ali Syed
- @begincalendar
- Ben Duffield
- Ben Lichtman
- Ben Mosher
- Benedikt Meurer
- Benjamin Bock
- Benjamin Lichtman
- Benny Neugebauer
- BigAru
- Bill Ticehurst
- Blaine Bublitz
- Blake Embrey
- @bluelovers
- @bootstraponline
- Bowden Kelly
- Bowden Kenny
- Brad Zacher
- Brandon Banks
- Brandon Bloom
- Brandon Slade
- Brendan Kenny
- Brett Mayen
- Brian Terlson
- Bryan Forbes
- Caitlin Potter
- Caleb Sander
- Cameron Taggart
- @cedvdb
- Charles
- Charles Pierce
- Charly POLY
- Chris Bubernak
- Chris Patterson
- christian
- Christophe Vidal
- Chuck Jazdzewski
- Clay Miller
- Colby Russell
- Colin Snover
- Collins Abitekaniza
- Connor Clark
- Cotton Hou
- csigs
- Cyrus Najmabadi
- Dafrok Zhang
- Dahan Gong
- Daiki Nishikawa
- Dan Corder
- Dan Freeman
- Dan Quirk
- Dan Rollo
- Daniel Gooss
- Daniel Imms
- Daniel Krom
- Daniel Król
- Daniel Lehenbauer
- Daniel Rosenwasser
- David Li
- David Sheldrick
- David Sherret
- David Souther
- David Staheli
- Denis Nedelyaev
- Derek P Sifford
- Dhruv Rajvanshi
- Dick van den Brink
- Diogo Franco (Kovensky)
- Dirk Bäumer
- Dirk Holtwick
- Dmitrijs Minajevs
- Dom Chen
- Donald Pipowitch
- Doug Ilijev
- dreamran43@gmail.com
- @e-cloud
- Ecole Keine
- Eddie Jaoude
- Edward Thomson
- EECOLOR
- Eli Barzilay
- Elizabeth Dinella
- Ely Alamillo
- Eric Grube
- Eric Tsang
- Erik Edrosa
- Erik McClenney
- Esakki Raj
- Ethan Resnick
- Ethan Rubio
- Eugene Timokhov
- Evan Cahill
- Evan Martin
- Evan Sebastian
- ExE Boss
- Eyas Sharaiha
- Fabian Cook
- @falsandtru
- Filipe Silva
- @flowmemo
- Forbes Lindesay
- Francois Hendriks
- Francois Wouts
- Frank Wallis
- František Žiacik
- Frederico Bittencourt
- fullheightcoding
- Gabe Moothart
- Gabriel Isenberg
- Gabriela Araujo Britto
- Gabriela Britto
- gb714us
- Gilad Peleg
- Godfrey Chan
- Gorka Hernández Estomba
- Graeme Wicksted
- Guillaume Salles
- Guy Bedford
- hafiz
- Halasi Tamás
- Hendrik Liebau
- Henry Mercer
- Herrington Darkholme
- Hoang Pham
- Holger Jeromin
- Homa Wong
- Hye Sung Jung
- Iain Monro
- @IdeaHunter
- Igor Novozhilov
- Igor Oleinikov
- Ika
- iliashkolyar
- IllusionMH
- Ingvar Stepanyan
- Ingvar Stepanyan
- Isiah Meadows
- ispedals
- Ivan Enderlin
- Ivo Gabe de Wolff
- Iwata Hidetaka
- Jack Bates
- Jack Williams
- Jake Boone
- Jakub Korzeniowski
- Jakub Młokosiewicz
- James Henry
- James Keane
- James Whitney
- Jan Melcher
- Jason Freeman
- Jason Jarrett
- Jason Killian
- Jason Ramsay
- JBerger
- Jean Pierre
- Jed Mao
- Jeff Wilcox
- Jeffrey Morlan
- Jesse Schalken
- Jesse Trinity
- Jing Ma
- Jiri Tobisek
- Joe Calzaretta
- Joe Chung
- Joel Day
- Joey Watts
- Johannes Rieken
- John Doe
- John Vilk
- Jonathan Bond-Caron
- Jonathan Park
- Jonathan Toland
- Jordan Harband
- Jordi Oliveras Rovira
- Joscha Feth
- Joseph Wunderlich
- Josh Abernathy
- Josh Goldberg
- Josh Kalderimis
- Josh Soref
- Juan Luis Boya García
- Julian Williams
- Justin Bay
- Justin Johansson
- jwbay
- K. Preißer
- Kagami Sascha Rosylight
- Kanchalai Tanglertsampan
- karthikkp
- Kate Miháliková
- Keen Yee Liau
- Keith Mashinter
- Ken Howard
- Kenji Imamula
- Kerem Kat
- Kevin Donnelly
- Kevin Gibbons
- Kevin Lang
- Khải
- Kitson Kelly
- Klaus Meinhardt
- Kris Zyp
- Kyle Kelley
- Kārlis Gaņģis
- laoxiong
- Leon Aves
- Limon Monte
- Lorant Pinter
- Lucien Greathouse
- Luka Hartwig
- Lukas Elmer
- M.Yoshimura
- Maarten Sijm
- Magnus Hiie
- Magnus Kulke
- Manish Bansal
- Manish Giri
- Marcus Noble
- Marin Marinov
- Marius Schulz
- Markus Johnsson
- Markus Wolf
- Martin
- Martin Hiller
- Martin Johns
- Martin Probst
- Martin Vseticka
- Martyn Janes
- Masahiro Wakame
- Mateusz Burzyński
- Matt Bierner
- Matt McCutchen
- Matt Mitchell
- Matthew Aynalem
- Matthew Miller
- Mattias Buelens
- Max Heiber
- Maxwell Paul Brickner
- @meyer
- Micah Zoltu
- @micbou
- Michael
- Michael Crane
- Michael Henderson
- Michael Tamm
- Michael Tang
- Michal Przybys
- Mike Busyrev
- Mike Morearty
- Milosz Piechocki
- Mine Starks
- Minh Nguyen
- Mohamed Hegazy
- Mohsen Azimi
- Mukesh Prasad
- Myles Megyesi
- Nathan Day
- Nathan Fenner
- Nathan Shively-Sanders
- Nathan Yee
- ncoley
- Nicholas Yang
- Nicu Micleușanu
- @nieltg
- Nima Zahedi
- Noah Chen
- Noel Varanda
- Noel Yoo
- Noj Vek
- nrcoley
- Nuno Arruda
- Oleg Mihailik
- Oleksandr Chekhovskyi
- Omer Sheikh
- Orta Therox
- Orta Therox
- Oskar Grunning
- Oskar Segersva¨rd
- Oussama Ben Brahim
- Ozair Patel
- Patrick McCartney
- Patrick Zhong
- Paul Koerbitz
- Paul van Brenk
- @pcbro
- Pedro Maltez
- Pete Bacon Darwin
- Peter Burns
- Peter Šándor
- Philip Pesca
- Philippe Voinov
- Pi Lanningham
- Piero Cangianiello
- Pierre-Antoine Mills
- @piloopin
- Pranav Senthilnathan
- Prateek Goel
- Prateek Nayak
- Prayag Verma
- Priyantha Lankapura
- @progre
- Punya Biswal
- r7kamura
- Rado Kirov
- Raj Dosanjh
- rChaser53
- Reiner Dolp
- Remo H. Jansen
- @rflorian
- Rhys van der Waerden
- @rhysd
- Ricardo N Feliciano
- Richard Karmazín
- Richard Knoll
- Roger Spratley
- Ron Buckton
- Rostislav Galimsky
- Rowan Wyborn
- rpgeeganage
- Ruwan Pradeep Geeganage
- Ryan Cavanaugh
- Ryan Clarke
- Ryohei Ikegami
- Salisbury, Tom
- Sam Bostock
- Sam Drugan
- Sam El-Husseini
- Sam Lanning
- Sangmin Lee
- Sanket Mishra
- Sarangan Rajamanickam
- Sasha Joseph
- Sean Barag
- Sergey Rubanov
- Sergey Shandar
- Sergey Tychinin
- Sergii Bezliudnyi
- Sergio Baidon
- Sharon Rolel
- Sheetal Nandi
- Shengping Zhong
- Sheon Han
- Shyyko Serhiy
- Siddharth Singh
- sisisin
- Slawomir Sadziak
- Solal Pirelli
- Soo Jae Hwang
- Stan Thomas
- Stanislav Iliev
- Stanislav Sysoev
- Stas Vilchik
- Stephan Ginthör
- Steve Lucco
- @styfle
- Sudheesh Singanamalla
- Suhas
- Suhas Deshpande
- superkd37
- Sébastien Arod
- @T18970237136
- @t_
- Tan Li Hau
- Tapan Prakash
- Taras Mankovski
- Tarik Ozket
- Tetsuharu Ohzeki
- The Gitter Badger
- Thomas den Hollander
- Thorsten Ball
- Tien Hoanhtien
- Tim Lancina
- Tim Perry
- Tim Schaub
- Tim Suchanek
- Tim Viiding-Spader
- Tingan Ho
- Titian Cernicova-Dragomir
- tkondo
- Todd Thomson
- togru
- Tom J
- Torben Fitschen
- Toxyxer
- @TravCav
- Troy Tae
- TruongSinh Tran-Nguyen
- Tycho Grouwstra
- uhyo
- Vadi Taslim
- Vakhurin Sergey
- Valera Rozuvan
- Vilic Vane
- Vimal Raghubir
- Vladimir Kurchatkin
- Vladimir Matveev
- Vyacheslav Pukhanov
- Wenlu Wang
- Wes Souza
- Wesley Wigham
- William Orr
- Wilson Hobbs
- xiaofa
- xl1
- Yacine Hmito
- Yang Cao
- York Yao
- @yortus
- Yoshiki Shibukawa
- Yuichi Nukiyama
- Yuval Greenfield
- Yuya Tanaka
- Z
- Zeeshan Ahmed
- Zev Spitz
- Zhengbo Li
- Zixiang Li
- @Zzzen
- 阿卡琳

View file

@ -0,0 +1 @@
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.

View file

@ -0,0 +1,15 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */

View file

@ -0,0 +1,55 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of this License; and
You must cause any modified files to carry prominent notices stating that You changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View file

@ -0,0 +1,107 @@
# TypeScript
[![Build Status](https://travis-ci.org/microsoft/TypeScript.svg?branch=master)](https://travis-ci.org/microsoft/TypeScript)
[![VSTS Build Status](https://dev.azure.com/typescript/TypeScript/_apis/build/status/Typescript/node10)](https://dev.azure.com/typescript/TypeScript/_build/latest?definitionId=4&view=logs)
[![npm version](https://badge.fury.io/js/typescript.svg)](https://www.npmjs.com/package/typescript)
[![Downloads](https://img.shields.io/npm/dm/typescript.svg)](https://www.npmjs.com/package/typescript)
[TypeScript](https://www.typescriptlang.org/) is a language for application-scale JavaScript. TypeScript adds optional types to JavaScript that support tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the [playground](https://www.typescriptlang.org/play/), and stay up to date via [our blog](https://blogs.msdn.microsoft.com/typescript) and [Twitter account](https://twitter.com/typescript).
Find others who are using TypeScript at [our community page](https://www.typescriptlang.org/community/).
## Installing
For the latest stable version:
```bash
npm install -g typescript
```
For our nightly builds:
```bash
npm install -g typescript@next
```
## Contribute
There are many ways to [contribute](https://github.com/microsoft/TypeScript/blob/master/CONTRIBUTING.md) to TypeScript.
* [Submit bugs](https://github.com/microsoft/TypeScript/issues) and help us verify fixes as they are checked in.
* Review the [source code changes](https://github.com/microsoft/TypeScript/pulls).
* Engage with other TypeScript users and developers on [StackOverflow](https://stackoverflow.com/questions/tagged/typescript).
* Help each other in the [TypeScript Community Discord](https://discord.gg/typescript).
* Join the [#typescript](https://twitter.com/search?q=%23TypeScript) discussion on Twitter.
* [Contribute bug fixes](https://github.com/microsoft/TypeScript/blob/master/CONTRIBUTING.md).
* Read the language specification ([docx](https://github.com/microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.docx?raw=true),
[pdf](https://github.com/microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true), [md](https://github.com/microsoft/TypeScript/blob/master/doc/spec.md)).
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see
the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com)
with any additional questions or comments.
## Documentation
* [TypeScript in 5 minutes](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html)
* [Programming handbook](https://www.typescriptlang.org/docs/handbook/basic-types.html)
* [Language specification](https://github.com/microsoft/TypeScript/blob/master/doc/spec.md)
* [Homepage](https://www.typescriptlang.org/)
## Building
In order to build the TypeScript compiler, ensure that you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed.
Clone a copy of the repo:
```bash
git clone https://github.com/microsoft/TypeScript.git
```
Change to the TypeScript directory:
```bash
cd TypeScript
```
Install [Gulp](https://gulpjs.com/) tools and dev dependencies:
```bash
npm install -g gulp
npm ci
```
Use one of the following to build and test:
```
gulp local # Build the compiler into built/local.
gulp clean # Delete the built compiler.
gulp LKG # Replace the last known good with the built one.
# Bootstrapping step to be executed when the built compiler reaches a stable state.
gulp tests # Build the test infrastructure using the built compiler.
gulp runtests # Run tests using the built compiler and test infrastructure.
# Some low-value tests are skipped when not on a CI machine - you can use the
# --skipPercent=0 command to override this behavior and run all tests locally.
# You can override the specific suite runner used or specify a test for this command.
# Use --tests=<testPath> for a specific test and/or --runner=<runnerName> for a specific suite.
# Valid runners include conformance, compiler, fourslash, project, user, and docker
# The user and docker runners are extended test suite runners - the user runner
# works on disk in the tests/cases/user directory, while the docker runner works in containers.
# You'll need to have the docker executable in your system path for the docker runner to work.
gulp runtests-parallel # Like runtests, but split across multiple threads. Uses a number of threads equal to the system
# core count by default. Use --workers=<number> to adjust this.
gulp baseline-accept # This replaces the baseline test results with the results obtained from gulp runtests.
gulp lint # Runs eslint on the TypeScript source.
gulp help # List the above commands.
```
## Usage
```bash
node built/local/tsc.js hello.ts
```
## Roadmap
For details on our planned features and future direction please refer to our [roadmap](https://github.com/microsoft/TypeScript/wiki/Roadmap).

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,2 @@
#!/usr/bin/env node
require('../lib/tsc.js')

View file

@ -0,0 +1,2 @@
#!/usr/bin/env node
require('../lib/tsserver.js')

View file

@ -0,0 +1,5 @@
# Read This!
**These files are not meant to be edited by hand.**
If you need to make modifications, the respective files should be changed within the repository's top-level `src` directory.
Running `gulp LKG` will then appropriately update the files in this directory.

View file

@ -0,0 +1,67 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
"use strict";
var fs = require("fs");
function pipeExists(name) {
return fs.existsSync(name);
}
function createCancellationToken(args) {
var cancellationPipeName;
for (var i = 0; i < args.length - 1; i++) {
if (args[i] === "--cancellationPipeName") {
cancellationPipeName = args[i + 1];
break;
}
}
if (!cancellationPipeName) {
return {
isCancellationRequested: function () { return false; },
setRequest: function (_requestId) { return void 0; },
resetRequest: function (_requestId) { return void 0; }
};
}
if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") {
var namePrefix_1 = cancellationPipeName.slice(0, -1);
if (namePrefix_1.length === 0 || namePrefix_1.indexOf("*") >= 0) {
throw new Error("Invalid name for template cancellation pipe: it should have length greater than 2 characters and contain only one '*'.");
}
var perRequestPipeName_1;
var currentRequestId_1;
return {
isCancellationRequested: function () { return perRequestPipeName_1 !== undefined && pipeExists(perRequestPipeName_1); },
setRequest: function (requestId) {
currentRequestId_1 = requestId;
perRequestPipeName_1 = namePrefix_1 + requestId;
},
resetRequest: function (requestId) {
if (currentRequestId_1 !== requestId) {
throw new Error("Mismatched request id, expected " + currentRequestId_1 + ", actual " + requestId);
}
perRequestPipeName_1 = undefined;
}
};
}
else {
return {
isCancellationRequested: function () { return pipeExists(cancellationPipeName); },
setRequest: function (_requestId) { return void 0; },
resetRequest: function (_requestId) { return void 0; }
};
}
}
module.exports = createCancellationToken;
//# sourceMappingURL=cancellationToken.js.map

View file

@ -0,0 +1,24 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es5" />
/// <reference lib="dom" />
/// <reference lib="webworker.importscripts" />
/// <reference lib="scripthost" />

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,344 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/////////////////////////////
/// DOM Iterable APIs
/////////////////////////////
interface AudioParam {
setValueCurveAtTime(values: Iterable<number>, startTime: number, duration: number): AudioParam;
}
interface AudioParamMap extends ReadonlyMap<string, AudioParam> {
}
interface BaseAudioContext {
createIIRFilter(feedforward: Iterable<number>, feedback: Iterable<number>): IIRFilterNode;
createPeriodicWave(real: Iterable<number>, imag: Iterable<number>, constraints?: PeriodicWaveConstraints): PeriodicWave;
}
interface CSSRuleList {
[Symbol.iterator](): IterableIterator<CSSRule>;
}
interface CSSStyleDeclaration {
[Symbol.iterator](): IterableIterator<string>;
}
interface Cache {
addAll(requests: Iterable<RequestInfo>): Promise<void>;
}
interface CanvasPathDrawingStyles {
setLineDash(segments: Iterable<number>): void;
}
interface ClientRectList {
[Symbol.iterator](): IterableIterator<ClientRect>;
}
interface DOMRectList {
[Symbol.iterator](): IterableIterator<DOMRect>;
}
interface DOMStringList {
[Symbol.iterator](): IterableIterator<string>;
}
interface DOMTokenList {
[Symbol.iterator](): IterableIterator<string>;
entries(): IterableIterator<[number, string]>;
keys(): IterableIterator<number>;
values(): IterableIterator<string>;
}
interface DataTransferItemList {
[Symbol.iterator](): IterableIterator<DataTransferItem>;
}
interface FileList {
[Symbol.iterator](): IterableIterator<File>;
}
interface FormData {
[Symbol.iterator](): IterableIterator<[string, FormDataEntryValue]>;
/**
* Returns an array of key, value pairs for every entry in the list.
*/
entries(): IterableIterator<[string, FormDataEntryValue]>;
/**
* Returns a list of keys in the list.
*/
keys(): IterableIterator<string>;
/**
* Returns a list of values in the list.
*/
values(): IterableIterator<FormDataEntryValue>;
}
interface HTMLAllCollection {
[Symbol.iterator](): IterableIterator<Element>;
}
interface HTMLCollectionBase {
[Symbol.iterator](): IterableIterator<Element>;
}
interface HTMLCollectionOf<T extends Element> {
[Symbol.iterator](): IterableIterator<T>;
}
interface HTMLFormElement {
[Symbol.iterator](): IterableIterator<Element>;
}
interface HTMLSelectElement {
[Symbol.iterator](): IterableIterator<Element>;
}
interface Headers {
[Symbol.iterator](): IterableIterator<[string, string]>;
/**
* Returns an iterator allowing to go through all key/value pairs contained in this object.
*/
entries(): IterableIterator<[string, string]>;
/**
* Returns an iterator allowing to go through all keys of the key/value pairs contained in this object.
*/
keys(): IterableIterator<string>;
/**
* Returns an iterator allowing to go through all values of the key/value pairs contained in this object.
*/
values(): IterableIterator<string>;
}
interface IDBObjectStore {
/**
* Creates a new index in store with the given name, keyPath and options and returns a new IDBIndex. If the keyPath and options define constraints that cannot be satisfied with the data already in store the upgrade transaction will abort with a "ConstraintError" DOMException.
*
* Throws an "InvalidStateError" DOMException if not called within an upgrade transaction.
*/
createIndex(name: string, keyPath: string | Iterable<string>, options?: IDBIndexParameters): IDBIndex;
}
interface MediaKeyStatusMap {
[Symbol.iterator](): IterableIterator<[BufferSource, MediaKeyStatus]>;
entries(): IterableIterator<[BufferSource, MediaKeyStatus]>;
keys(): IterableIterator<BufferSource>;
values(): IterableIterator<MediaKeyStatus>;
}
interface MediaList {
[Symbol.iterator](): IterableIterator<string>;
}
interface MimeTypeArray {
[Symbol.iterator](): IterableIterator<MimeType>;
}
interface NamedNodeMap {
[Symbol.iterator](): IterableIterator<Attr>;
}
interface Navigator {
requestMediaKeySystemAccess(keySystem: string, supportedConfigurations: Iterable<MediaKeySystemConfiguration>): Promise<MediaKeySystemAccess>;
}
interface NodeList {
[Symbol.iterator](): IterableIterator<Node>;
/**
* Returns an array of key, value pairs for every entry in the list.
*/
entries(): IterableIterator<[number, Node]>;
/**
* Returns an list of keys in the list.
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the list.
*/
values(): IterableIterator<Node>;
}
interface NodeListOf<TNode extends Node> {
[Symbol.iterator](): IterableIterator<TNode>;
/**
* Returns an array of key, value pairs for every entry in the list.
*/
entries(): IterableIterator<[number, TNode]>;
/**
* Returns an list of keys in the list.
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the list.
*/
values(): IterableIterator<TNode>;
}
interface Plugin {
[Symbol.iterator](): IterableIterator<MimeType>;
}
interface PluginArray {
[Symbol.iterator](): IterableIterator<Plugin>;
}
interface RTCRtpTransceiver {
setCodecPreferences(codecs: Iterable<RTCRtpCodecCapability>): void;
}
interface RTCStatsReport extends ReadonlyMap<string, any> {
}
interface SVGLengthList {
[Symbol.iterator](): IterableIterator<SVGLength>;
}
interface SVGNumberList {
[Symbol.iterator](): IterableIterator<SVGNumber>;
}
interface SVGPointList {
[Symbol.iterator](): IterableIterator<DOMPoint>;
}
interface SVGStringList {
[Symbol.iterator](): IterableIterator<string>;
}
interface SourceBufferList {
[Symbol.iterator](): IterableIterator<SourceBuffer>;
}
interface SpeechGrammarList {
[Symbol.iterator](): IterableIterator<SpeechGrammar>;
}
interface SpeechRecognitionResult {
[Symbol.iterator](): IterableIterator<SpeechRecognitionAlternative>;
}
interface SpeechRecognitionResultList {
[Symbol.iterator](): IterableIterator<SpeechRecognitionResult>;
}
interface StyleSheetList {
[Symbol.iterator](): IterableIterator<CSSStyleSheet>;
}
interface TextTrackCueList {
[Symbol.iterator](): IterableIterator<TextTrackCue>;
}
interface TextTrackList {
[Symbol.iterator](): IterableIterator<TextTrack>;
}
interface TouchList {
[Symbol.iterator](): IterableIterator<Touch>;
}
interface URLSearchParams {
[Symbol.iterator](): IterableIterator<[string, string]>;
/**
* Returns an array of key, value pairs for every entry in the search params.
*/
entries(): IterableIterator<[string, string]>;
/**
* Returns a list of keys in the search params.
*/
keys(): IterableIterator<string>;
/**
* Returns a list of values in the search params.
*/
values(): IterableIterator<string>;
}
interface VRDisplay {
requestPresent(layers: Iterable<VRLayer>): Promise<void>;
}
interface WEBGL_draw_buffers {
drawBuffersWEBGL(buffers: Iterable<GLenum>): void;
}
interface WebAuthentication {
makeCredential(accountInformation: Account, cryptoParameters: Iterable<ScopedCredentialParameters>, attestationChallenge: Int8Array | Int16Array | Int32Array | Uint8Array | Uint16Array | Uint32Array | Uint8ClampedArray | Float32Array | Float64Array | DataView | ArrayBuffer | null, options?: ScopedCredentialOptions): Promise<ScopedCredentialInfo>;
}
interface WebGL2RenderingContextBase {
clearBufferfv(buffer: GLenum, drawbuffer: GLint, values: Iterable<GLfloat>, srcOffset?: GLuint): void;
clearBufferiv(buffer: GLenum, drawbuffer: GLint, values: Iterable<GLint>, srcOffset?: GLuint): void;
clearBufferuiv(buffer: GLenum, drawbuffer: GLint, values: Iterable<GLuint>, srcOffset?: GLuint): void;
drawBuffers(buffers: Iterable<GLenum>): void;
getActiveUniforms(program: WebGLProgram, uniformIndices: Iterable<GLuint>, pname: GLenum): any;
getUniformIndices(program: WebGLProgram, uniformNames: Iterable<string>): Iterable<GLuint> | null;
invalidateFramebuffer(target: GLenum, attachments: Iterable<GLenum>): void;
invalidateSubFramebuffer(target: GLenum, attachments: Iterable<GLenum>, x: GLint, y: GLint, width: GLsizei, height: GLsizei): void;
transformFeedbackVaryings(program: WebGLProgram, varyings: Iterable<string>, bufferMode: GLenum): void;
uniform1uiv(location: WebGLUniformLocation | null, data: Iterable<GLuint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform2uiv(location: WebGLUniformLocation | null, data: Iterable<GLuint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform3uiv(location: WebGLUniformLocation | null, data: Iterable<GLuint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform4uiv(location: WebGLUniformLocation | null, data: Iterable<GLuint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix2x3fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix2x4fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix3x2fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix3x4fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix4x2fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix4x3fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
vertexAttribI4iv(index: GLuint, values: Iterable<GLint>): void;
vertexAttribI4uiv(index: GLuint, values: Iterable<GLuint>): void;
}
interface WebGL2RenderingContextOverloads {
uniform1fv(location: WebGLUniformLocation | null, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform1iv(location: WebGLUniformLocation | null, data: Iterable<GLint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform2fv(location: WebGLUniformLocation | null, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform2iv(location: WebGLUniformLocation | null, data: Iterable<GLint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform3fv(location: WebGLUniformLocation | null, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform3iv(location: WebGLUniformLocation | null, data: Iterable<GLint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform4fv(location: WebGLUniformLocation | null, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniform4iv(location: WebGLUniformLocation | null, data: Iterable<GLint>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix2fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix3fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
uniformMatrix4fv(location: WebGLUniformLocation | null, transpose: GLboolean, data: Iterable<GLfloat>, srcOffset?: GLuint, srcLength?: GLuint): void;
}
interface WebGLRenderingContextBase {
vertexAttrib1fv(index: GLuint, values: Iterable<GLfloat>): void;
vertexAttrib2fv(index: GLuint, values: Iterable<GLfloat>): void;
vertexAttrib3fv(index: GLuint, values: Iterable<GLfloat>): void;
vertexAttrib4fv(index: GLuint, values: Iterable<GLfloat>): void;
}
interface WebGLRenderingContextOverloads {
uniform1fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
uniform1iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
uniform2fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
uniform2iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
uniform3fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
uniform3iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
uniform4fv(location: WebGLUniformLocation | null, v: Iterable<GLfloat>): void;
uniform4iv(location: WebGLUniformLocation | null, v: Iterable<GLint>): void;
uniformMatrix2fv(location: WebGLUniformLocation | null, transpose: GLboolean, value: Iterable<GLfloat>): void;
uniformMatrix3fv(location: WebGLUniformLocation | null, transpose: GLboolean, value: Iterable<GLfloat>): void;
uniformMatrix4fv(location: WebGLUniformLocation | null, transpose: GLboolean, value: Iterable<GLfloat>): void;
}

View file

@ -0,0 +1,89 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface Map<K, V> {
clear(): void;
delete(key: K): boolean;
forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
readonly size: number;
}
interface MapConstructor {
new(): Map<any, any>;
new<K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
readonly prototype: Map<any, any>;
}
declare var Map: MapConstructor;
interface ReadonlyMap<K, V> {
forEach(callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void, thisArg?: any): void;
get(key: K): V | undefined;
has(key: K): boolean;
readonly size: number;
}
interface WeakMap<K extends object, V> {
delete(key: K): boolean;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
}
interface WeakMapConstructor {
new <K extends object = object, V = any>(entries?: readonly [K, V][] | null): WeakMap<K, V>;
readonly prototype: WeakMap<object, any>;
}
declare var WeakMap: WeakMapConstructor;
interface Set<T> {
add(value: T): this;
clear(): void;
delete(value: T): boolean;
forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
has(value: T): boolean;
readonly size: number;
}
interface SetConstructor {
new <T = any>(values?: readonly T[] | null): Set<T>;
readonly prototype: Set<any>;
}
declare var Set: SetConstructor;
interface ReadonlySet<T> {
forEach(callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void, thisArg?: any): void;
has(value: T): boolean;
readonly size: number;
}
interface WeakSet<T extends object> {
add(value: T): this;
delete(value: T): boolean;
has(value: T): boolean;
}
interface WeakSetConstructor {
new <T extends object = object>(values?: readonly T[] | null): WeakSet<T>;
readonly prototype: WeakSet<object>;
}
declare var WeakSet: WeakSetConstructor;

View file

@ -0,0 +1,517 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface Array<T> {
/**
* Returns the value of the first element in the array where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found, find
* immediately returns that element value. Otherwise, find returns undefined.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find<S extends T>(predicate: (this: void, value: T, index: number, obj: T[]) => value is S, thisArg?: any): S | undefined;
find(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found,
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: T, index: number, obj: T[]) => unknown, thisArg?: any): number;
/**
* Returns the this object after filling the section identified by start and end with value
* @param value value to fill array section with
* @param start index to start filling the array at. If start is negative, it is treated as
* length+start where length is the length of the array.
* @param end index to stop filling the array at. If end is negative, it is treated as
* length+end.
*/
fill(value: T, start?: number, end?: number): this;
/**
* Returns the this object after copying a section of the array identified by start and end
* to the same array starting at position target
* @param target If target is negative, it is treated as length+target where length is the
* length of the array.
* @param start If start is negative, it is treated as length+start. If end is negative, it
* is treated as length+end.
* @param end If not specified, length of the this object is used as its default value.
*/
copyWithin(target: number, start: number, end?: number): this;
}
interface ArrayConstructor {
/**
* Creates an array from an array-like object.
* @param arrayLike An array-like object to convert to an array.
*/
from<T>(arrayLike: ArrayLike<T>): T[];
/**
* Creates an array from an iterable object.
* @param arrayLike An array-like object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(arrayLike: ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
/**
* Returns a new array from a set of elements.
* @param items A set of elements to include in the new array object.
*/
of<T>(...items: T[]): T[];
}
interface DateConstructor {
new (value: number | string | Date): Date;
}
interface Function {
/**
* Returns the name of the function. Function names are read-only and can not be changed.
*/
readonly name: string;
}
interface Math {
/**
* Returns the number of leading zero bits in the 32-bit binary representation of a number.
* @param x A numeric expression.
*/
clz32(x: number): number;
/**
* Returns the result of 32-bit multiplication of two numbers.
* @param x First number
* @param y Second number
*/
imul(x: number, y: number): number;
/**
* Returns the sign of the x, indicating whether x is positive, negative or zero.
* @param x The numeric expression to test
*/
sign(x: number): number;
/**
* Returns the base 10 logarithm of a number.
* @param x A numeric expression.
*/
log10(x: number): number;
/**
* Returns the base 2 logarithm of a number.
* @param x A numeric expression.
*/
log2(x: number): number;
/**
* Returns the natural logarithm of 1 + x.
* @param x A numeric expression.
*/
log1p(x: number): number;
/**
* Returns the result of (e^x - 1), which is an implementation-dependent approximation to
* subtracting 1 from the exponential function of x (e raised to the power of x, where e
* is the base of the natural logarithms).
* @param x A numeric expression.
*/
expm1(x: number): number;
/**
* Returns the hyperbolic cosine of a number.
* @param x A numeric expression that contains an angle measured in radians.
*/
cosh(x: number): number;
/**
* Returns the hyperbolic sine of a number.
* @param x A numeric expression that contains an angle measured in radians.
*/
sinh(x: number): number;
/**
* Returns the hyperbolic tangent of a number.
* @param x A numeric expression that contains an angle measured in radians.
*/
tanh(x: number): number;
/**
* Returns the inverse hyperbolic cosine of a number.
* @param x A numeric expression that contains an angle measured in radians.
*/
acosh(x: number): number;
/**
* Returns the inverse hyperbolic sine of a number.
* @param x A numeric expression that contains an angle measured in radians.
*/
asinh(x: number): number;
/**
* Returns the inverse hyperbolic tangent of a number.
* @param x A numeric expression that contains an angle measured in radians.
*/
atanh(x: number): number;
/**
* Returns the square root of the sum of squares of its arguments.
* @param values Values to compute the square root for.
* If no arguments are passed, the result is +0.
* If there is only one argument, the result is the absolute value.
* If any argument is +Infinity or -Infinity, the result is +Infinity.
* If any argument is NaN, the result is NaN.
* If all arguments are either +0 or 0, the result is +0.
*/
hypot(...values: number[]): number;
/**
* Returns the integral part of the a numeric expression, x, removing any fractional digits.
* If x is already an integer, the result is x.
* @param x A numeric expression.
*/
trunc(x: number): number;
/**
* Returns the nearest single precision float representation of a number.
* @param x A numeric expression.
*/
fround(x: number): number;
/**
* Returns an implementation-dependent approximation to the cube root of number.
* @param x A numeric expression.
*/
cbrt(x: number): number;
}
interface NumberConstructor {
/**
* The value of Number.EPSILON is the difference between 1 and the smallest value greater than 1
* that is representable as a Number value, which is approximately:
* 2.2204460492503130808472633361816 x 1016.
*/
readonly EPSILON: number;
/**
* Returns true if passed value is finite.
* Unlike the global isFinite, Number.isFinite doesn't forcibly convert the parameter to a
* number. Only finite values of the type number, result in true.
* @param number A numeric value.
*/
isFinite(number: unknown): boolean;
/**
* Returns true if the value passed is an integer, false otherwise.
* @param number A numeric value.
*/
isInteger(number: unknown): boolean;
/**
* Returns a Boolean value that indicates whether a value is the reserved value NaN (not a
* number). Unlike the global isNaN(), Number.isNaN() doesn't forcefully convert the parameter
* to a number. Only values of the type number, that are also NaN, result in true.
* @param number A numeric value.
*/
isNaN(number: unknown): boolean;
/**
* Returns true if the value passed is a safe integer.
* @param number A numeric value.
*/
isSafeInteger(number: unknown): boolean;
/**
* The value of the largest integer n such that n and n + 1 are both exactly representable as
* a Number value.
* The value of Number.MAX_SAFE_INTEGER is 9007199254740991 2^53 1.
*/
readonly MAX_SAFE_INTEGER: number;
/**
* The value of the smallest integer n such that n and n 1 are both exactly representable as
* a Number value.
* The value of Number.MIN_SAFE_INTEGER is 9007199254740991 ((2^53 1)).
*/
readonly MIN_SAFE_INTEGER: number;
/**
* Converts a string to a floating-point number.
* @param string A string that contains a floating-point number.
*/
parseFloat(string: string): number;
/**
* Converts A string to an integer.
* @param s A string to convert into a number.
* @param radix A value between 2 and 36 that specifies the base of the number in numString.
* If this argument is not supplied, strings with a prefix of '0x' are considered hexadecimal.
* All other strings are considered decimal.
*/
parseInt(string: string, radix?: number): number;
}
interface ObjectConstructor {
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param source The source object from which to copy properties.
*/
assign<T, U>(target: T, source: U): T & U;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param source1 The first source object from which to copy properties.
* @param source2 The second source object from which to copy properties.
*/
assign<T, U, V>(target: T, source1: U, source2: V): T & U & V;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param source1 The first source object from which to copy properties.
* @param source2 The second source object from which to copy properties.
* @param source3 The third source object from which to copy properties.
*/
assign<T, U, V, W>(target: T, source1: U, source2: V, source3: W): T & U & V & W;
/**
* Copy the values of all of the enumerable own properties from one or more source objects to a
* target object. Returns the target object.
* @param target The target object to copy to.
* @param sources One or more source objects from which to copy properties
*/
assign(target: object, ...sources: any[]): any;
/**
* Returns an array of all symbol properties found directly on object o.
* @param o Object to retrieve the symbols from.
*/
getOwnPropertySymbols(o: any): symbol[];
/**
* Returns the names of the enumerable string properties and methods of an object.
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
keys(o: {}): string[];
/**
* Returns true if the values are the same value, false otherwise.
* @param value1 The first value.
* @param value2 The second value.
*/
is(value1: any, value2: any): boolean;
/**
* Sets the prototype of a specified object o to object proto or null. Returns the object o.
* @param o The object to change its prototype.
* @param proto The value of the new prototype or null.
*/
setPrototypeOf(o: any, proto: object | null): any;
}
interface ReadonlyArray<T> {
/**
* Returns the value of the first element in the array where predicate is true, and undefined
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found, find
* immediately returns that element value. Otherwise, find returns undefined.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
find<S extends T>(predicate: (this: void, value: T, index: number, obj: readonly T[]) => value is S, thisArg?: any): S | undefined;
find(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): T | undefined;
/**
* Returns the index of the first element in the array where predicate is true, and -1
* otherwise.
* @param predicate find calls predicate once for each element of the array, in ascending
* order, until it finds one where predicate returns true. If such an element is found,
* findIndex immediately returns that element index. Otherwise, findIndex returns -1.
* @param thisArg If provided, it will be used as the this value for each invocation of
* predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: T, index: number, obj: readonly T[]) => unknown, thisArg?: any): number;
}
interface RegExp {
/**
* Returns a string indicating the flags of the regular expression in question. This field is read-only.
* The characters in this string are sequenced and concatenated in the following order:
*
* - "g" for global
* - "i" for ignoreCase
* - "m" for multiline
* - "u" for unicode
* - "y" for sticky
*
* If no flags are set, the value is the empty string.
*/
readonly flags: string;
/**
* Returns a Boolean value indicating the state of the sticky flag (y) used with a regular
* expression. Default is false. Read-only.
*/
readonly sticky: boolean;
/**
* Returns a Boolean value indicating the state of the Unicode flag (u) used with a regular
* expression. Default is false. Read-only.
*/
readonly unicode: boolean;
}
interface RegExpConstructor {
new (pattern: RegExp | string, flags?: string): RegExp;
(pattern: RegExp | string, flags?: string): RegExp;
}
interface String {
/**
* Returns a nonnegative integer Number less than 1114112 (0x110000) that is the code point
* value of the UTF-16 encoded code point starting at the string element at position pos in
* the String resulting from converting this object to a String.
* If there is no element at that position, the result is undefined.
* If a valid UTF-16 surrogate pair does not begin at pos, the result is the code unit at pos.
*/
codePointAt(pos: number): number | undefined;
/**
* Returns true if searchString appears as a substring of the result of converting this
* object to a String, at one or more positions that are
* greater than or equal to position; otherwise, returns false.
* @param searchString search string
* @param position If position is undefined, 0 is assumed, so as to search all of the String.
*/
includes(searchString: string, position?: number): boolean;
/**
* Returns true if the sequence of elements of searchString converted to a String is the
* same as the corresponding elements of this object (converted to a String) starting at
* endPosition length(this). Otherwise returns false.
*/
endsWith(searchString: string, endPosition?: number): boolean;
/**
* Returns the String value result of normalizing the string into the normalization form
* named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
* @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
* is "NFC"
*/
normalize(form: "NFC" | "NFD" | "NFKC" | "NFKD"): string;
/**
* Returns the String value result of normalizing the string into the normalization form
* named by form as specified in Unicode Standard Annex #15, Unicode Normalization Forms.
* @param form Applicable values: "NFC", "NFD", "NFKC", or "NFKD", If not specified default
* is "NFC"
*/
normalize(form?: string): string;
/**
* Returns a String value that is made from count copies appended together. If count is 0,
* the empty string is returned.
* @param count number of copies to append
*/
repeat(count: number): string;
/**
* Returns true if the sequence of elements of searchString converted to a String is the
* same as the corresponding elements of this object (converted to a String) starting at
* position. Otherwise returns false.
*/
startsWith(searchString: string, position?: number): boolean;
/**
* Returns an <a> HTML anchor element and sets the name attribute to the text value
* @param name
*/
anchor(name: string): string;
/** Returns a <big> HTML element */
big(): string;
/** Returns a <blink> HTML element */
blink(): string;
/** Returns a <b> HTML element */
bold(): string;
/** Returns a <tt> HTML element */
fixed(): string;
/** Returns a <font> HTML element and sets the color attribute value */
fontcolor(color: string): string;
/** Returns a <font> HTML element and sets the size attribute value */
fontsize(size: number): string;
/** Returns a <font> HTML element and sets the size attribute value */
fontsize(size: string): string;
/** Returns an <i> HTML element */
italics(): string;
/** Returns an <a> HTML element and sets the href attribute value */
link(url: string): string;
/** Returns a <small> HTML element */
small(): string;
/** Returns a <strike> HTML element */
strike(): string;
/** Returns a <sub> HTML element */
sub(): string;
/** Returns a <sup> HTML element */
sup(): string;
}
interface StringConstructor {
/**
* Return the String value whose elements are, in order, the elements in the List elements.
* If length is 0, the empty string is returned.
*/
fromCodePoint(...codePoints: number[]): string;
/**
* String.raw is intended for use as a tag function of a Tagged Template String. When called
* as such the first argument will be a well formed template call site object and the rest
* parameter will contain the substitution values.
* @param template A well-formed template string call site representation.
* @param substitutions A set of substitution values.
*/
raw(template: TemplateStringsArray, ...substitutions: any[]): string;
}

View file

@ -0,0 +1,30 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es5" />
/// <reference lib="es2015.core" />
/// <reference lib="es2015.collection" />
/// <reference lib="es2015.iterable" />
/// <reference lib="es2015.generator" />
/// <reference lib="es2015.promise" />
/// <reference lib="es2015.proxy" />
/// <reference lib="es2015.reflect" />
/// <reference lib="es2015.symbol" />
/// <reference lib="es2015.symbol.wellknown" />

View file

@ -0,0 +1,79 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.iterable" />
interface Generator<T = unknown, TReturn = any, TNext = unknown> extends Iterator<T, TReturn, TNext> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
return(value: TReturn): IteratorResult<T, TReturn>;
throw(e: any): IteratorResult<T, TReturn>;
[Symbol.iterator](): Generator<T, TReturn, TNext>;
}
interface GeneratorFunction {
/**
* Creates a new Generator object.
* @param args A list of arguments the function accepts.
*/
new (...args: any[]): Generator;
/**
* Creates a new Generator object.
* @param args A list of arguments the function accepts.
*/
(...args: any[]): Generator;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: Generator;
}
interface GeneratorFunctionConstructor {
/**
* Creates a new Generator function.
* @param args A list of arguments the function accepts.
*/
new (...args: string[]): GeneratorFunction;
/**
* Creates a new Generator function.
* @param args A list of arguments the function accepts.
*/
(...args: string[]): GeneratorFunction;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: GeneratorFunction;
}

View file

@ -0,0 +1,509 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.symbol" />
interface SymbolConstructor {
/**
* A method that returns the default iterator for an object. Called by the semantics of the
* for-of statement.
*/
readonly iterator: symbol;
}
interface IteratorYieldResult<TYield> {
done?: false;
value: TYield;
}
interface IteratorReturnResult<TReturn> {
done: true;
value: TReturn;
}
type IteratorResult<T, TReturn = any> = IteratorYieldResult<T> | IteratorReturnResult<TReturn>;
interface Iterator<T, TReturn = any, TNext = undefined> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): IteratorResult<T, TReturn>;
return?(value?: TReturn): IteratorResult<T, TReturn>;
throw?(e?: any): IteratorResult<T, TReturn>;
}
interface Iterable<T> {
[Symbol.iterator](): Iterator<T>;
}
interface IterableIterator<T> extends Iterator<T> {
[Symbol.iterator](): IterableIterator<T>;
}
interface Array<T> {
/** Iterator */
[Symbol.iterator](): IterableIterator<T>;
/**
* Returns an iterable of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, T]>;
/**
* Returns an iterable of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an iterable of values in the array
*/
values(): IterableIterator<T>;
}
interface ArrayConstructor {
/**
* Creates an array from an iterable object.
* @param iterable An iterable object to convert to an array.
*/
from<T>(iterable: Iterable<T> | ArrayLike<T>): T[];
/**
* Creates an array from an iterable object.
* @param iterable An iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(iterable: Iterable<T> | ArrayLike<T>, mapfn: (v: T, k: number) => U, thisArg?: any): U[];
}
interface ReadonlyArray<T> {
/** Iterator of values in the array. */
[Symbol.iterator](): IterableIterator<T>;
/**
* Returns an iterable of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, T]>;
/**
* Returns an iterable of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an iterable of values in the array
*/
values(): IterableIterator<T>;
}
interface IArguments {
/** Iterator */
[Symbol.iterator](): IterableIterator<any>;
}
interface Map<K, V> {
/** Returns an iterable of entries in the map. */
[Symbol.iterator](): IterableIterator<[K, V]>;
/**
* Returns an iterable of key, value pairs for every entry in the map.
*/
entries(): IterableIterator<[K, V]>;
/**
* Returns an iterable of keys in the map
*/
keys(): IterableIterator<K>;
/**
* Returns an iterable of values in the map
*/
values(): IterableIterator<V>;
}
interface ReadonlyMap<K, V> {
/** Returns an iterable of entries in the map. */
[Symbol.iterator](): IterableIterator<[K, V]>;
/**
* Returns an iterable of key, value pairs for every entry in the map.
*/
entries(): IterableIterator<[K, V]>;
/**
* Returns an iterable of keys in the map
*/
keys(): IterableIterator<K>;
/**
* Returns an iterable of values in the map
*/
values(): IterableIterator<V>;
}
interface MapConstructor {
new <K, V>(iterable: Iterable<readonly [K, V]>): Map<K, V>;
}
interface WeakMap<K extends object, V> { }
interface WeakMapConstructor {
new <K extends object, V>(iterable: Iterable<[K, V]>): WeakMap<K, V>;
}
interface Set<T> {
/** Iterates over values in the set. */
[Symbol.iterator](): IterableIterator<T>;
/**
* Returns an iterable of [v,v] pairs for every value `v` in the set.
*/
entries(): IterableIterator<[T, T]>;
/**
* Despite its name, returns an iterable of the values in the set,
*/
keys(): IterableIterator<T>;
/**
* Returns an iterable of values in the set.
*/
values(): IterableIterator<T>;
}
interface ReadonlySet<T> {
/** Iterates over values in the set. */
[Symbol.iterator](): IterableIterator<T>;
/**
* Returns an iterable of [v,v] pairs for every value `v` in the set.
*/
entries(): IterableIterator<[T, T]>;
/**
* Despite its name, returns an iterable of the values in the set,
*/
keys(): IterableIterator<T>;
/**
* Returns an iterable of values in the set.
*/
values(): IterableIterator<T>;
}
interface SetConstructor {
new <T>(iterable?: Iterable<T> | null): Set<T>;
}
interface WeakSet<T extends object> { }
interface WeakSetConstructor {
new <T extends object = object>(iterable: Iterable<T>): WeakSet<T>;
}
interface Promise<T> { }
interface PromiseConstructor {
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An iterable of Promises.
* @returns A new Promise.
*/
all<T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>;
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* or rejected.
* @param values An iterable of Promises.
* @returns A new Promise.
*/
race<T>(values: Iterable<T>): Promise<T extends PromiseLike<infer U> ? U : T>;
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* or rejected.
* @param values An iterable of Promises.
* @returns A new Promise.
*/
race<T>(values: Iterable<T | PromiseLike<T>>): Promise<T>;
}
declare namespace Reflect {
function enumerate(target: object): IterableIterator<any>;
}
interface String {
/** Iterator */
[Symbol.iterator](): IterableIterator<string>;
}
interface Int8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Int8ArrayConstructor {
new (elements: Iterable<number>): Int8Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int8Array;
}
interface Uint8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Uint8ArrayConstructor {
new (elements: Iterable<number>): Uint8Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8Array;
}
interface Uint8ClampedArray {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Uint8ClampedArrayConstructor {
new (elements: Iterable<number>): Uint8ClampedArray;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint8ClampedArray;
}
interface Int16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Int16ArrayConstructor {
new (elements: Iterable<number>): Int16Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int16Array;
}
interface Uint16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Uint16ArrayConstructor {
new (elements: Iterable<number>): Uint16Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint16Array;
}
interface Int32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Int32ArrayConstructor {
new (elements: Iterable<number>): Int32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Int32Array;
}
interface Uint32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Uint32ArrayConstructor {
new (elements: Iterable<number>): Uint32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Uint32Array;
}
interface Float32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Float32ArrayConstructor {
new (elements: Iterable<number>): Float32Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float32Array;
}
interface Float64Array {
[Symbol.iterator](): IterableIterator<number>;
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
}
interface Float64ArrayConstructor {
new (elements: Iterable<number>): Float64Array;
/**
* Creates an array from an array-like or iterable object.
* @param arrayLike An array-like or iterable object to convert to an array.
* @param mapfn A mapping function to call on every element of the array.
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from(arrayLike: Iterable<number>, mapfn?: (v: number, k: number) => number, thisArg?: any): Float64Array;
}

View file

@ -0,0 +1,150 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface PromiseConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: Promise<any>;
/**
* Creates a new Promise.
* @param executor A callback used to initialize the promise. This callback is passed two arguments:
* a resolve callback used to resolve the promise with a value or the result of another promise,
* and a reject callback used to reject the promise with a provided reason or error.
*/
new <T>(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>, T10 | PromiseLike<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5, T6, T7, T8, T9>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>, T9 | PromiseLike<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5, T6, T7, T8>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>, T8 | PromiseLike<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5, T6, T7>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>, T7 | PromiseLike<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5, T6>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>, T6 | PromiseLike<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4, T5>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>, T5 | PromiseLike<T5>]): Promise<[T1, T2, T3, T4, T5]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3, T4>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2, T3>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T1, T2>(values: readonly [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<T>(values: readonly (T | PromiseLike<T>)[]): Promise<T[]>;
// see: lib.es2015.iterable.d.ts
// all<T>(values: Iterable<T | PromiseLike<T>>): Promise<T[]>;
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* or rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
race<T>(values: readonly T[]): Promise<T extends PromiseLike<infer U> ? U : T>;
// see: lib.es2015.iterable.d.ts
// race<T>(values: Iterable<T>): Promise<T extends PromiseLike<infer U> ? U : T>;
/**
* Creates a new rejected promise for the provided reason.
* @param reason The reason the promise was rejected.
* @returns A new rejected Promise.
*/
reject<T = never>(reason?: any): Promise<T>;
/**
* Creates a new resolved promise for the provided value.
* @param value A promise.
* @returns A promise whose internal state matches the provided promise.
*/
resolve<T>(value: T | PromiseLike<T>): Promise<T>;
/**
* Creates a new resolved promise .
* @returns A resolved promise.
*/
resolve(): Promise<void>;
}
declare var Promise: PromiseConstructor;

View file

@ -0,0 +1,42 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface ProxyHandler<T extends object> {
getPrototypeOf? (target: T): object | null;
setPrototypeOf? (target: T, v: any): boolean;
isExtensible? (target: T): boolean;
preventExtensions? (target: T): boolean;
getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor | undefined;
has? (target: T, p: PropertyKey): boolean;
get? (target: T, p: PropertyKey, receiver: any): any;
set? (target: T, p: PropertyKey, value: any, receiver: any): boolean;
deleteProperty? (target: T, p: PropertyKey): boolean;
defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean;
enumerate? (target: T): PropertyKey[];
ownKeys? (target: T): PropertyKey[];
apply? (target: T, thisArg: any, argArray?: any): any;
construct? (target: T, argArray: any, newTarget?: any): object;
}
interface ProxyConstructor {
revocable<T extends object>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; };
new <T extends object>(target: T, handler: ProxyHandler<T>): T;
}
declare var Proxy: ProxyConstructor;

View file

@ -0,0 +1,35 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
declare namespace Reflect {
function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
function construct(target: Function, argumentsList: ArrayLike<any>, newTarget?: any): any;
function defineProperty(target: object, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
function deleteProperty(target: object, propertyKey: PropertyKey): boolean;
function get(target: object, propertyKey: PropertyKey, receiver?: any): any;
function getOwnPropertyDescriptor(target: object, propertyKey: PropertyKey): PropertyDescriptor | undefined;
function getPrototypeOf(target: object): object;
function has(target: object, propertyKey: PropertyKey): boolean;
function isExtensible(target: object): boolean;
function ownKeys(target: object): PropertyKey[];
function preventExtensions(target: object): boolean;
function set(target: object, propertyKey: PropertyKey, value: any, receiver?: any): boolean;
function setPrototypeOf(target: object, proto: any): boolean;
}

View file

@ -0,0 +1,48 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface SymbolConstructor {
/**
* A reference to the prototype.
*/
readonly prototype: Symbol;
/**
* Returns a new unique Symbol value.
* @param description Description of the new Symbol object.
*/
(description?: string | number): symbol;
/**
* Returns a Symbol object from the global symbol registry matching the given key if found.
* Otherwise, returns a new symbol with this key.
* @param key key to search for.
*/
for(key: string): symbol;
/**
* Returns a key from the global symbol registry matching the given Symbol if found.
* Otherwise, returns a undefined.
* @param sym Symbol to find the key for.
*/
keyFor(sym: symbol): string | undefined;
}
declare var Symbol: SymbolConstructor;

View file

@ -0,0 +1,319 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.symbol" />
interface SymbolConstructor {
/**
* A method that determines if a constructor object recognizes an object as one of the
* constructors instances. Called by the semantics of the instanceof operator.
*/
readonly hasInstance: symbol;
/**
* A Boolean value that if true indicates that an object should flatten to its array elements
* by Array.prototype.concat.
*/
readonly isConcatSpreadable: symbol;
/**
* A regular expression method that matches the regular expression against a string. Called
* by the String.prototype.match method.
*/
readonly match: symbol;
/**
* A regular expression method that replaces matched substrings of a string. Called by the
* String.prototype.replace method.
*/
readonly replace: symbol;
/**
* A regular expression method that returns the index within a string that matches the
* regular expression. Called by the String.prototype.search method.
*/
readonly search: symbol;
/**
* A function valued property that is the constructor function that is used to create
* derived objects.
*/
readonly species: symbol;
/**
* A regular expression method that splits a string at the indices that match the regular
* expression. Called by the String.prototype.split method.
*/
readonly split: symbol;
/**
* A method that converts an object to a corresponding primitive value.
* Called by the ToPrimitive abstract operation.
*/
readonly toPrimitive: symbol;
/**
* A String value that is used in the creation of the default string description of an object.
* Called by the built-in method Object.prototype.toString.
*/
readonly toStringTag: symbol;
/**
* An Object whose own property names are property names that are excluded from the 'with'
* environment bindings of the associated objects.
*/
readonly unscopables: symbol;
}
interface Symbol {
readonly [Symbol.toStringTag]: string;
}
interface Array<T> {
/**
* Returns an object whose properties have the value 'true'
* when they will be absent when used in a 'with' statement.
*/
[Symbol.unscopables](): {
copyWithin: boolean;
entries: boolean;
fill: boolean;
find: boolean;
findIndex: boolean;
keys: boolean;
values: boolean;
};
}
interface Date {
/**
* Converts a Date object to a string.
*/
[Symbol.toPrimitive](hint: "default"): string;
/**
* Converts a Date object to a string.
*/
[Symbol.toPrimitive](hint: "string"): string;
/**
* Converts a Date object to a number.
*/
[Symbol.toPrimitive](hint: "number"): number;
/**
* Converts a Date object to a string or number.
*
* @param hint The strings "number", "string", or "default" to specify what primitive to return.
*
* @throws {TypeError} If 'hint' was given something other than "number", "string", or "default".
* @returns A number if 'hint' was "number", a string if 'hint' was "string" or "default".
*/
[Symbol.toPrimitive](hint: string): string | number;
}
interface Map<K, V> {
readonly [Symbol.toStringTag]: string;
}
interface WeakMap<K extends object, V> {
readonly [Symbol.toStringTag]: string;
}
interface Set<T> {
readonly [Symbol.toStringTag]: string;
}
interface WeakSet<T extends object> {
readonly [Symbol.toStringTag]: string;
}
interface JSON {
readonly [Symbol.toStringTag]: string;
}
interface Function {
/**
* Determines whether the given value inherits from this function if this function was used
* as a constructor function.
*
* A constructor function can control which objects are recognized as its instances by
* 'instanceof' by overriding this method.
*/
[Symbol.hasInstance](value: any): boolean;
}
interface GeneratorFunction {
readonly [Symbol.toStringTag]: string;
}
interface Math {
readonly [Symbol.toStringTag]: string;
}
interface Promise<T> {
readonly [Symbol.toStringTag]: string;
}
interface PromiseConstructor {
readonly [Symbol.species]: PromiseConstructor;
}
interface RegExp {
/**
* Matches a string with this regular expression, and returns an array containing the results of
* that search.
* @param string A string to search within.
*/
[Symbol.match](string: string): RegExpMatchArray | null;
/**
* Replaces text in a string, using this regular expression.
* @param string A String object or string literal whose contents matching against
* this regular expression will be replaced
* @param replaceValue A String object or string literal containing the text to replace for every
* successful match of this regular expression.
*/
[Symbol.replace](string: string, replaceValue: string): string;
/**
* Replaces text in a string, using this regular expression.
* @param string A String object or string literal whose contents matching against
* this regular expression will be replaced
* @param replacer A function that returns the replacement text.
*/
[Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string;
/**
* Finds the position beginning first substring match in a regular expression search
* using this regular expression.
*
* @param string The string to search within.
*/
[Symbol.search](string: string): number;
/**
* Returns an array of substrings that were delimited by strings in the original input that
* match against this regular expression.
*
* If the regular expression contains capturing parentheses, then each time this
* regular expression matches, the results (including any undefined results) of the
* capturing parentheses are spliced.
*
* @param string string value to split
* @param limit if not undefined, the output array is truncated so that it contains no more
* than 'limit' elements.
*/
[Symbol.split](string: string, limit?: number): string[];
}
interface RegExpConstructor {
readonly [Symbol.species]: RegExpConstructor;
}
interface String {
/**
* Matches a string or an object that supports being matched against, and returns an array
* containing the results of that search, or null if no matches are found.
* @param matcher An object that supports being matched against.
*/
match(matcher: { [Symbol.match](string: string): RegExpMatchArray | null; }): RegExpMatchArray | null;
/**
* Replaces text in a string, using an object that supports replacement within a string.
* @param searchValue A object can search for and replace matches within a string.
* @param replaceValue A string containing the text to replace for every successful match of searchValue in this string.
*/
replace(searchValue: { [Symbol.replace](string: string, replaceValue: string): string; }, replaceValue: string): string;
/**
* Replaces text in a string, using an object that supports replacement within a string.
* @param searchValue A object can search for and replace matches within a string.
* @param replacer A function that returns the replacement text.
*/
replace(searchValue: { [Symbol.replace](string: string, replacer: (substring: string, ...args: any[]) => string): string; }, replacer: (substring: string, ...args: any[]) => string): string;
/**
* Finds the first substring match in a regular expression search.
* @param searcher An object which supports searching within a string.
*/
search(searcher: { [Symbol.search](string: string): number; }): number;
/**
* Split a string into substrings using the specified separator and return them as an array.
* @param splitter An object that can split a string.
* @param limit A value used to limit the number of elements returned in the array.
*/
split(splitter: { [Symbol.split](string: string, limit?: number): string[]; }, limit?: number): string[];
}
interface ArrayBuffer {
readonly [Symbol.toStringTag]: string;
}
interface DataView {
readonly [Symbol.toStringTag]: string;
}
interface Int8Array {
readonly [Symbol.toStringTag]: "Int8Array";
}
interface Uint8Array {
readonly [Symbol.toStringTag]: "Uint8Array";
}
interface Uint8ClampedArray {
readonly [Symbol.toStringTag]: "Uint8ClampedArray";
}
interface Int16Array {
readonly [Symbol.toStringTag]: "Int16Array";
}
interface Uint16Array {
readonly [Symbol.toStringTag]: "Uint16Array";
}
interface Int32Array {
readonly [Symbol.toStringTag]: "Int32Array";
}
interface Uint32Array {
readonly [Symbol.toStringTag]: "Uint32Array";
}
interface Float32Array {
readonly [Symbol.toStringTag]: "Float32Array";
}
interface Float64Array {
readonly [Symbol.toStringTag]: "Float64Array";
}
interface ArrayConstructor {
readonly [Symbol.species]: ArrayConstructor;
}
interface MapConstructor {
readonly [Symbol.species]: MapConstructor;
}
interface SetConstructor {
readonly [Symbol.species]: SetConstructor;
}
interface ArrayBufferConstructor {
readonly [Symbol.species]: ArrayBufferConstructor;
}

View file

@ -0,0 +1,118 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface Array<T> {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: T, fromIndex?: number): boolean;
}
interface ReadonlyArray<T> {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: T, fromIndex?: number): boolean;
}
interface Int8Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint8Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint8ClampedArray {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Int16Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint16Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Int32Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Uint32Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Float32Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}
interface Float64Array {
/**
* Determines whether an array includes a certain element, returning true or false as appropriate.
* @param searchElement The element to search for.
* @param fromIndex The position in this array at which to begin searching for searchElement.
*/
includes(searchElement: number, fromIndex?: number): boolean;
}

View file

@ -0,0 +1,22 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015" />
/// <reference lib="es2016.array.include" />

View file

@ -0,0 +1,25 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2016" />
/// <reference lib="dom" />
/// <reference lib="webworker.importscripts" />
/// <reference lib="scripthost" />
/// <reference lib="dom.iterable" />

View file

@ -0,0 +1,26 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2016" />
/// <reference lib="es2017.object" />
/// <reference lib="es2017.sharedmemory" />
/// <reference lib="es2017.string" />
/// <reference lib="es2017.intl" />
/// <reference lib="es2017.typedarrays" />

View file

@ -0,0 +1,25 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2017" />
/// <reference lib="dom" />
/// <reference lib="webworker.importscripts" />
/// <reference lib="scripthost" />
/// <reference lib="dom.iterable" />

View file

@ -0,0 +1,32 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
declare namespace Intl {
type DateTimeFormatPartTypes = "day" | "dayPeriod" | "era" | "hour" | "literal" | "minute" | "month" | "second" | "timeZoneName" | "weekday" | "year";
interface DateTimeFormatPart {
type: DateTimeFormatPartTypes;
value: string;
}
interface DateTimeFormat {
formatToParts(date?: Date | number): DateTimeFormatPart[];
}
}

View file

@ -0,0 +1,51 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface ObjectConstructor {
/**
* Returns an array of values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
values<T>(o: { [s: string]: T } | ArrayLike<T>): T[];
/**
* Returns an array of values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
values(o: {}): any[];
/**
* Returns an array of key/values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
/**
* Returns an array of key/values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries(o: {}): [string, any][];
/**
* Returns an object containing all own property descriptors of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
getOwnPropertyDescriptors<T>(o: T): {[P in keyof T]: TypedPropertyDescriptor<T[P]>} & { [x: string]: PropertyDescriptor };
}

View file

@ -0,0 +1,138 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.symbol" />
/// <reference lib="es2015.symbol.wellknown" />
interface SharedArrayBuffer {
/**
* Read-only. The length of the ArrayBuffer (in bytes).
*/
readonly byteLength: number;
/*
* The SharedArrayBuffer constructor's length property whose value is 1.
*/
length: number;
/**
* Returns a section of an SharedArrayBuffer.
*/
slice(begin: number, end?: number): SharedArrayBuffer;
readonly [Symbol.species]: SharedArrayBuffer;
readonly [Symbol.toStringTag]: "SharedArrayBuffer";
}
interface SharedArrayBufferConstructor {
readonly prototype: SharedArrayBuffer;
new (byteLength: number): SharedArrayBuffer;
}
declare var SharedArrayBuffer: SharedArrayBufferConstructor;
interface ArrayBufferTypes {
SharedArrayBuffer: SharedArrayBuffer;
}
interface Atomics {
/**
* Adds a value to the value at the given position in the array, returning the original value.
* Until this atomic operation completes, any other read or write operation against the array
* will block.
*/
add(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
/**
* Stores the bitwise AND of a value with the value at the given position in the array,
* returning the original value. Until this atomic operation completes, any other read or
* write operation against the array will block.
*/
and(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
/**
* Replaces the value at the given position in the array if the original value equals the given
* expected value, returning the original value. Until this atomic operation completes, any
* other read or write operation against the array will block.
*/
compareExchange(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, expectedValue: number, replacementValue: number): number;
/**
* Replaces the value at the given position in the array, returning the original value. Until
* this atomic operation completes, any other read or write operation against the array will
* block.
*/
exchange(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
/**
* Returns a value indicating whether high-performance algorithms can use atomic operations
* (`true`) or must use locks (`false`) for the given number of bytes-per-element of a typed
* array.
*/
isLockFree(size: number): boolean;
/**
* Returns the value at the given position in the array. Until this atomic operation completes,
* any other read or write operation against the array will block.
*/
load(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number): number;
/**
* Stores the bitwise OR of a value with the value at the given position in the array,
* returning the original value. Until this atomic operation completes, any other read or write
* operation against the array will block.
*/
or(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
/**
* Stores a value at the given position in the array, returning the new value. Until this
* atomic operation completes, any other read or write operation against the array will block.
*/
store(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
/**
* Subtracts a value from the value at the given position in the array, returning the original
* value. Until this atomic operation completes, any other read or write operation against the
* array will block.
*/
sub(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
/**
* If the value at the given position in the array is equal to the provided value, the current
* agent is put to sleep causing execution to suspend until the timeout expires (returning
* `"timed-out"`) or until the agent is awoken (returning `"ok"`); otherwise, returns
* `"not-equal"`.
*/
wait(typedArray: Int32Array, index: number, value: number, timeout?: number): "ok" | "not-equal" | "timed-out";
/**
* Wakes up sleeping agents that are waiting on the given index of the array, returning the
* number of agents that were awoken.
*/
notify(typedArray: Int32Array, index: number, count: number): number;
/**
* Stores the bitwise XOR of a value with the value at the given position in the array,
* returning the original value. Until this atomic operation completes, any other read or write
* operation against the array will block.
*/
xor(typedArray: Int8Array | Uint8Array | Int16Array | Uint16Array | Int32Array | Uint32Array, index: number, value: number): number;
readonly [Symbol.toStringTag]: "Atomics";
}
declare var Atomics: Atomics;

View file

@ -0,0 +1,47 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface String {
/**
* Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
* The padding is applied from the start (left) of the current string.
*
* @param maxLength The length of the resulting string once the current string has been padded.
* If this parameter is smaller than the current string's length, the current string will be returned as it is.
*
* @param fillString The string to pad the current string with.
* If this string is too long, it will be truncated and the left-most part will be applied.
* The default value for this parameter is " " (U+0020).
*/
padStart(maxLength: number, fillString?: string): string;
/**
* Pads the current string with a given string (possibly repeated) so that the resulting string reaches a given length.
* The padding is applied from the end (right) of the current string.
*
* @param maxLength The length of the resulting string once the current string has been padded.
* If this parameter is smaller than the current string's length, the current string will be returned as it is.
*
* @param fillString The string to pad the current string with.
* If this string is too long, it will be truncated and the left-most part will be applied.
* The default value for this parameter is " " (U+0020).
*/
padEnd(maxLength: number, fillString?: string): string;
}

View file

@ -0,0 +1,55 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
interface Int8ArrayConstructor {
new (): Int8Array;
}
interface Uint8ArrayConstructor {
new (): Uint8Array;
}
interface Uint8ClampedArrayConstructor {
new (): Uint8ClampedArray;
}
interface Int16ArrayConstructor {
new (): Int16Array;
}
interface Uint16ArrayConstructor {
new (): Uint16Array;
}
interface Int32ArrayConstructor {
new (): Int32Array;
}
interface Uint32ArrayConstructor {
new (): Uint32Array;
}
interface Float32ArrayConstructor {
new (): Float32Array;
}
interface Float64ArrayConstructor {
new (): Float64Array;
}

View file

@ -0,0 +1,79 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2018.asynciterable" />
interface AsyncGenerator<T = unknown, TReturn = any, TNext = unknown> extends AsyncIterator<T, TReturn, TNext> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
return(value: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
throw(e: any): Promise<IteratorResult<T, TReturn>>;
[Symbol.asyncIterator](): AsyncGenerator<T, TReturn, TNext>;
}
interface AsyncGeneratorFunction {
/**
* Creates a new AsyncGenerator object.
* @param args A list of arguments the function accepts.
*/
new (...args: any[]): AsyncGenerator;
/**
* Creates a new AsyncGenerator object.
* @param args A list of arguments the function accepts.
*/
(...args: any[]): AsyncGenerator;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: AsyncGenerator;
}
interface AsyncGeneratorFunctionConstructor {
/**
* Creates a new AsyncGenerator function.
* @param args A list of arguments the function accepts.
*/
new (...args: string[]): AsyncGeneratorFunction;
/**
* Creates a new AsyncGenerator function.
* @param args A list of arguments the function accepts.
*/
(...args: string[]): AsyncGeneratorFunction;
/**
* The length of the arguments.
*/
readonly length: number;
/**
* Returns the name of the function.
*/
readonly name: string;
/**
* A reference to the prototype.
*/
readonly prototype: AsyncGeneratorFunction;
}

View file

@ -0,0 +1,45 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
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
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
/// <reference no-default-lib="true"/>
/// <reference lib="es2015.symbol" />
/// <reference lib="es2015.iterable" />
interface SymbolConstructor {
/**
* A method that returns the default async iterator for an object. Called by the semantics of
* the for-await-of statement.
*/
readonly asyncIterator: symbol;
}
interface AsyncIterator<T, TReturn = any, TNext = undefined> {
// NOTE: 'next' is defined using a tuple to ensure we report the correct assignability errors in all places.
next(...args: [] | [TNext]): Promise<IteratorResult<T, TReturn>>;
return?(value?: TReturn | PromiseLike<TReturn>): Promise<IteratorResult<T, TReturn>>;
throw?(e?: any): Promise<IteratorResult<T, TReturn>>;
}
interface AsyncIterable<T> {
[Symbol.asyncIterator](): AsyncIterator<T>;
}
interface AsyncIterableIterator<T> extends AsyncIterator<T> {
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
}

Some files were not shown because too many files have changed in this diff Show more