mirror of
https://github.com/github/codeql-action.git
synced 2026-01-06 06:30:10 +08:00
Bump artifact dependencies if CODEQL_ACTION_ARTIFACT_V2_UPGRADE enabled (#2482)
Co-authored-by: Andrew Eisenberg <aeisenberg@github.com> Co-authored-by: Henry Mercer <henrymercer@github.com>
This commit is contained in:
9
node_modules/twirp-ts/build/protoc-gen-twirp-ts/file.d.ts
generated
vendored
Normal file
9
node_modules/twirp-ts/build/protoc-gen-twirp-ts/file.d.ts
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
import { GeneratedFile } from "@protobuf-ts/plugin-framework";
|
||||
export declare class File implements GeneratedFile {
|
||||
readonly fileName: string;
|
||||
private content;
|
||||
constructor(fileName: string);
|
||||
getFilename(): string;
|
||||
setContent(content: string): this;
|
||||
getContent(): string;
|
||||
}
|
||||
20
node_modules/twirp-ts/build/protoc-gen-twirp-ts/file.js
generated
vendored
Normal file
20
node_modules/twirp-ts/build/protoc-gen-twirp-ts/file.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.File = void 0;
|
||||
class File {
|
||||
constructor(fileName) {
|
||||
this.fileName = fileName;
|
||||
this.content = "";
|
||||
}
|
||||
getFilename() {
|
||||
return this.fileName;
|
||||
}
|
||||
setContent(content) {
|
||||
this.content = content;
|
||||
return this;
|
||||
}
|
||||
getContent() {
|
||||
return this.content;
|
||||
}
|
||||
}
|
||||
exports.File = File;
|
||||
30
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/gateway.d.ts
generated
vendored
Normal file
30
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/gateway.d.ts
generated
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
import { FileDescriptorProto } from "@protobuf-ts/plugin-framework";
|
||||
import { MatchFunction } from "path-to-regexp";
|
||||
export declare enum Pattern {
|
||||
POST = "post",
|
||||
GET = "get",
|
||||
PATCH = "patch",
|
||||
PUT = "put",
|
||||
DELETE = "delete"
|
||||
}
|
||||
export interface HttpRoute {
|
||||
serviceName: string;
|
||||
methodName: string;
|
||||
packageName: string;
|
||||
matchingPath: string;
|
||||
matcher: MatchFunction;
|
||||
httpMethod: Pattern;
|
||||
bodyKey?: string;
|
||||
responseBodyKey?: string;
|
||||
additionalBindings?: HttpRoute;
|
||||
}
|
||||
export declare type HttpRulePattern = {
|
||||
[key in Pattern]: string;
|
||||
};
|
||||
export interface HttpOption extends HttpRulePattern {
|
||||
body: string;
|
||||
responseBody: string;
|
||||
additional_bindings: HttpOption;
|
||||
}
|
||||
export declare function genGateway(ctx: any, files: readonly FileDescriptorProto[]): Promise<string>;
|
||||
export declare function getMethod(httpSpec: HttpOption): Pattern;
|
||||
113
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/gateway.js
generated
vendored
Normal file
113
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/gateway.js
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMethod = exports.genGateway = exports.Pattern = void 0;
|
||||
const fs_1 = require("fs");
|
||||
const ts_poet_1 = require("ts-poet");
|
||||
const path_to_regexp_1 = require("path-to-regexp");
|
||||
const Gateway = ts_poet_1.imp("Gateway@twirp-ts");
|
||||
const GatewayPattern = ts_poet_1.imp("Pattern@twirp-ts");
|
||||
const pathToRegexpMatch = ts_poet_1.imp("match@path-to-regexp");
|
||||
const debug = (content) => fs_1.writeFileSync(__dirname + "/debug.json", JSON.stringify(content, null, 2), "utf-8");
|
||||
var Pattern;
|
||||
(function (Pattern) {
|
||||
Pattern["POST"] = "post";
|
||||
Pattern["GET"] = "get";
|
||||
Pattern["PATCH"] = "patch";
|
||||
Pattern["PUT"] = "put";
|
||||
Pattern["DELETE"] = "delete";
|
||||
})(Pattern = exports.Pattern || (exports.Pattern = {}));
|
||||
function genGateway(ctx, files) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const httpRoutes = files.reduce((all, current) => {
|
||||
current.service.forEach(service => {
|
||||
service.method.forEach((method) => {
|
||||
const options = ctx.interpreter.readOptions(method);
|
||||
if (options && options["google.api.http"]) {
|
||||
const httpSpec = options["google.api.http"];
|
||||
all.push(parseHttpOption(httpSpec, current.package || "", method.name, service.name));
|
||||
if (httpSpec.additional_bindings) {
|
||||
all.push(parseHttpOption(httpSpec.additional_bindings, current.package || "", method.name, service.name));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return all;
|
||||
}, []);
|
||||
return genGatewayHandler(httpRoutes).toStringWithImports();
|
||||
});
|
||||
}
|
||||
exports.genGateway = genGateway;
|
||||
function genGatewayHandler(httpRoute) {
|
||||
const genRoutes = (method) => httpRoute.filter(route => route.httpMethod === method).map(route => {
|
||||
return ts_poet_1.code `
|
||||
{
|
||||
packageName: "${route.packageName}",
|
||||
methodName: "${route.methodName}",
|
||||
serviceName: "${route.serviceName}",
|
||||
httpMethod: "${route.httpMethod}" as ${GatewayPattern},
|
||||
matchingPath: "${route.matchingPath}{:query_string(\\\\?.*)}?",
|
||||
matcher: ${pathToRegexpMatch}("${route.matchingPath}{:query_string(\\\\?.*)}?"),
|
||||
bodyKey: "${route.bodyKey || ""}",
|
||||
responseBodyKey: "${route.responseBodyKey || ""}",
|
||||
},
|
||||
`;
|
||||
});
|
||||
return ts_poet_1.code `
|
||||
export function createGateway() {
|
||||
return new ${Gateway}({
|
||||
post: [${ts_poet_1.joinCode(genRoutes(Pattern.POST), { on: "\n" })}],
|
||||
get: [${ts_poet_1.joinCode(genRoutes(Pattern.GET), { on: "\n" })}],
|
||||
put: [${ts_poet_1.joinCode(genRoutes(Pattern.PUT), { on: "\n" })}],
|
||||
patch: [${ts_poet_1.joinCode(genRoutes(Pattern.PATCH), { on: "\n" })}],
|
||||
delete: [${ts_poet_1.joinCode(genRoutes(Pattern.DELETE), { on: "\n" })}],
|
||||
})
|
||||
}
|
||||
`;
|
||||
}
|
||||
function parseHttpOption(httpOption, packageName, methodName, serviceName) {
|
||||
const httpMethod = getMethod(httpOption);
|
||||
const matchingUrl = httpOption[httpMethod];
|
||||
const matchingPath = matcher(matchingUrl);
|
||||
const httpRoute = {
|
||||
packageName,
|
||||
methodName,
|
||||
serviceName,
|
||||
httpMethod: httpMethod,
|
||||
matchingPath,
|
||||
matcher: path_to_regexp_1.match(matchingPath),
|
||||
bodyKey: httpOption.body,
|
||||
responseBodyKey: httpOption.responseBody,
|
||||
};
|
||||
return httpRoute;
|
||||
}
|
||||
function matcher(url) {
|
||||
return url.split("/").map((urlSegment) => {
|
||||
const matchURLParams = /{([0-9a-zA-Z_-]+)}/.exec(urlSegment);
|
||||
if (matchURLParams && matchURLParams.length > 0) {
|
||||
const paramName = matchURLParams[1];
|
||||
return "{:" + paramName + "}";
|
||||
}
|
||||
else {
|
||||
return urlSegment;
|
||||
}
|
||||
}).join("/");
|
||||
}
|
||||
function getMethod(httpSpec) {
|
||||
const possibleMethods = ["post", "get", "patch", "put", "delete"];
|
||||
for (const method of possibleMethods) {
|
||||
if (method in httpSpec) {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
throw new Error(`HTTP method not found`);
|
||||
}
|
||||
exports.getMethod = getMethod;
|
||||
3
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/index-file.d.ts
generated
vendored
Normal file
3
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/index-file.d.ts
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { DescriptorRegistry } from "@protobuf-ts/plugin-framework";
|
||||
import { File } from "../file";
|
||||
export declare function genIndexFile(registry: DescriptorRegistry, files: File[]): File;
|
||||
29
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/index-file.js
generated
vendored
Normal file
29
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/index-file.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.genIndexFile = void 0;
|
||||
const file_1 = require("../file");
|
||||
function genIndexFile(registry, files) {
|
||||
const fileToExport = registry.allFiles()
|
||||
.filter((fileDescriptor) => {
|
||||
let hasExports = false;
|
||||
registry.visitTypes(fileDescriptor, descriptor => {
|
||||
// we are not interested in synthetic types like map entry messages
|
||||
if (registry.isSyntheticElement(descriptor))
|
||||
return;
|
||||
hasExports = true;
|
||||
});
|
||||
return hasExports;
|
||||
})
|
||||
.map((file => { var _a; return (_a = file.name) === null || _a === void 0 ? void 0 : _a.replace(".proto", ""); }));
|
||||
const compiledFiles = files.filter(file => file.getContent() !== "").map(file => {
|
||||
return file.fileName.replace(".ts", "");
|
||||
});
|
||||
if (compiledFiles.length > 0) {
|
||||
fileToExport.push(...compiledFiles);
|
||||
}
|
||||
const indexFile = new file_1.File('index.ts');
|
||||
return indexFile.setContent(fileToExport.map((fileName) => {
|
||||
return `export * from "./${fileName}";`;
|
||||
}).join("\n"));
|
||||
}
|
||||
exports.genIndexFile = genIndexFile;
|
||||
17
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/open-api.d.ts
generated
vendored
Normal file
17
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/open-api.d.ts
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import { FileDescriptorProto } from "@protobuf-ts/plugin-framework";
|
||||
interface OpenAPIDoc {
|
||||
fileName: string;
|
||||
content: string;
|
||||
}
|
||||
export declare enum OpenAPIType {
|
||||
GATEWAY = 0,
|
||||
TWIRP = 1
|
||||
}
|
||||
/**
|
||||
* Generate twirp compliant OpenAPI doc
|
||||
* @param ctx
|
||||
* @param files
|
||||
* @param type
|
||||
*/
|
||||
export declare function genOpenAPI(ctx: any, files: readonly FileDescriptorProto[], type: OpenAPIType): Promise<OpenAPIDoc[]>;
|
||||
export {};
|
||||
580
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/open-api.js
generated
vendored
Normal file
580
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/open-api.js
generated
vendored
Normal file
@@ -0,0 +1,580 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.genOpenAPI = exports.OpenAPIType = void 0;
|
||||
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
|
||||
const yaml = __importStar(require("yaml"));
|
||||
const local_type_name_1 = require("../local-type-name");
|
||||
const gateway_1 = require("./gateway");
|
||||
var OpenAPIType;
|
||||
(function (OpenAPIType) {
|
||||
OpenAPIType[OpenAPIType["GATEWAY"] = 0] = "GATEWAY";
|
||||
OpenAPIType[OpenAPIType["TWIRP"] = 1] = "TWIRP";
|
||||
})(OpenAPIType = exports.OpenAPIType || (exports.OpenAPIType = {}));
|
||||
/**
|
||||
* Generate twirp compliant OpenAPI doc
|
||||
* @param ctx
|
||||
* @param files
|
||||
* @param type
|
||||
*/
|
||||
function genOpenAPI(ctx, files, type) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const documents = [];
|
||||
files.forEach(file => {
|
||||
file.service.forEach((service) => {
|
||||
var _a, _b;
|
||||
const document = {
|
||||
openapi: "3.0.3",
|
||||
info: {
|
||||
title: `${service.name}`,
|
||||
version: "1.0.0",
|
||||
description: genDescription(ctx, service),
|
||||
},
|
||||
paths: type === OpenAPIType.TWIRP ?
|
||||
genTwirpPaths(ctx, file, service) :
|
||||
genGatewayPaths(ctx, file, service),
|
||||
components: genComponents(ctx, service.method),
|
||||
};
|
||||
const fileName = type === OpenAPIType.TWIRP ?
|
||||
`${(_a = service.name) === null || _a === void 0 ? void 0 : _a.toLowerCase()}.twirp.openapi.yaml` :
|
||||
`${(_b = service.name) === null || _b === void 0 ? void 0 : _b.toLowerCase()}.openapi.yaml`;
|
||||
documents.push({
|
||||
fileName,
|
||||
content: yaml.stringify(document),
|
||||
});
|
||||
});
|
||||
});
|
||||
return documents;
|
||||
});
|
||||
}
|
||||
exports.genOpenAPI = genOpenAPI;
|
||||
/**
|
||||
* Generates OpenAPI Twirp URI paths
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genTwirpPaths(ctx, file, service) {
|
||||
return service.method.reduce((paths, method) => {
|
||||
const description = genDescription(ctx, method);
|
||||
paths[`/${file.package ? file.package + "." : ""}${service.name}/${method.name}`] = {
|
||||
post: {
|
||||
summary: description,
|
||||
operationId: `${service.name}_${method.name}`,
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
$ref: genRef(ctx, method.inputType)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
responses: {
|
||||
"200": {
|
||||
description: "OK",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
$ref: genRef(ctx, method.outputType),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return paths;
|
||||
}, {});
|
||||
}
|
||||
/**
|
||||
* Generates OpenAPI Twrip Gateway URI paths
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genGatewayPaths(ctx, file, service) {
|
||||
const registry = ctx.registry;
|
||||
/**
|
||||
* Build paths recursively
|
||||
* @param method
|
||||
* @param httpSpec
|
||||
* @param paths
|
||||
*/
|
||||
function buildPath(method, httpSpec, paths) {
|
||||
const httpMethod = gateway_1.getMethod(httpSpec);
|
||||
const description = genDescription(ctx, method);
|
||||
const pathItem = {
|
||||
[httpMethod]: {
|
||||
summary: description,
|
||||
operationId: `${service.name}_${method.name}`,
|
||||
}
|
||||
};
|
||||
const inputMessage = registry.resolveTypeName(method.inputType);
|
||||
const outPutMessage = registry.resolveTypeName(method.outputType);
|
||||
// All methods except GET have body
|
||||
if (httpMethod !== gateway_1.Pattern.GET) {
|
||||
pathItem[httpMethod].requestBody = genGatewayBody(ctx, httpSpec, inputMessage);
|
||||
}
|
||||
// All methods might have params
|
||||
pathItem[httpMethod].parameters = genGatewayParams(ctx, httpSpec, inputMessage);
|
||||
pathItem[httpMethod].responses = genGatewayResponse(ctx, httpSpec, outPutMessage);
|
||||
paths[`${httpSpec[httpMethod]}`] = pathItem;
|
||||
if (httpSpec.additional_bindings) {
|
||||
buildPath(method, httpSpec.additional_bindings, paths);
|
||||
}
|
||||
}
|
||||
return service.method.reduce((paths, method) => {
|
||||
const options = ctx.interpreter.readOptions(method);
|
||||
if (!options || options && !options["google.api.http"]) {
|
||||
return paths;
|
||||
}
|
||||
const httpSpec = options["google.api.http"];
|
||||
buildPath(method, httpSpec, paths);
|
||||
return paths;
|
||||
}, {});
|
||||
}
|
||||
/**
|
||||
* Generate OpenAPI Gateway Response
|
||||
* @param ctx
|
||||
* @param httpOptions
|
||||
* @param message
|
||||
*/
|
||||
function genGatewayResponse(ctx, httpOptions, message) {
|
||||
let schema = {};
|
||||
if (httpOptions.responseBody) {
|
||||
schema = {
|
||||
type: "object",
|
||||
properties: {
|
||||
[httpOptions.responseBody]: {
|
||||
$ref: `#/components/schemas/${message.name}`
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
schema = {
|
||||
$ref: `#/components/schemas/${message.name}`
|
||||
};
|
||||
}
|
||||
return {
|
||||
"200": {
|
||||
description: "OK",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Generate OpenAPI Gateway Response
|
||||
* @param ctx
|
||||
* @param httpOptions
|
||||
* @param message
|
||||
*/
|
||||
function genGatewayBody(ctx, httpOptions, message) {
|
||||
const schema = {};
|
||||
if (httpOptions.body === "*") {
|
||||
schema.$ref = `#/components/schemas/${message.name}`;
|
||||
}
|
||||
else if (httpOptions.body) {
|
||||
const subField = message.field.find(field => field.name === httpOptions.body);
|
||||
if (!subField) {
|
||||
throw new Error(`the body field ${httpOptions.body} cannot be mapped to message ${message.name}`);
|
||||
}
|
||||
schema.properties = {
|
||||
[httpOptions.body]: genField(ctx, subField),
|
||||
};
|
||||
}
|
||||
return {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
schema,
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Generates OpenAPI Gateway Parameters
|
||||
* @param ctx
|
||||
* @param httpOptions
|
||||
* @param message
|
||||
*/
|
||||
function genGatewayParams(ctx, httpOptions, message) {
|
||||
const httpMethod = gateway_1.getMethod(httpOptions);
|
||||
const params = parseUriParams(httpOptions[httpMethod]);
|
||||
const urlParams = message.field
|
||||
.filter((field) => params.find((param) => param === field.name))
|
||||
.map((field) => {
|
||||
return {
|
||||
name: field.name,
|
||||
in: "path",
|
||||
required: true,
|
||||
schema: Object.assign({}, genField(ctx, field))
|
||||
};
|
||||
});
|
||||
if (httpOptions.body === "*") {
|
||||
return urlParams;
|
||||
}
|
||||
const queryString = message.field
|
||||
.filter((field) => field.name !== httpOptions.body &&
|
||||
!params.find(param => param === field.name))
|
||||
.map((field) => {
|
||||
return {
|
||||
name: field.name,
|
||||
in: "query",
|
||||
schema: Object.assign({}, genField(ctx, field))
|
||||
};
|
||||
});
|
||||
return [
|
||||
...queryString,
|
||||
...urlParams,
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Generates OpenAPI Components
|
||||
* @param ctx
|
||||
* @param methods
|
||||
*/
|
||||
function genComponents(ctx, methods) {
|
||||
const components = {
|
||||
schemas: {}
|
||||
};
|
||||
methods.reduce((schemas, method) => {
|
||||
genSchema(ctx, schemas, method.inputType);
|
||||
genSchema(ctx, schemas, method.outputType);
|
||||
return schemas;
|
||||
}, components.schemas);
|
||||
return components;
|
||||
}
|
||||
/**
|
||||
* Generate OpenAPI Schemas
|
||||
* @param ctx
|
||||
* @param schemas
|
||||
* @param typeName
|
||||
*/
|
||||
function genSchema(ctx, schemas, typeName) {
|
||||
const registry = ctx.registry;
|
||||
const localName = localMessageName(ctx, typeName);
|
||||
if (!localName) {
|
||||
return;
|
||||
}
|
||||
const descriptor = registry.resolveTypeName(typeName);
|
||||
if (schemas[localName]) {
|
||||
return;
|
||||
}
|
||||
// Handle OneOf
|
||||
if (descriptor.field.some((field) => registry.isUserDeclaredOneof(field))) {
|
||||
schemas[localName] = genOneOfType(ctx, descriptor);
|
||||
descriptor.oneofDecl.forEach((oneOfField, index) => {
|
||||
const oneOfTyName = `${localName}_${capitalizeFirstLetter(oneOfField.name)}`;
|
||||
const oneOfFields = descriptor.field.filter(field => {
|
||||
return field.oneofIndex === index;
|
||||
});
|
||||
schemas[oneOfTyName] = genOneOfTypeKind(ctx, descriptor, oneOfFields);
|
||||
});
|
||||
}
|
||||
else {
|
||||
schemas[localName] = genType(ctx, descriptor);
|
||||
}
|
||||
descriptor.field.forEach((field) => {
|
||||
if (field.type !== plugin_framework_1.FieldDescriptorProto_Type.MESSAGE || !registry.isMapField(field)) {
|
||||
return;
|
||||
}
|
||||
if (registry.isMapField(field)) {
|
||||
const entry = registry.resolveTypeName(field.typeName);
|
||||
if (plugin_framework_1.DescriptorProto.is(entry)) {
|
||||
const valueField = entry.field.find(fd => fd.number === 2);
|
||||
if (!valueField) {
|
||||
return;
|
||||
}
|
||||
if (valueField.type !== plugin_framework_1.FieldDescriptorProto_Type.MESSAGE) {
|
||||
return;
|
||||
}
|
||||
field = valueField;
|
||||
}
|
||||
}
|
||||
else if (registry.isSyntheticElement(descriptor)) {
|
||||
return;
|
||||
}
|
||||
genSchema(ctx, schemas, field.typeName);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Generate an OpenAPI type
|
||||
* @param ctx
|
||||
* @param message
|
||||
*/
|
||||
function genType(ctx, message) {
|
||||
const description = genDescription(ctx, message);
|
||||
return {
|
||||
properties: genMessageProperties(ctx, message),
|
||||
description,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Generate a Protobuf to OpenAPI oneof type
|
||||
* @param ctx
|
||||
* @param message
|
||||
*/
|
||||
function genOneOfType(ctx, message) {
|
||||
const description = genDescription(ctx, message);
|
||||
const oneOf = {
|
||||
allOf: [
|
||||
{
|
||||
type: "object",
|
||||
properties: genMessageProperties(ctx, message),
|
||||
},
|
||||
],
|
||||
description,
|
||||
};
|
||||
message.oneofDecl.forEach((field) => {
|
||||
oneOf.allOf.push({
|
||||
$ref: `#/components/schemas/${message.name}_${capitalizeFirstLetter(field.name)}`
|
||||
});
|
||||
});
|
||||
return oneOf;
|
||||
}
|
||||
/**
|
||||
* Generate one of type
|
||||
* @param ctx
|
||||
* @param message
|
||||
* @param oneOfFields
|
||||
*/
|
||||
function genOneOfTypeKind(ctx, message, oneOfFields) {
|
||||
return {
|
||||
oneOf: oneOfFields.map((oneOf) => {
|
||||
return {
|
||||
type: "object",
|
||||
properties: {
|
||||
[oneOf.name]: genField(ctx, oneOf),
|
||||
}
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Generate message properties
|
||||
* @param ctx
|
||||
* @param message
|
||||
*/
|
||||
function genMessageProperties(ctx, message) {
|
||||
const registry = ctx.registry;
|
||||
return message.field.reduce((fields, field) => {
|
||||
if (registry.isUserDeclaredOneof(field)) {
|
||||
return fields;
|
||||
}
|
||||
fields[field.name] = genField(ctx, field);
|
||||
return fields;
|
||||
}, {});
|
||||
}
|
||||
/**
|
||||
* Generates OpenAPI $ref
|
||||
* @param ctx
|
||||
* @param name
|
||||
*/
|
||||
function genRef(ctx, name) {
|
||||
const messageType = localMessageName(ctx, name);
|
||||
return `#/components/schemas/${messageType}`;
|
||||
}
|
||||
/**
|
||||
* Generate field definition
|
||||
* @param ctx
|
||||
* @param field
|
||||
*/
|
||||
function genField(ctx, field) {
|
||||
let openApiType;
|
||||
const registry = ctx.registry;
|
||||
switch (field.type) {
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.DOUBLE:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.FLOAT:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.BOOL:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.STRING:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.FIXED32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.FIXED64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.INT32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.INT64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SFIXED32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SFIXED64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SINT32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SINT64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.UINT32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.UINT64:
|
||||
openApiType = {
|
||||
type: genScalar(field.type),
|
||||
};
|
||||
break;
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.BYTES:
|
||||
openApiType = {
|
||||
type: "array",
|
||||
items: {
|
||||
type: "integer",
|
||||
}
|
||||
};
|
||||
break;
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.ENUM:
|
||||
const enumType = registry.getEnumFieldEnum(field);
|
||||
openApiType = genEnum(enumType);
|
||||
break;
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.MESSAGE:
|
||||
// Map type
|
||||
if (registry.isMapField(field)) {
|
||||
const mapTypeValue = registry.getMapValueType(field);
|
||||
if (typeof mapTypeValue === "number") {
|
||||
const scalar = mapTypeValue;
|
||||
openApiType = {
|
||||
type: "object",
|
||||
additionalProperties: {
|
||||
type: genScalar(scalar)
|
||||
}
|
||||
};
|
||||
}
|
||||
else if (plugin_framework_1.EnumDescriptorProto.is(mapTypeValue)) {
|
||||
openApiType = {
|
||||
type: "object",
|
||||
additionalProperties: Object.assign({}, genEnum(mapTypeValue))
|
||||
};
|
||||
}
|
||||
else if (plugin_framework_1.DescriptorProto.is(mapTypeValue)) {
|
||||
openApiType = {
|
||||
type: "object",
|
||||
additionalProperties: {
|
||||
$ref: `#/components/schemas/${mapTypeValue.name}`,
|
||||
}
|
||||
};
|
||||
}
|
||||
else {
|
||||
throw new Error("map value not supported");
|
||||
}
|
||||
break;
|
||||
}
|
||||
openApiType = {
|
||||
$ref: genRef(ctx, field.typeName),
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw new Error(`${field.name} of type ${field.type} not supported`);
|
||||
}
|
||||
const description = genDescription(ctx, field);
|
||||
if (field.label === plugin_framework_1.FieldDescriptorProto_Label.REPEATED && !registry.isMapField(field)) {
|
||||
return {
|
||||
type: "array",
|
||||
items: openApiType,
|
||||
description: description || "",
|
||||
};
|
||||
}
|
||||
if (field.type !== plugin_framework_1.FieldDescriptorProto_Type.MESSAGE) {
|
||||
openApiType.description = description || "";
|
||||
}
|
||||
return openApiType;
|
||||
}
|
||||
/**
|
||||
* Generates enum definition
|
||||
* @param enumType
|
||||
*/
|
||||
function genEnum(enumType) {
|
||||
return {
|
||||
type: 'string',
|
||||
enum: enumType.value.map((value) => {
|
||||
return value.name;
|
||||
})
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Generate scalar
|
||||
* @param type
|
||||
*/
|
||||
function genScalar(type) {
|
||||
switch (type) {
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.BOOL:
|
||||
return "boolean";
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.DOUBLE:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.FLOAT:
|
||||
return "number";
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.STRING:
|
||||
return "string";
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.FIXED32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.FIXED64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.INT32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.INT64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SFIXED32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SFIXED64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SINT32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.SINT64:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.UINT32:
|
||||
case plugin_framework_1.FieldDescriptorProto_Type.UINT64:
|
||||
return "integer";
|
||||
default:
|
||||
throw new Error(`${type} is not a scalar value`);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Generates the description
|
||||
* @param ctx
|
||||
* @param descriptor
|
||||
*/
|
||||
function genDescription(ctx, descriptor) {
|
||||
const registry = ctx.registry;
|
||||
const source = registry.sourceCodeComments(descriptor);
|
||||
const description = source.leading || source.trailing || "";
|
||||
return description.trim();
|
||||
}
|
||||
/**
|
||||
* Format protobuf name
|
||||
* @param ctx
|
||||
* @param name
|
||||
*/
|
||||
function localMessageName(ctx, name) {
|
||||
const registry = ctx.registry;
|
||||
const symbols = ctx.symbols;
|
||||
const entry = symbols.find(registry.resolveTypeName(name));
|
||||
if (!entry) {
|
||||
return "";
|
||||
}
|
||||
return local_type_name_1.createLocalTypeName(entry.descriptor, registry);
|
||||
}
|
||||
function parseUriParams(uri) {
|
||||
return getMatches(uri, /{([a-zA-Z_0-9]+)}/g, 1);
|
||||
}
|
||||
function getMatches(str, regex, index = 1) {
|
||||
const matches = [];
|
||||
let match;
|
||||
while (match = regex.exec(str)) {
|
||||
matches.push(match[index]);
|
||||
}
|
||||
return matches;
|
||||
}
|
||||
function capitalizeFirstLetter(str) {
|
||||
return str.charAt(0).toUpperCase() + str.slice(1);
|
||||
}
|
||||
20
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/twirp.d.ts
generated
vendored
Normal file
20
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/twirp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import { FileDescriptorProto } from "@protobuf-ts/plugin-framework";
|
||||
/**
|
||||
* Generates the client and server implementation of the twirp
|
||||
* specification.
|
||||
* @param ctx
|
||||
* @param file
|
||||
*/
|
||||
export declare function generateTwirp(ctx: any, file: FileDescriptorProto): Promise<string>;
|
||||
/**
|
||||
* Generates the client implementation of the twirp specification.
|
||||
* @param ctx
|
||||
* @param file
|
||||
*/
|
||||
export declare function generateTwirpClient(ctx: any, file: FileDescriptorProto): Promise<string>;
|
||||
/**
|
||||
* Generates the server implementation of the twirp specification.
|
||||
* @param ctx
|
||||
* @param file
|
||||
*/
|
||||
export declare function generateTwirpServer(ctx: any, file: FileDescriptorProto): Promise<string>;
|
||||
448
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/twirp.js
generated
vendored
Normal file
448
node_modules/twirp-ts/build/protoc-gen-twirp-ts/gen/twirp.js
generated
vendored
Normal file
@@ -0,0 +1,448 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.generateTwirpServer = exports.generateTwirpClient = exports.generateTwirp = void 0;
|
||||
const ts_poet_1 = require("ts-poet");
|
||||
const camel_case_1 = require("camel-case");
|
||||
const local_type_name_1 = require("../local-type-name");
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const TwirpServer = ts_poet_1.imp("TwirpServer@twirp-ts");
|
||||
const Interceptor = ts_poet_1.imp("Interceptor@twirp-ts");
|
||||
const RouterEvents = ts_poet_1.imp("RouterEvents@twirp-ts");
|
||||
const chainInterceptors = ts_poet_1.imp("chainInterceptors@twirp-ts");
|
||||
const TwirpContentType = ts_poet_1.imp("TwirpContentType@twirp-ts");
|
||||
const TwirpContext = ts_poet_1.imp("TwirpContext@twirp-ts");
|
||||
const TwirpError = ts_poet_1.imp("TwirpError@twirp-ts");
|
||||
const TwirpErrorCode = ts_poet_1.imp("TwirpErrorCode@twirp-ts");
|
||||
/**
|
||||
* Generates the client and server implementation of the twirp
|
||||
* specification.
|
||||
* @param ctx
|
||||
* @param file
|
||||
*/
|
||||
function generateTwirp(ctx, file) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const contents = file.service.map((service) => {
|
||||
return ts_poet_1.joinCode([
|
||||
genClient(ctx, file, service),
|
||||
genServer(ctx, file, service),
|
||||
], { on: "\n\n" });
|
||||
});
|
||||
return ts_poet_1.joinCode(contents, { on: "\n\n" }).toStringWithImports();
|
||||
});
|
||||
}
|
||||
exports.generateTwirp = generateTwirp;
|
||||
/**
|
||||
* Generates the client implementation of the twirp specification.
|
||||
* @param ctx
|
||||
* @param file
|
||||
*/
|
||||
function generateTwirpClient(ctx, file) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const contents = file.service.map((service) => {
|
||||
return ts_poet_1.joinCode([genClient(ctx, file, service)], { on: "\n\n" });
|
||||
});
|
||||
return ts_poet_1.joinCode(contents, { on: "\n\n" }).toStringWithImports();
|
||||
});
|
||||
}
|
||||
exports.generateTwirpClient = generateTwirpClient;
|
||||
/**
|
||||
* Generates the server implementation of the twirp specification.
|
||||
* @param ctx
|
||||
* @param file
|
||||
*/
|
||||
function generateTwirpServer(ctx, file) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const contents = file.service.map((service) => {
|
||||
return ts_poet_1.joinCode([genServer(ctx, file, service)], { on: "\n\n" });
|
||||
});
|
||||
return ts_poet_1.joinCode(contents, { on: "\n\n" }).toStringWithImports();
|
||||
});
|
||||
}
|
||||
exports.generateTwirpServer = generateTwirpServer;
|
||||
function genClient(ctx, file, service) {
|
||||
return ts_poet_1.code `
|
||||
//==================================//
|
||||
// Client Code //
|
||||
//==================================//
|
||||
|
||||
interface Rpc {
|
||||
request(
|
||||
service: string,
|
||||
method: string,
|
||||
contentType: "application/json" | "application/protobuf",
|
||||
data: object | Uint8Array,
|
||||
): Promise<object | Uint8Array>;
|
||||
}
|
||||
|
||||
${genTwirpClientInterface(ctx, file, service)}
|
||||
|
||||
${genTwripClientJSONImpl(ctx, file, service)}
|
||||
${genTwripClientProtobufImpl(ctx, file, service)}
|
||||
`;
|
||||
}
|
||||
function genTwirpClientInterface(ctx, file, service) {
|
||||
const methods = service.method.map((method) => {
|
||||
return ts_poet_1.code `
|
||||
${formatMethodName(ctx, method.name)}(request: ${relativeMessageName(ctx, file, method.inputType)}): Promise<${relativeMessageName(ctx, file, method.outputType)}>
|
||||
`;
|
||||
});
|
||||
return ts_poet_1.code `
|
||||
export interface ${service.name}Client {
|
||||
${ts_poet_1.joinCode(methods, { on: "\n" })}
|
||||
}
|
||||
`;
|
||||
}
|
||||
/**
|
||||
* Generates the json client
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genTwripClientJSONImpl(ctx, file, service) {
|
||||
const methods = service.method.map((method) => {
|
||||
return ts_poet_1.code `
|
||||
${formatMethodName(ctx, method.name)}(request: ${relativeMessageName(ctx, file, method.inputType)}): Promise<${relativeMessageName(ctx, file, method.outputType)}> {
|
||||
const data = ${relativeMessageName(ctx, file, method.inputType)}.${encodeJSON(ctx, "request")};
|
||||
const promise = this.rpc.request(
|
||||
"${file.package ? file.package + "." : ""}${service.name}",
|
||||
"${formatMethodName(ctx, method.name)}",
|
||||
"application/json",
|
||||
data as object,
|
||||
);
|
||||
return promise.then((data) => ${relativeMessageName(ctx, file, method.outputType)}.${decodeJSON(ctx, "data as any")});
|
||||
}
|
||||
`;
|
||||
});
|
||||
const bindings = service.method.map((method) => {
|
||||
return ts_poet_1.code `
|
||||
this.${formatMethodName(ctx, method.name)}.bind(this);
|
||||
`;
|
||||
});
|
||||
return ts_poet_1.code `
|
||||
export class ${service.name}ClientJSON implements ${service.name}Client {
|
||||
private readonly rpc: Rpc;
|
||||
constructor(rpc: Rpc) {
|
||||
this.rpc = rpc;
|
||||
${ts_poet_1.joinCode(bindings, { on: `\n` })}
|
||||
}
|
||||
${ts_poet_1.joinCode(methods, { on: `\n\n` })}
|
||||
}
|
||||
`;
|
||||
}
|
||||
/**
|
||||
* Generate the protobuf client
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genTwripClientProtobufImpl(ctx, file, service) {
|
||||
const methods = service.method.map((method) => {
|
||||
return ts_poet_1.code `
|
||||
${formatMethodName(ctx, method.name)}(request: ${relativeMessageName(ctx, file, method.inputType)}): Promise<${relativeMessageName(ctx, file, method.outputType)}> {
|
||||
const data = ${relativeMessageName(ctx, file, method.inputType)}.${encodeProtobuf(ctx, "request")};
|
||||
const promise = this.rpc.request(
|
||||
"${file.package ? file.package + "." : ""}${service.name}",
|
||||
"${formatMethodName(ctx, method.name)}",
|
||||
"application/protobuf",
|
||||
data,
|
||||
);
|
||||
return promise.then((data) => ${relativeMessageName(ctx, file, method.outputType)}.${decodeProtobuf(ctx, "data as Uint8Array")});
|
||||
}
|
||||
`;
|
||||
});
|
||||
const bindings = service.method.map((method) => {
|
||||
return ts_poet_1.code `
|
||||
this.${formatMethodName(ctx, method.name)}.bind(this);
|
||||
`;
|
||||
});
|
||||
return ts_poet_1.code `
|
||||
export class ${service.name}ClientProtobuf implements ${service.name}Client {
|
||||
private readonly rpc: Rpc;
|
||||
constructor(rpc: Rpc) {
|
||||
this.rpc = rpc;
|
||||
${ts_poet_1.joinCode(bindings, { on: `\n` })}
|
||||
}
|
||||
${ts_poet_1.joinCode(methods, { on: `\n\n` })}
|
||||
}
|
||||
`;
|
||||
}
|
||||
/**
|
||||
* Generates twirp service definition
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genTwirpService(ctx, file, service) {
|
||||
const importService = service.name;
|
||||
const serverMethods = service.method.map((method) => {
|
||||
return ts_poet_1.code `
|
||||
${formatMethodName(ctx, method.name)}(ctx: T, request: ${relativeMessageName(ctx, file, method.inputType)}): Promise<${relativeMessageName(ctx, file, method.outputType)}>
|
||||
`;
|
||||
});
|
||||
const methodEnum = service.method.map((method) => {
|
||||
return ts_poet_1.code `${formatMethodName(ctx, method.name)} = "${formatMethodName(ctx, method.name)}",`;
|
||||
});
|
||||
const methodList = service.method.map((method) => {
|
||||
return ts_poet_1.code `${importService}Method.${formatMethodName(ctx, method.name)}`;
|
||||
});
|
||||
return ts_poet_1.code `
|
||||
export interface ${importService}Twirp<T extends ${TwirpContext} = ${TwirpContext}> {
|
||||
${ts_poet_1.joinCode(serverMethods, { on: `\n` })}
|
||||
}
|
||||
|
||||
export enum ${importService}Method {
|
||||
${ts_poet_1.joinCode(methodEnum, { on: "\n" })}
|
||||
}
|
||||
|
||||
export const ${importService}MethodList = [${ts_poet_1.joinCode(methodList, { on: "," })}];
|
||||
`;
|
||||
}
|
||||
/**
|
||||
* Generates the twirp server specification
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genServer(ctx, file, service) {
|
||||
var _a;
|
||||
const importService = service.name;
|
||||
return ts_poet_1.code `
|
||||
|
||||
//==================================//
|
||||
// Server Code //
|
||||
//==================================//
|
||||
|
||||
${genTwirpService(ctx, file, service)}
|
||||
|
||||
export function create${importService}Server<T extends ${TwirpContext} = ${TwirpContext}>(service: ${importService}Twirp<T>) {
|
||||
return new ${TwirpServer}<${importService}Twirp, T>({
|
||||
service,
|
||||
packageName: "${(_a = file.package) !== null && _a !== void 0 ? _a : ''}",
|
||||
serviceName: "${importService}",
|
||||
methodList: ${importService}MethodList,
|
||||
matchRoute: match${importService}Route,
|
||||
})
|
||||
}
|
||||
${genRouteHandler(ctx, file, service)}
|
||||
${ts_poet_1.joinCode(genHandleRequestMethod(ctx, file, service), { on: "\n\n" })}
|
||||
${ts_poet_1.joinCode(genHandleJSONRequest(ctx, file, service), { on: "\n\n" })}
|
||||
${ts_poet_1.joinCode(genHandleProtobufRequest(ctx, file, service), { on: "\n\n" })}
|
||||
`;
|
||||
}
|
||||
/**
|
||||
* Generate the route handler
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genRouteHandler(ctx, file, service) {
|
||||
const cases = service.method.map(method => ts_poet_1.code `
|
||||
case "${formatMethodName(ctx, method.name)}":
|
||||
return async (ctx: T, service: ${service.name}Twirp ,data: Buffer, interceptors?: ${Interceptor}<T, ${relativeMessageName(ctx, file, method.inputType)}, ${relativeMessageName(ctx, file, method.outputType)}>[]) => {
|
||||
ctx = {...ctx, methodName: "${formatMethodName(ctx, method.name)}" }
|
||||
await events.onMatch(ctx);
|
||||
return handle${formatMethodName(ctx, method.name, service.name)}Request(ctx, service, data, interceptors)
|
||||
}
|
||||
`);
|
||||
return ts_poet_1.code `
|
||||
function match${service.name}Route<T extends ${TwirpContext} = ${TwirpContext}>(method: string, events: ${RouterEvents}<T>) {
|
||||
switch(method) {
|
||||
${ts_poet_1.joinCode(cases, { on: `\n` })}
|
||||
default:
|
||||
events.onNotFound();
|
||||
const msg = \`no handler found\`;
|
||||
throw new ${TwirpError}(${TwirpErrorCode}.BadRoute, msg)
|
||||
}
|
||||
}
|
||||
`;
|
||||
}
|
||||
/**
|
||||
* Generate request handler for methods
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genHandleRequestMethod(ctx, file, service) {
|
||||
return service.method.map(method => {
|
||||
return ts_poet_1.code `
|
||||
function handle${formatMethodName(ctx, method.name, service.name)}Request<T extends ${TwirpContext} = ${TwirpContext}>(ctx: T, service: ${service.name}Twirp ,data: Buffer, interceptors?: ${Interceptor}<T, ${relativeMessageName(ctx, file, method.inputType)}, ${relativeMessageName(ctx, file, method.outputType)}>[]): Promise<string | Uint8Array> {
|
||||
switch (ctx.contentType) {
|
||||
case ${TwirpContentType}.JSON:
|
||||
return handle${formatMethodName(ctx, method.name, service.name)}JSON<T>(ctx, service, data, interceptors);
|
||||
case ${TwirpContentType}.Protobuf:
|
||||
return handle${formatMethodName(ctx, method.name, service.name)}Protobuf<T>(ctx, service, data, interceptors);
|
||||
default:
|
||||
const msg = "unexpected Content-Type";
|
||||
throw new ${TwirpError}(${TwirpErrorCode}.BadRoute, msg);
|
||||
}
|
||||
}
|
||||
`;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Generate a JSON request handler for a method
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genHandleJSONRequest(ctx, file, service) {
|
||||
return service.method.map(method => {
|
||||
return ts_poet_1.code `
|
||||
|
||||
async function handle${formatMethodName(ctx, method.name, service.name)}JSON<T extends ${TwirpContext} = ${TwirpContext}>(ctx: T, service: ${service.name}Twirp, data: Buffer, interceptors?: ${Interceptor}<T, ${relativeMessageName(ctx, file, method.inputType)}, ${relativeMessageName(ctx, file, method.outputType)}>[]) {
|
||||
let request: ${relativeMessageName(ctx, file, method.inputType)}
|
||||
let response: ${relativeMessageName(ctx, file, method.outputType)}
|
||||
|
||||
try {
|
||||
const body = JSON.parse(data.toString() || "{}");
|
||||
request = ${relativeMessageName(ctx, file, method.inputType)}.${decodeJSON(ctx, "body")};
|
||||
} catch(e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the json request could not be decoded";
|
||||
throw new ${TwirpError}(${TwirpErrorCode}.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = ${chainInterceptors}(...interceptors) as Interceptor<T, ${relativeMessageName(ctx, file, method.inputType)}, ${relativeMessageName(ctx, file, method.outputType)}>
|
||||
response = await interceptor(ctx, request!, (ctx, inputReq) => {
|
||||
return service.${formatMethodName(ctx, method.name)}(ctx, inputReq);
|
||||
});
|
||||
} else {
|
||||
response = await service.${formatMethodName(ctx, method.name)}(ctx, request!)
|
||||
}
|
||||
|
||||
return JSON.stringify(${relativeMessageName(ctx, file, method.outputType)}.${encodeJSON(ctx, "response")} as string);
|
||||
}
|
||||
`;
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Generates a protobuf request handler
|
||||
* @param ctx
|
||||
* @param file
|
||||
* @param service
|
||||
*/
|
||||
function genHandleProtobufRequest(ctx, file, service) {
|
||||
return service.method.map(method => {
|
||||
return ts_poet_1.code `
|
||||
|
||||
async function handle${formatMethodName(ctx, method.name, service.name)}Protobuf<T extends ${TwirpContext} = ${TwirpContext}>(ctx: T, service: ${service.name}Twirp, data: Buffer, interceptors?: ${Interceptor}<T, ${relativeMessageName(ctx, file, method.inputType)}, ${relativeMessageName(ctx, file, method.outputType)}>[]) {
|
||||
let request: ${relativeMessageName(ctx, file, method.inputType)}
|
||||
let response: ${relativeMessageName(ctx, file, method.outputType)}
|
||||
|
||||
try {
|
||||
request = ${relativeMessageName(ctx, file, method.inputType)}.${decodeProtobuf(ctx, "data")};
|
||||
} catch(e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the protobuf request could not be decoded";
|
||||
throw new ${TwirpError}(${TwirpErrorCode}.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = ${chainInterceptors}(...interceptors) as Interceptor<T, ${relativeMessageName(ctx, file, method.inputType)}, ${relativeMessageName(ctx, file, method.outputType)}>
|
||||
response = await interceptor(ctx, request!, (ctx, inputReq) => {
|
||||
return service.${formatMethodName(ctx, method.name)}(ctx, inputReq);
|
||||
});
|
||||
} else {
|
||||
response = await service.${formatMethodName(ctx, method.name)}(ctx, request!)
|
||||
}
|
||||
|
||||
return Buffer.from(${relativeMessageName(ctx, file, method.outputType)}.${encodeProtobuf(ctx, "response")});
|
||||
}
|
||||
`;
|
||||
});
|
||||
}
|
||||
var SupportedLibs;
|
||||
(function (SupportedLibs) {
|
||||
SupportedLibs["TSProto"] = "ts-proto";
|
||||
SupportedLibs["ProtobufTS"] = "protobuf-ts";
|
||||
})(SupportedLibs || (SupportedLibs = {}));
|
||||
function validateLib(lib) {
|
||||
switch (lib) {
|
||||
case "ts-proto":
|
||||
return SupportedLibs.TSProto;
|
||||
case "protobuf-ts":
|
||||
return SupportedLibs.ProtobufTS;
|
||||
default:
|
||||
throw new Error(`library ${lib} not supported`);
|
||||
}
|
||||
}
|
||||
function decodeJSON(ctx, dataName) {
|
||||
const protoLib = validateLib(ctx.lib);
|
||||
if (protoLib === SupportedLibs.TSProto) {
|
||||
return ts_poet_1.code `fromJSON(${dataName})`;
|
||||
}
|
||||
return ts_poet_1.code `fromJson(${dataName}, { ignoreUnknownFields: true })`;
|
||||
}
|
||||
function encodeJSON(ctx, dataName) {
|
||||
const protoLib = validateLib(ctx.lib);
|
||||
if (protoLib === SupportedLibs.TSProto) {
|
||||
return ts_poet_1.code `toJSON(${dataName})`;
|
||||
}
|
||||
return ts_poet_1.code `toJson(${dataName}, {useProtoFieldName: true, emitDefaultValues: ${ctx.emitDefaultValues ? 'true' : 'false'}})`;
|
||||
}
|
||||
function encodeProtobuf(ctx, dataName) {
|
||||
const protoLib = validateLib(ctx.lib);
|
||||
if (protoLib === SupportedLibs.TSProto) {
|
||||
return ts_poet_1.code `encode(${dataName}).finish()`;
|
||||
}
|
||||
return ts_poet_1.code `toBinary(${dataName})`;
|
||||
}
|
||||
function decodeProtobuf(ctx, dataName) {
|
||||
const protoLib = validateLib(ctx.lib);
|
||||
if (protoLib === SupportedLibs.TSProto) {
|
||||
return ts_poet_1.code `decode(${dataName})`;
|
||||
}
|
||||
return ts_poet_1.code `fromBinary(${dataName})`;
|
||||
}
|
||||
function relativeMessageName(ctx, file, messageName) {
|
||||
const registry = ctx.registry;
|
||||
const symbols = ctx.symbols;
|
||||
const entry = symbols.find(registry.resolveTypeName(messageName));
|
||||
if (!entry) {
|
||||
throw new Error(`Message ${messageName} not found`);
|
||||
}
|
||||
const messageType = local_type_name_1.createLocalTypeName(entry.descriptor, registry);
|
||||
const relativePath = createRelativeImportPath(file.name, entry.file.getFilename());
|
||||
return ts_poet_1.code `${ts_poet_1.imp(`${messageType}@${relativePath}`)}`;
|
||||
}
|
||||
/**
|
||||
* Create a relative path for an import statement like
|
||||
* `import {Foo} from "./foo"`
|
||||
*/
|
||||
function createRelativeImportPath(currentPath, pathToImportFrom) {
|
||||
// create relative path to the file to import
|
||||
let fromPath = path_1.default.relative(path_1.default.dirname(currentPath), pathToImportFrom);
|
||||
// on windows, this may add backslash directory separators.
|
||||
// we replace them with forward slash.
|
||||
if (path_1.default.sep !== "/") {
|
||||
fromPath = fromPath.split(path_1.default.sep).join("/");
|
||||
}
|
||||
// drop file extension
|
||||
fromPath = fromPath.replace(/\.[a-z]+$/, '');
|
||||
// make sure to start with './' to signal relative path to module resolution
|
||||
if (!fromPath.startsWith('../') && !fromPath.startsWith('./')) {
|
||||
fromPath = './' + fromPath;
|
||||
}
|
||||
return fromPath;
|
||||
}
|
||||
function formatMethodName(ctx, methodName, serviceName) {
|
||||
if (methodName === undefined)
|
||||
return undefined;
|
||||
serviceName = serviceName || "";
|
||||
return ctx.camelCase ? camel_case_1.camelCase(serviceName) + camel_case_1.camelCase(methodName) : serviceName + methodName;
|
||||
}
|
||||
97
node_modules/twirp-ts/build/protoc-gen-twirp-ts/interpreter.d.ts
generated
vendored
Normal file
97
node_modules/twirp-ts/build/protoc-gen-twirp-ts/interpreter.d.ts
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import { DescriptorProto, DescriptorRegistry, EnumDescriptorProto, FieldDescriptorProto, FieldOptions_JSType, FileDescriptorProto, MethodDescriptorProto, ServiceDescriptorProto } from "@protobuf-ts/plugin-framework";
|
||||
import * as rt from "@protobuf-ts/runtime";
|
||||
declare type JsonOptionsMap = {
|
||||
[extensionName: string]: rt.JsonValue;
|
||||
};
|
||||
/**
|
||||
* Code borrowed from @protobuf-js/plugin all the rights of this code goes to the author
|
||||
*
|
||||
*
|
||||
* 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 messageTypes;
|
||||
private readonly enumInfos;
|
||||
constructor(registry: DescriptorRegistry);
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* 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 runtime information for an enum.
|
||||
* Creates the info if not created previously.
|
||||
*/
|
||||
getEnumInfo(descriptorOrTypeName: string | EnumDescriptorProto): rt.EnumInfo;
|
||||
/**
|
||||
* Create a name for a field or a oneof.
|
||||
* - use lowerCamelCase
|
||||
* - escape reserved object property names by
|
||||
* adding '$' at the end
|
||||
* - don't have to escape reserved keywords
|
||||
*/
|
||||
private static createTypescriptNameForField;
|
||||
private buildMessageType;
|
||||
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 {};
|
||||
436
node_modules/twirp-ts/build/protoc-gen-twirp-ts/interpreter.js
generated
vendored
Normal file
436
node_modules/twirp-ts/build/protoc-gen-twirp-ts/interpreter.js
generated
vendored
Normal file
@@ -0,0 +1,436 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.RuntimeEnumBuilder = exports.Interpreter = void 0;
|
||||
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
|
||||
const rt = __importStar(require("@protobuf-ts/runtime"));
|
||||
const runtime_1 = require("@protobuf-ts/runtime");
|
||||
/**
|
||||
* Code borrowed from @protobuf-js/plugin all the rights of this code goes to the author
|
||||
*
|
||||
*
|
||||
* 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) {
|
||||
this.registry = registry;
|
||||
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 = []) {
|
||||
// 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), excludeOptions), {});
|
||||
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;
|
||||
}
|
||||
/**
|
||||
* 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) {
|
||||
type = this.buildMessageType(typeName, descriptor.field, []);
|
||||
this.messageTypes.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;
|
||||
}
|
||||
/**
|
||||
* Create a name for a field or a oneof.
|
||||
* - use lowerCamelCase
|
||||
* - escape reserved object property names by
|
||||
* adding '$' at the end
|
||||
* - don't have to escape reserved keywords
|
||||
*/
|
||||
static createTypescriptNameForField(descriptor, additionalReservedWords = "", escapeCharacter = "$") {
|
||||
const reservedObjectProperties = "__proto__,toString".split(",");
|
||||
let name = descriptor.name;
|
||||
runtime_1.assert(name !== undefined);
|
||||
name = rt.lowerCamelCase(name);
|
||||
if (reservedObjectProperties.includes(name)) {
|
||||
name = name + escapeCharacter;
|
||||
}
|
||||
if (additionalReservedWords.split(",").includes(name)) {
|
||||
name = name + escapeCharacter;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
buildMessageType(typeName, fields, excludeOptions) {
|
||||
let desc = this.registry.resolveTypeName(typeName);
|
||||
runtime_1.assert(plugin_framework_1.DescriptorProto.is(desc));
|
||||
return new rt.MessageType(typeName, this.buildFieldInfos(fields, excludeOptions), this.readOptions(desc, excludeOptions));
|
||||
}
|
||||
// skips GROUP field type
|
||||
buildFieldInfos(fieldDescriptors, excludeOptions) {
|
||||
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, excludeOptions);
|
||||
if (fi) {
|
||||
result.push(fi);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
// throws on unexpected field types, notably GROUP
|
||||
buildFieldInfo(fieldDescriptor, excludeOptions) {
|
||||
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 = Interpreter.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 = Interpreter.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;
|
||||
}
|
||||
else {
|
||||
info.options = this.readOptions(fieldDescriptor, excludeOptions);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
buildEnumInfo(descriptor) {
|
||||
let sharedPrefix = this.registry.findEnumSharedPrefix(descriptor, `${descriptor.name}`);
|
||||
let hasZero = descriptor.value.some((v) => v.number === 0);
|
||||
let builder = new RuntimeEnumBuilder();
|
||||
if (!hasZero) {
|
||||
throw new Error("must provide zero value for enum " + descriptor.name);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
12
node_modules/twirp-ts/build/protoc-gen-twirp-ts/local-type-name.d.ts
generated
vendored
Normal file
12
node_modules/twirp-ts/build/protoc-gen-twirp-ts/local-type-name.d.ts
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { AnyTypeDescriptorProto, IDescriptorTree } from "@protobuf-ts/plugin-framework";
|
||||
/**
|
||||
* Code borrowed from @protobuf-js/plugin all the rights of this code goes to the author
|
||||
*
|
||||
* 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;
|
||||
45
node_modules/twirp-ts/build/protoc-gen-twirp-ts/local-type-name.js
generated
vendored
Normal file
45
node_modules/twirp-ts/build/protoc-gen-twirp-ts/local-type-name.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
"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");
|
||||
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 = "Long,Uint8Array,array,Array,string,String,number,Number,boolean,Boolean,bigint,BigInt".split(",");
|
||||
const escapeCharacter = "$";
|
||||
/**
|
||||
* Code borrowed from @protobuf-js/plugin all the rights of this code goes to the author
|
||||
*
|
||||
* 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;
|
||||
38
node_modules/twirp-ts/build/protoc-gen-twirp-ts/plugin.d.ts
generated
vendored
Normal file
38
node_modules/twirp-ts/build/protoc-gen-twirp-ts/plugin.d.ts
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { CodeGeneratorRequest, CodeGeneratorResponse_Feature, PluginBase } from "@protobuf-ts/plugin-framework";
|
||||
import { File } from "./file";
|
||||
export declare class ProtobuftsPlugin extends PluginBase<File> {
|
||||
parameters: {
|
||||
ts_proto: {
|
||||
description: string;
|
||||
};
|
||||
gateway: {
|
||||
description: string;
|
||||
};
|
||||
index_file: {
|
||||
description: string;
|
||||
};
|
||||
emit_default_values: {
|
||||
description: string;
|
||||
};
|
||||
openapi_twirp: {
|
||||
description: string;
|
||||
};
|
||||
openapi_gateway: {
|
||||
description: string;
|
||||
};
|
||||
standalone: {
|
||||
description: string;
|
||||
};
|
||||
client_only: {
|
||||
description: string;
|
||||
};
|
||||
server_only: {
|
||||
description: string;
|
||||
};
|
||||
camel_case: {
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
generate(request: CodeGeneratorRequest): Promise<File[]>;
|
||||
protected getSupportedFeatures: () => CodeGeneratorResponse_Feature[];
|
||||
}
|
||||
145
node_modules/twirp-ts/build/protoc-gen-twirp-ts/plugin.js
generated
vendored
Normal file
145
node_modules/twirp-ts/build/protoc-gen-twirp-ts/plugin.js
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ProtobuftsPlugin = void 0;
|
||||
const plugin_framework_1 = require("@protobuf-ts/plugin-framework");
|
||||
const file_1 = require("./file");
|
||||
const twirp_1 = require("./gen/twirp");
|
||||
const gateway_1 = require("./gen/gateway");
|
||||
const local_type_name_1 = require("./local-type-name");
|
||||
const interpreter_1 = require("./interpreter");
|
||||
const open_api_1 = require("./gen/open-api");
|
||||
const index_file_1 = require("./gen/index-file");
|
||||
class ProtobuftsPlugin extends plugin_framework_1.PluginBase {
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
this.parameters = {
|
||||
ts_proto: {
|
||||
description: "Use the ts-proto compiler (protobuf-ts by default)",
|
||||
},
|
||||
gateway: {
|
||||
description: "Generates the twirp gateway",
|
||||
},
|
||||
index_file: {
|
||||
description: "Generates an index.ts file that exports all the types",
|
||||
},
|
||||
emit_default_values: {
|
||||
description: "Json encode and decode will emit default values",
|
||||
},
|
||||
openapi_twirp: {
|
||||
description: "Generates an OpenAPI spec for twirp handlers",
|
||||
},
|
||||
openapi_gateway: {
|
||||
description: "Generates an OpenAPI spec for gateway handlers",
|
||||
},
|
||||
standalone: {
|
||||
description: "Generates client and server in 2 separate files",
|
||||
},
|
||||
client_only: {
|
||||
description: "Only client will be generated (overrides 'standalone')",
|
||||
},
|
||||
server_only: {
|
||||
description: "Only server will be generated (overrides 'standalone')",
|
||||
},
|
||||
camel_case: {
|
||||
description: "Generates with method names in camel case.",
|
||||
},
|
||||
};
|
||||
// we support proto3-optionals, so we let protoc know
|
||||
this.getSupportedFeatures = () => [
|
||||
plugin_framework_1.CodeGeneratorResponse_Feature.PROTO3_OPTIONAL,
|
||||
];
|
||||
}
|
||||
generate(request) {
|
||||
var _a, _b, _c, _d;
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const params = this.parseOptions(this.parameters, request.parameter), registry = plugin_framework_1.DescriptorRegistry.createFrom(request), symbols = new plugin_framework_1.SymbolTable(), interpreter = new interpreter_1.Interpreter(registry);
|
||||
const ctx = {
|
||||
lib: params.ts_proto ? "ts-proto" : "protobuf-ts",
|
||||
emitDefaultValues: params.emit_default_values,
|
||||
symbols,
|
||||
registry,
|
||||
interpreter,
|
||||
camelCase: params.camel_case,
|
||||
};
|
||||
const files = [];
|
||||
for (let fileDescriptor of registry.allFiles()) {
|
||||
const messageFileOut = new file_1.File(`${(_a = fileDescriptor.name) === null || _a === void 0 ? void 0 : _a.replace(".proto", "").toLowerCase()}`);
|
||||
registry.visitTypes(fileDescriptor, (descriptor) => {
|
||||
// we are not interested in synthetic types like map entry messages
|
||||
if (registry.isSyntheticElement(descriptor))
|
||||
return;
|
||||
ctx.symbols.register(local_type_name_1.createLocalTypeName(descriptor, registry), descriptor, messageFileOut);
|
||||
});
|
||||
// Generate a combined client and server bundle if no code gen
|
||||
// options are passed.
|
||||
if (!params.standalone && !params.client_only && !params.server_only) {
|
||||
const twirpFileOut = new file_1.File(`${(_b = fileDescriptor.name) === null || _b === void 0 ? void 0 : _b.replace(".proto", "").toLowerCase()}.twirp.ts`);
|
||||
const twirpFileContent = yield twirp_1.generateTwirp(ctx, fileDescriptor);
|
||||
twirpFileOut.setContent(twirpFileContent);
|
||||
files.push(twirpFileOut);
|
||||
}
|
||||
if (params.server_only && params.client_only) {
|
||||
throw new Error("Only one of server_only or client_only can be passed.");
|
||||
}
|
||||
if (params.server_only || params.standalone) {
|
||||
const serverFileOut = new file_1.File(`${(_c = fileDescriptor.name) === null || _c === void 0 ? void 0 : _c.replace(".proto", "").toLowerCase()}.twirp.ts`);
|
||||
const serverContent = yield twirp_1.generateTwirpServer(ctx, fileDescriptor);
|
||||
serverFileOut.setContent(serverContent);
|
||||
files.push(serverFileOut);
|
||||
}
|
||||
if (params.client_only || params.standalone) {
|
||||
const clientFileOut = new file_1.File(`${(_d = fileDescriptor.name) === null || _d === void 0 ? void 0 : _d.replace(".proto", "").toLowerCase()}.twirp-client.ts`);
|
||||
const clientContent = yield twirp_1.generateTwirpClient(ctx, fileDescriptor);
|
||||
clientFileOut.setContent(clientContent);
|
||||
files.push(clientFileOut);
|
||||
}
|
||||
}
|
||||
// Gateway generation
|
||||
if (params.gateway) {
|
||||
const gatewayFileOut = new file_1.File(`gateway.twirp.ts`);
|
||||
const gatewayContent = yield gateway_1.genGateway(ctx, registry.allFiles());
|
||||
gatewayFileOut.setContent(gatewayContent);
|
||||
files.push(gatewayFileOut);
|
||||
}
|
||||
// Create index file
|
||||
if (params.index_file) {
|
||||
files.push(index_file_1.genIndexFile(registry, [...files]));
|
||||
}
|
||||
// Open API
|
||||
const docs = [];
|
||||
if (params.openapi_twirp) {
|
||||
docs.push(...(yield open_api_1.genOpenAPI(ctx, registry.allFiles(), open_api_1.OpenAPIType.TWIRP)));
|
||||
}
|
||||
if (params.openapi_gateway) {
|
||||
docs.push(...(yield open_api_1.genOpenAPI(ctx, registry.allFiles(), open_api_1.OpenAPIType.GATEWAY)));
|
||||
}
|
||||
docs.forEach((doc) => {
|
||||
const file = new file_1.File(`${doc.fileName}`);
|
||||
file.setContent(doc.content);
|
||||
files.push(file);
|
||||
});
|
||||
return files;
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.ProtobuftsPlugin = ProtobuftsPlugin;
|
||||
new ProtobuftsPlugin()
|
||||
.run()
|
||||
.then(() => {
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((e) => {
|
||||
process.stderr.write("FAILED!");
|
||||
process.stderr.write(e.message);
|
||||
process.stderr.write(e.stack);
|
||||
process.exit(1);
|
||||
});
|
||||
2
node_modules/twirp-ts/build/twirp/__mocks__/gateway.twirp.d.ts
generated
vendored
Normal file
2
node_modules/twirp-ts/build/twirp/__mocks__/gateway.twirp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import { Gateway } from "../index";
|
||||
export declare function createGateway(): Gateway;
|
||||
47
node_modules/twirp-ts/build/twirp/__mocks__/gateway.twirp.js
generated
vendored
Normal file
47
node_modules/twirp-ts/build/twirp/__mocks__/gateway.twirp.js
generated
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createGateway = void 0;
|
||||
const index_1 = require("../index");
|
||||
const path_to_regexp_1 = require("path-to-regexp");
|
||||
function createGateway() {
|
||||
return new index_1.Gateway({
|
||||
post: [
|
||||
{
|
||||
packageName: "twirp.example.haberdasher",
|
||||
methodName: "MakeHat",
|
||||
serviceName: "Haberdasher",
|
||||
httpMethod: "post",
|
||||
matchingPath: "/hat{:query_string(\\?.*)}?",
|
||||
matcher: path_to_regexp_1.match("/hat{:query_string(\\?.*)}?"),
|
||||
bodyKey: "*",
|
||||
responseBodyKey: "",
|
||||
},
|
||||
],
|
||||
get: [
|
||||
{
|
||||
packageName: "twirp.example.haberdasher",
|
||||
methodName: "FindHat",
|
||||
serviceName: "Haberdasher",
|
||||
httpMethod: "get",
|
||||
matchingPath: "/hat/{:hat_id}{:query_string(\\?.*)}?",
|
||||
matcher: path_to_regexp_1.match("/hat/{:hat_id}{:query_string(\\?.*)}?"),
|
||||
bodyKey: "",
|
||||
responseBodyKey: "",
|
||||
},
|
||||
{
|
||||
packageName: "twirp.example.haberdasher",
|
||||
methodName: "ListHat",
|
||||
serviceName: "Haberdasher",
|
||||
httpMethod: "get",
|
||||
matchingPath: "/hat{:query_string(\\?.*)}?",
|
||||
matcher: path_to_regexp_1.match("/hat{:query_string(\\?.*)}?"),
|
||||
bodyKey: "",
|
||||
responseBodyKey: "",
|
||||
},
|
||||
],
|
||||
put: [],
|
||||
patch: [],
|
||||
delete: [],
|
||||
});
|
||||
}
|
||||
exports.createGateway = createGateway;
|
||||
147
node_modules/twirp-ts/build/twirp/__mocks__/service.d.ts
generated
vendored
Normal file
147
node_modules/twirp-ts/build/twirp/__mocks__/service.d.ts
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
import { ServiceType } from "@protobuf-ts/runtime-rpc";
|
||||
import type { BinaryWriteOptions } from "@protobuf-ts/runtime";
|
||||
import type { IBinaryWriter } from "@protobuf-ts/runtime";
|
||||
import type { BinaryReadOptions } from "@protobuf-ts/runtime";
|
||||
import type { IBinaryReader } from "@protobuf-ts/runtime";
|
||||
import { MessageType } from "@protobuf-ts/runtime";
|
||||
/**
|
||||
* @generated from protobuf message twirp.example.haberdasher.FindHatRPC
|
||||
*/
|
||||
export interface FindHatRPC {
|
||||
/**
|
||||
* @generated from protobuf field: string hat_id = 1;
|
||||
*/
|
||||
hatId: string;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message twirp.example.haberdasher.ListHatRPC
|
||||
*/
|
||||
export interface ListHatRPC {
|
||||
/**
|
||||
* @generated from protobuf field: repeated twirp.example.haberdasher.Filter filters = 1;
|
||||
*/
|
||||
filters: Filter[];
|
||||
}
|
||||
/**
|
||||
* Size of a Hat, in inches.
|
||||
*
|
||||
* @generated from protobuf message twirp.example.haberdasher.Size
|
||||
*/
|
||||
export interface Size {
|
||||
/**
|
||||
* @generated from protobuf field: int32 inches = 1;
|
||||
*/
|
||||
inches: number;
|
||||
}
|
||||
/**
|
||||
* A Hat is a piece of headwear made by a Haberdasher.
|
||||
*
|
||||
* @generated from protobuf message twirp.example.haberdasher.Hat
|
||||
*/
|
||||
export interface Hat {
|
||||
/**
|
||||
* @generated from protobuf field: string id = 1;
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* @generated from protobuf field: int32 inches = 2;
|
||||
*/
|
||||
inches: number;
|
||||
/**
|
||||
* @generated from protobuf field: string color = 3;
|
||||
*/
|
||||
color: string;
|
||||
/**
|
||||
* @generated from protobuf field: string name = 4;
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* @generated from protobuf field: repeated twirp.example.haberdasher.Hat variants = 5;
|
||||
*/
|
||||
variants: Hat[];
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message twirp.example.haberdasher.Filter
|
||||
*/
|
||||
export interface Filter {
|
||||
/**
|
||||
* @generated from protobuf field: string order_by = 1;
|
||||
*/
|
||||
orderBy: string;
|
||||
/**
|
||||
* @generated from protobuf field: twirp.example.haberdasher.Pagination pagination = 2;
|
||||
*/
|
||||
pagination?: Pagination;
|
||||
}
|
||||
/**
|
||||
* @generated from protobuf message twirp.example.haberdasher.Pagination
|
||||
*/
|
||||
export interface Pagination {
|
||||
/**
|
||||
* @generated from protobuf field: int32 limit = 1;
|
||||
*/
|
||||
limit: number;
|
||||
/**
|
||||
* @generated from protobuf field: int32 offset = 2;
|
||||
*/
|
||||
offset: number;
|
||||
}
|
||||
declare class FindHatRPC$Type extends MessageType<FindHatRPC> {
|
||||
constructor();
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: FindHatRPC): FindHatRPC;
|
||||
internalBinaryWrite(message: FindHatRPC, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.FindHatRPC
|
||||
*/
|
||||
export declare const FindHatRPC: FindHatRPC$Type;
|
||||
declare class ListHatRPC$Type extends MessageType<ListHatRPC> {
|
||||
constructor();
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: ListHatRPC): ListHatRPC;
|
||||
internalBinaryWrite(message: ListHatRPC, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.ListHatRPC
|
||||
*/
|
||||
export declare const ListHatRPC: ListHatRPC$Type;
|
||||
declare class Size$Type extends MessageType<Size> {
|
||||
constructor();
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Size): Size;
|
||||
internalBinaryWrite(message: Size, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Size
|
||||
*/
|
||||
export declare const Size: Size$Type;
|
||||
declare class Hat$Type extends MessageType<Hat> {
|
||||
constructor();
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Hat): Hat;
|
||||
internalBinaryWrite(message: Hat, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Hat
|
||||
*/
|
||||
export declare const Hat: Hat$Type;
|
||||
declare class Filter$Type extends MessageType<Filter> {
|
||||
constructor();
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Filter): Filter;
|
||||
internalBinaryWrite(message: Filter, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Filter
|
||||
*/
|
||||
export declare const Filter: Filter$Type;
|
||||
declare class Pagination$Type extends MessageType<Pagination> {
|
||||
constructor();
|
||||
internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: Pagination): Pagination;
|
||||
internalBinaryWrite(message: Pagination, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter;
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Pagination
|
||||
*/
|
||||
export declare const Pagination: Pagination$Type;
|
||||
/**
|
||||
* @generated ServiceType for protobuf service twirp.example.haberdasher.Haberdasher
|
||||
*/
|
||||
export declare const Haberdasher: ServiceType;
|
||||
export {};
|
||||
300
node_modules/twirp-ts/build/twirp/__mocks__/service.js
generated
vendored
Normal file
300
node_modules/twirp-ts/build/twirp/__mocks__/service.js
generated
vendored
Normal file
@@ -0,0 +1,300 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Haberdasher = exports.Pagination = exports.Filter = exports.Hat = exports.Size = exports.ListHatRPC = exports.FindHatRPC = void 0;
|
||||
// @generated by protobuf-ts 2.0.0-alpha.27 with parameters client_none,generate_dependencies
|
||||
// @generated from protobuf file "service.proto" (package "twirp.example.haberdasher", syntax proto3)
|
||||
// tslint:disable
|
||||
const runtime_rpc_1 = require("@protobuf-ts/runtime-rpc");
|
||||
const runtime_1 = require("@protobuf-ts/runtime");
|
||||
const runtime_2 = require("@protobuf-ts/runtime");
|
||||
const runtime_3 = require("@protobuf-ts/runtime");
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class FindHatRPC$Type extends runtime_3.MessageType {
|
||||
constructor() {
|
||||
super("twirp.example.haberdasher.FindHatRPC", [
|
||||
{ no: 1, name: "hat_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
|
||||
]);
|
||||
}
|
||||
internalBinaryRead(reader, length, options, target) {
|
||||
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string hat_id */ 1:
|
||||
message.hatId = reader.string();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message, writer, options) {
|
||||
/* string hat_id = 1; */
|
||||
if (message.hatId !== "")
|
||||
writer.tag(1, runtime_1.WireType.LengthDelimited).string(message.hatId);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.FindHatRPC
|
||||
*/
|
||||
exports.FindHatRPC = new FindHatRPC$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class ListHatRPC$Type extends runtime_3.MessageType {
|
||||
constructor() {
|
||||
super("twirp.example.haberdasher.ListHatRPC", [
|
||||
{ no: 1, name: "filters", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => exports.Filter }
|
||||
]);
|
||||
}
|
||||
internalBinaryRead(reader, length, options, target) {
|
||||
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* repeated twirp.example.haberdasher.Filter filters */ 1:
|
||||
message.filters.push(exports.Filter.internalBinaryRead(reader, reader.uint32(), options));
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message, writer, options) {
|
||||
/* repeated twirp.example.haberdasher.Filter filters = 1; */
|
||||
for (let i = 0; i < message.filters.length; i++)
|
||||
exports.Filter.internalBinaryWrite(message.filters[i], writer.tag(1, runtime_1.WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.ListHatRPC
|
||||
*/
|
||||
exports.ListHatRPC = new ListHatRPC$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class Size$Type extends runtime_3.MessageType {
|
||||
constructor() {
|
||||
super("twirp.example.haberdasher.Size", [
|
||||
{ no: 1, name: "inches", kind: "scalar", T: 5 /*ScalarType.INT32*/ }
|
||||
]);
|
||||
}
|
||||
internalBinaryRead(reader, length, options, target) {
|
||||
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* int32 inches */ 1:
|
||||
message.inches = reader.int32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message, writer, options) {
|
||||
/* int32 inches = 1; */
|
||||
if (message.inches !== 0)
|
||||
writer.tag(1, runtime_1.WireType.Varint).int32(message.inches);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Size
|
||||
*/
|
||||
exports.Size = new Size$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class Hat$Type extends runtime_3.MessageType {
|
||||
constructor() {
|
||||
super("twirp.example.haberdasher.Hat", [
|
||||
{ no: 1, name: "id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "inches", kind: "scalar", T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 3, name: "color", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 4, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 5, name: "variants", kind: "message", repeat: 1 /*RepeatType.PACKED*/, T: () => exports.Hat }
|
||||
]);
|
||||
}
|
||||
internalBinaryRead(reader, length, options, target) {
|
||||
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string id */ 1:
|
||||
message.id = reader.string();
|
||||
break;
|
||||
case /* int32 inches */ 2:
|
||||
message.inches = reader.int32();
|
||||
break;
|
||||
case /* string color */ 3:
|
||||
message.color = reader.string();
|
||||
break;
|
||||
case /* string name */ 4:
|
||||
message.name = reader.string();
|
||||
break;
|
||||
case /* repeated twirp.example.haberdasher.Hat variants */ 5:
|
||||
message.variants.push(exports.Hat.internalBinaryRead(reader, reader.uint32(), options));
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message, writer, options) {
|
||||
/* string id = 1; */
|
||||
if (message.id !== "")
|
||||
writer.tag(1, runtime_1.WireType.LengthDelimited).string(message.id);
|
||||
/* int32 inches = 2; */
|
||||
if (message.inches !== 0)
|
||||
writer.tag(2, runtime_1.WireType.Varint).int32(message.inches);
|
||||
/* string color = 3; */
|
||||
if (message.color !== "")
|
||||
writer.tag(3, runtime_1.WireType.LengthDelimited).string(message.color);
|
||||
/* string name = 4; */
|
||||
if (message.name !== "")
|
||||
writer.tag(4, runtime_1.WireType.LengthDelimited).string(message.name);
|
||||
/* repeated twirp.example.haberdasher.Hat variants = 5; */
|
||||
for (let i = 0; i < message.variants.length; i++)
|
||||
exports.Hat.internalBinaryWrite(message.variants[i], writer.tag(5, runtime_1.WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Hat
|
||||
*/
|
||||
exports.Hat = new Hat$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class Filter$Type extends runtime_3.MessageType {
|
||||
constructor() {
|
||||
super("twirp.example.haberdasher.Filter", [
|
||||
{ no: 1, name: "order_by", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
|
||||
{ no: 2, name: "pagination", kind: "message", T: () => exports.Pagination }
|
||||
]);
|
||||
}
|
||||
internalBinaryRead(reader, length, options, target) {
|
||||
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* string order_by */ 1:
|
||||
message.orderBy = reader.string();
|
||||
break;
|
||||
case /* twirp.example.haberdasher.Pagination pagination */ 2:
|
||||
message.pagination = exports.Pagination.internalBinaryRead(reader, reader.uint32(), options, message.pagination);
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message, writer, options) {
|
||||
/* string order_by = 1; */
|
||||
if (message.orderBy !== "")
|
||||
writer.tag(1, runtime_1.WireType.LengthDelimited).string(message.orderBy);
|
||||
/* twirp.example.haberdasher.Pagination pagination = 2; */
|
||||
if (message.pagination)
|
||||
exports.Pagination.internalBinaryWrite(message.pagination, writer.tag(2, runtime_1.WireType.LengthDelimited).fork(), options).join();
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Filter
|
||||
*/
|
||||
exports.Filter = new Filter$Type();
|
||||
// @generated message type with reflection information, may provide speed optimized methods
|
||||
class Pagination$Type extends runtime_3.MessageType {
|
||||
constructor() {
|
||||
super("twirp.example.haberdasher.Pagination", [
|
||||
{ no: 1, name: "limit", kind: "scalar", T: 5 /*ScalarType.INT32*/ },
|
||||
{ no: 2, name: "offset", kind: "scalar", T: 5 /*ScalarType.INT32*/ }
|
||||
]);
|
||||
}
|
||||
internalBinaryRead(reader, length, options, target) {
|
||||
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
|
||||
while (reader.pos < end) {
|
||||
let [fieldNo, wireType] = reader.tag();
|
||||
switch (fieldNo) {
|
||||
case /* int32 limit */ 1:
|
||||
message.limit = reader.int32();
|
||||
break;
|
||||
case /* int32 offset */ 2:
|
||||
message.offset = reader.int32();
|
||||
break;
|
||||
default:
|
||||
let u = options.readUnknownField;
|
||||
if (u === "throw")
|
||||
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
|
||||
let d = reader.skip(wireType);
|
||||
if (u !== false)
|
||||
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
internalBinaryWrite(message, writer, options) {
|
||||
/* int32 limit = 1; */
|
||||
if (message.limit !== 0)
|
||||
writer.tag(1, runtime_1.WireType.Varint).int32(message.limit);
|
||||
/* int32 offset = 2; */
|
||||
if (message.offset !== 0)
|
||||
writer.tag(2, runtime_1.WireType.Varint).int32(message.offset);
|
||||
let u = options.writeUnknownFields;
|
||||
if (u !== false)
|
||||
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
|
||||
return writer;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @generated MessageType for protobuf message twirp.example.haberdasher.Pagination
|
||||
*/
|
||||
exports.Pagination = new Pagination$Type();
|
||||
/**
|
||||
* @generated ServiceType for protobuf service twirp.example.haberdasher.Haberdasher
|
||||
*/
|
||||
exports.Haberdasher = new runtime_rpc_1.ServiceType("twirp.example.haberdasher.Haberdasher", [
|
||||
{ name: "MakeHat", options: { "google.api.http": { body: "*", post: "/hat" } }, I: exports.Size, O: exports.Hat },
|
||||
{ name: "FindHat", options: { "google.api.http": { get: "/hat/{hat_id}" } }, I: exports.FindHatRPC, O: exports.FindHatRPC },
|
||||
{ name: "ListHat", options: { "google.api.http": { get: "/hat" } }, I: exports.ListHatRPC, O: exports.ListHatRPC }
|
||||
]);
|
||||
38
node_modules/twirp-ts/build/twirp/__mocks__/service.twirp.d.ts
generated
vendored
Normal file
38
node_modules/twirp-ts/build/twirp/__mocks__/service.twirp.d.ts
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/// <reference types="node" />
|
||||
import { TwirpContext, TwirpServer } from "../index";
|
||||
import { Size, Hat, FindHatRPC, ListHatRPC } from "./service";
|
||||
interface Rpc {
|
||||
request(service: string, method: string, contentType: "application/json" | "application/protobuf", data: object | Uint8Array): Promise<object | Uint8Array>;
|
||||
}
|
||||
export interface HaberdasherClient {
|
||||
MakeHat(request: Size): Promise<Hat>;
|
||||
FindHat(request: FindHatRPC): Promise<FindHatRPC>;
|
||||
ListHat(request: ListHatRPC): Promise<ListHatRPC>;
|
||||
}
|
||||
export declare class HaberdasherClientJSON implements HaberdasherClient {
|
||||
private readonly rpc;
|
||||
constructor(rpc: Rpc);
|
||||
MakeHat(request: Size): Promise<Hat>;
|
||||
FindHat(request: FindHatRPC): Promise<FindHatRPC>;
|
||||
ListHat(request: ListHatRPC): Promise<ListHatRPC>;
|
||||
}
|
||||
export declare class HaberdasherClientProtobuf implements HaberdasherClient {
|
||||
private readonly rpc;
|
||||
constructor(rpc: Rpc);
|
||||
MakeHat(request: Size): Promise<Hat>;
|
||||
FindHat(request: FindHatRPC): Promise<FindHatRPC>;
|
||||
ListHat(request: ListHatRPC): Promise<ListHatRPC>;
|
||||
}
|
||||
export interface HaberdasherTwirp<T extends TwirpContext = TwirpContext> {
|
||||
MakeHat(ctx: T, request: Size): Promise<Hat>;
|
||||
FindHat(ctx: T, request: FindHatRPC): Promise<FindHatRPC>;
|
||||
ListHat(ctx: T, request: ListHatRPC): Promise<ListHatRPC>;
|
||||
}
|
||||
export declare enum HaberdasherMethod {
|
||||
MakeHat = "MakeHat",
|
||||
FindHat = "FindHat",
|
||||
ListHat = "ListHat"
|
||||
}
|
||||
export declare const HaberdasherMethodList: HaberdasherMethod[];
|
||||
export declare function createHaberdasherServer<T extends TwirpContext = TwirpContext>(service: HaberdasherTwirp<T>): TwirpServer<HaberdasherTwirp<TwirpContext<import("http").IncomingMessage, import("http").ServerResponse>>, T>;
|
||||
export {};
|
||||
313
node_modules/twirp-ts/build/twirp/__mocks__/service.twirp.js
generated
vendored
Normal file
313
node_modules/twirp-ts/build/twirp/__mocks__/service.twirp.js
generated
vendored
Normal file
@@ -0,0 +1,313 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createHaberdasherServer = exports.HaberdasherMethodList = exports.HaberdasherMethod = exports.HaberdasherClientProtobuf = exports.HaberdasherClientJSON = void 0;
|
||||
const index_1 = require("../index");
|
||||
const service_1 = require("./service");
|
||||
class HaberdasherClientJSON {
|
||||
constructor(rpc) {
|
||||
this.rpc = rpc;
|
||||
this.MakeHat.bind(this);
|
||||
this.FindHat.bind(this);
|
||||
this.ListHat.bind(this);
|
||||
}
|
||||
MakeHat(request) {
|
||||
const data = service_1.Size.toJson(request, {
|
||||
useProtoFieldName: true,
|
||||
emitDefaultValues: false,
|
||||
});
|
||||
const promise = this.rpc.request("twirp.example.haberdasher.Haberdasher", "MakeHat", "application/json", data);
|
||||
return promise.then((data) => service_1.Hat.fromJson(data, { ignoreUnknownFields: true }));
|
||||
}
|
||||
FindHat(request) {
|
||||
const data = service_1.FindHatRPC.toJson(request, {
|
||||
useProtoFieldName: true,
|
||||
emitDefaultValues: false,
|
||||
});
|
||||
const promise = this.rpc.request("twirp.example.haberdasher.Haberdasher", "FindHat", "application/json", data);
|
||||
return promise.then((data) => service_1.FindHatRPC.fromJson(data, { ignoreUnknownFields: true }));
|
||||
}
|
||||
ListHat(request) {
|
||||
const data = service_1.ListHatRPC.toJson(request, {
|
||||
useProtoFieldName: true,
|
||||
emitDefaultValues: false,
|
||||
});
|
||||
const promise = this.rpc.request("twirp.example.haberdasher.Haberdasher", "ListHat", "application/json", data);
|
||||
return promise.then((data) => service_1.ListHatRPC.fromJson(data, { ignoreUnknownFields: true }));
|
||||
}
|
||||
}
|
||||
exports.HaberdasherClientJSON = HaberdasherClientJSON;
|
||||
class HaberdasherClientProtobuf {
|
||||
constructor(rpc) {
|
||||
this.rpc = rpc;
|
||||
this.MakeHat.bind(this);
|
||||
this.FindHat.bind(this);
|
||||
this.ListHat.bind(this);
|
||||
}
|
||||
MakeHat(request) {
|
||||
const data = service_1.Size.toBinary(request);
|
||||
const promise = this.rpc.request("twirp.example.haberdasher.Haberdasher", "MakeHat", "application/protobuf", data);
|
||||
return promise.then((data) => service_1.Hat.fromBinary(data));
|
||||
}
|
||||
FindHat(request) {
|
||||
const data = service_1.FindHatRPC.toBinary(request);
|
||||
const promise = this.rpc.request("twirp.example.haberdasher.Haberdasher", "FindHat", "application/protobuf", data);
|
||||
return promise.then((data) => service_1.FindHatRPC.fromBinary(data));
|
||||
}
|
||||
ListHat(request) {
|
||||
const data = service_1.ListHatRPC.toBinary(request);
|
||||
const promise = this.rpc.request("twirp.example.haberdasher.Haberdasher", "ListHat", "application/protobuf", data);
|
||||
return promise.then((data) => service_1.ListHatRPC.fromBinary(data));
|
||||
}
|
||||
}
|
||||
exports.HaberdasherClientProtobuf = HaberdasherClientProtobuf;
|
||||
var HaberdasherMethod;
|
||||
(function (HaberdasherMethod) {
|
||||
HaberdasherMethod["MakeHat"] = "MakeHat";
|
||||
HaberdasherMethod["FindHat"] = "FindHat";
|
||||
HaberdasherMethod["ListHat"] = "ListHat";
|
||||
})(HaberdasherMethod = exports.HaberdasherMethod || (exports.HaberdasherMethod = {}));
|
||||
exports.HaberdasherMethodList = [
|
||||
HaberdasherMethod.MakeHat,
|
||||
HaberdasherMethod.FindHat,
|
||||
HaberdasherMethod.ListHat,
|
||||
];
|
||||
function createHaberdasherServer(service) {
|
||||
return new index_1.TwirpServer({
|
||||
service,
|
||||
packageName: "twirp.example.haberdasher",
|
||||
serviceName: "Haberdasher",
|
||||
methodList: exports.HaberdasherMethodList,
|
||||
matchRoute: matchHaberdasherRoute,
|
||||
});
|
||||
}
|
||||
exports.createHaberdasherServer = createHaberdasherServer;
|
||||
function matchHaberdasherRoute(method, events) {
|
||||
switch (method) {
|
||||
case "MakeHat":
|
||||
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
|
||||
ctx = Object.assign(Object.assign({}, ctx), { methodName: "MakeHat" });
|
||||
yield events.onMatch(ctx);
|
||||
return handleHaberdasherMakeHatRequest(ctx, service, data, interceptors);
|
||||
});
|
||||
case "FindHat":
|
||||
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
|
||||
ctx = Object.assign(Object.assign({}, ctx), { methodName: "FindHat" });
|
||||
yield events.onMatch(ctx);
|
||||
return handleHaberdasherFindHatRequest(ctx, service, data, interceptors);
|
||||
});
|
||||
case "ListHat":
|
||||
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
|
||||
ctx = Object.assign(Object.assign({}, ctx), { methodName: "ListHat" });
|
||||
yield events.onMatch(ctx);
|
||||
return handleHaberdasherListHatRequest(ctx, service, data, interceptors);
|
||||
});
|
||||
default:
|
||||
events.onNotFound();
|
||||
const msg = `no handler found`;
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.BadRoute, msg);
|
||||
}
|
||||
}
|
||||
function handleHaberdasherMakeHatRequest(ctx, service, data, interceptors) {
|
||||
switch (ctx.contentType) {
|
||||
case index_1.TwirpContentType.JSON:
|
||||
return handleHaberdasherMakeHatJSON(ctx, service, data, interceptors);
|
||||
case index_1.TwirpContentType.Protobuf:
|
||||
return handleHaberdasherMakeHatProtobuf(ctx, service, data, interceptors);
|
||||
default:
|
||||
const msg = "unexpected Content-Type";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.BadRoute, msg);
|
||||
}
|
||||
}
|
||||
function handleHaberdasherFindHatRequest(ctx, service, data, interceptors) {
|
||||
switch (ctx.contentType) {
|
||||
case index_1.TwirpContentType.JSON:
|
||||
return handleHaberdasherFindHatJSON(ctx, service, data, interceptors);
|
||||
case index_1.TwirpContentType.Protobuf:
|
||||
return handleHaberdasherFindHatProtobuf(ctx, service, data, interceptors);
|
||||
default:
|
||||
const msg = "unexpected Content-Type";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.BadRoute, msg);
|
||||
}
|
||||
}
|
||||
function handleHaberdasherListHatRequest(ctx, service, data, interceptors) {
|
||||
switch (ctx.contentType) {
|
||||
case index_1.TwirpContentType.JSON:
|
||||
return handleHaberdasherListHatJSON(ctx, service, data, interceptors);
|
||||
case index_1.TwirpContentType.Protobuf:
|
||||
return handleHaberdasherListHatProtobuf(ctx, service, data, interceptors);
|
||||
default:
|
||||
const msg = "unexpected Content-Type";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.BadRoute, msg);
|
||||
}
|
||||
}
|
||||
function handleHaberdasherMakeHatJSON(ctx, service, data, interceptors) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let request;
|
||||
let response;
|
||||
try {
|
||||
const body = JSON.parse(data.toString() || "{}");
|
||||
request = service_1.Size.fromJson(body, { ignoreUnknownFields: true });
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the json request could not be decoded";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = index_1.chainInterceptors(...interceptors);
|
||||
response = yield interceptor(ctx, request, (ctx, inputReq) => {
|
||||
return service.MakeHat(ctx, inputReq);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = yield service.MakeHat(ctx, request);
|
||||
}
|
||||
return JSON.stringify(service_1.Hat.toJson(response, {
|
||||
useProtoFieldName: true,
|
||||
emitDefaultValues: false,
|
||||
}));
|
||||
});
|
||||
}
|
||||
function handleHaberdasherFindHatJSON(ctx, service, data, interceptors) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let request;
|
||||
let response;
|
||||
try {
|
||||
const body = JSON.parse(data.toString() || "{}");
|
||||
request = service_1.FindHatRPC.fromJson(body, { ignoreUnknownFields: true });
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the json request could not be decoded";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = index_1.chainInterceptors(...interceptors);
|
||||
response = yield interceptor(ctx, request, (ctx, inputReq) => {
|
||||
return service.FindHat(ctx, inputReq);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = yield service.FindHat(ctx, request);
|
||||
}
|
||||
return JSON.stringify(service_1.FindHatRPC.toJson(response, {
|
||||
useProtoFieldName: true,
|
||||
emitDefaultValues: false,
|
||||
}));
|
||||
});
|
||||
}
|
||||
function handleHaberdasherListHatJSON(ctx, service, data, interceptors) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let request;
|
||||
let response;
|
||||
try {
|
||||
const body = JSON.parse(data.toString() || "{}");
|
||||
request = service_1.ListHatRPC.fromJson(body, { ignoreUnknownFields: true });
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the json request could not be decoded";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = index_1.chainInterceptors(...interceptors);
|
||||
response = yield interceptor(ctx, request, (ctx, inputReq) => {
|
||||
return service.ListHat(ctx, inputReq);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = yield service.ListHat(ctx, request);
|
||||
}
|
||||
return JSON.stringify(service_1.ListHatRPC.toJson(response, {
|
||||
useProtoFieldName: true,
|
||||
emitDefaultValues: false,
|
||||
}));
|
||||
});
|
||||
}
|
||||
function handleHaberdasherMakeHatProtobuf(ctx, service, data, interceptors) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let request;
|
||||
let response;
|
||||
try {
|
||||
request = service_1.Size.fromBinary(data);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the protobuf request could not be decoded";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = index_1.chainInterceptors(...interceptors);
|
||||
response = yield interceptor(ctx, request, (ctx, inputReq) => {
|
||||
return service.MakeHat(ctx, inputReq);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = yield service.MakeHat(ctx, request);
|
||||
}
|
||||
return Buffer.from(service_1.Hat.toBinary(response));
|
||||
});
|
||||
}
|
||||
function handleHaberdasherFindHatProtobuf(ctx, service, data, interceptors) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let request;
|
||||
let response;
|
||||
try {
|
||||
request = service_1.FindHatRPC.fromBinary(data);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the protobuf request could not be decoded";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = index_1.chainInterceptors(...interceptors);
|
||||
response = yield interceptor(ctx, request, (ctx, inputReq) => {
|
||||
return service.FindHat(ctx, inputReq);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = yield service.FindHat(ctx, request);
|
||||
}
|
||||
return Buffer.from(service_1.FindHatRPC.toBinary(response));
|
||||
});
|
||||
}
|
||||
function handleHaberdasherListHatProtobuf(ctx, service, data, interceptors) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
let request;
|
||||
let response;
|
||||
try {
|
||||
request = service_1.ListHatRPC.fromBinary(data);
|
||||
}
|
||||
catch (e) {
|
||||
if (e instanceof Error) {
|
||||
const msg = "the protobuf request could not be decoded";
|
||||
throw new index_1.TwirpError(index_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
if (interceptors && interceptors.length > 0) {
|
||||
const interceptor = index_1.chainInterceptors(...interceptors);
|
||||
response = yield interceptor(ctx, request, (ctx, inputReq) => {
|
||||
return service.ListHat(ctx, inputReq);
|
||||
});
|
||||
}
|
||||
else {
|
||||
response = yield service.ListHat(ctx, request);
|
||||
}
|
||||
return Buffer.from(service_1.ListHatRPC.toBinary(response));
|
||||
});
|
||||
}
|
||||
1
node_modules/twirp-ts/build/twirp/__tests__/client.test.d.ts
generated
vendored
Normal file
1
node_modules/twirp-ts/build/twirp/__tests__/client.test.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
160
node_modules/twirp-ts/build/twirp/__tests__/client.test.js
generated
vendored
Normal file
160
node_modules/twirp-ts/build/twirp/__tests__/client.test.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const http = __importStar(require("http"));
|
||||
const http_terminator_1 = require("http-terminator");
|
||||
const service_twirp_1 = require("../__mocks__/service.twirp");
|
||||
const service_1 = require("../__mocks__/service");
|
||||
const http_client_1 = require("../http.client");
|
||||
const errors_1 = require("../errors");
|
||||
describe("Twirp Clients", () => {
|
||||
let httpTerminator;
|
||||
let server;
|
||||
beforeEach(() => {
|
||||
const twirpServer = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return service_1.Hat.create({
|
||||
id: "1",
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: 100,
|
||||
variants: [],
|
||||
});
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
server = http.createServer(twirpServer.httpHandler());
|
||||
httpTerminator = http_terminator_1.createHttpTerminator({
|
||||
server,
|
||||
});
|
||||
});
|
||||
it("can call methods using the JSON client", (done) => {
|
||||
const port = 9999;
|
||||
server.listen(port, () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const client = new service_twirp_1.HaberdasherClientJSON(http_client_1.NodeHttpRPC({
|
||||
baseUrl: "http://localhost:9999/twirp",
|
||||
}));
|
||||
const hat = yield client.MakeHat({
|
||||
inches: 1,
|
||||
});
|
||||
expect(hat).toEqual({
|
||||
id: "1",
|
||||
color: "blue",
|
||||
inches: 100,
|
||||
name: "cap",
|
||||
variants: [],
|
||||
});
|
||||
yield httpTerminator.terminate();
|
||||
done();
|
||||
}));
|
||||
});
|
||||
it("can call methods using the Protobuf client", (done) => {
|
||||
const port = 9999;
|
||||
server.listen(port, () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const client = new service_twirp_1.HaberdasherClientProtobuf(http_client_1.NodeHttpRPC({
|
||||
baseUrl: "http://localhost:9999/twirp",
|
||||
}));
|
||||
const hat = yield client.MakeHat({
|
||||
inches: 1,
|
||||
});
|
||||
expect(hat).toEqual({
|
||||
id: "1",
|
||||
color: "blue",
|
||||
inches: 100,
|
||||
name: "cap",
|
||||
variants: [],
|
||||
});
|
||||
yield httpTerminator.terminate();
|
||||
done();
|
||||
}));
|
||||
});
|
||||
it("will return a TwripError when a error occur", (done) => {
|
||||
const twirpServer = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const error = new errors_1.InternalServerError("error");
|
||||
error.withMeta("test", "msg");
|
||||
error.withMeta("test2", "msg2");
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
server = http.createServer(twirpServer.httpHandler());
|
||||
httpTerminator = http_terminator_1.createHttpTerminator({
|
||||
server,
|
||||
});
|
||||
const port = 9999;
|
||||
server.listen(port, () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const client = new service_twirp_1.HaberdasherClientProtobuf(http_client_1.NodeHttpRPC({
|
||||
baseUrl: "http://localhost:9999/twirp",
|
||||
}));
|
||||
let err;
|
||||
try {
|
||||
yield client.MakeHat({
|
||||
inches: 1,
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
err = e;
|
||||
}
|
||||
expect(err).toBeInstanceOf(errors_1.TwirpError);
|
||||
const twirpErr = err;
|
||||
expect(twirpErr.code).toEqual(errors_1.TwirpErrorCode.Internal);
|
||||
expect(twirpErr.msg).toEqual("error");
|
||||
expect(twirpErr.meta).toEqual({
|
||||
test: "msg",
|
||||
test2: "msg2"
|
||||
});
|
||||
yield httpTerminator.terminate();
|
||||
done();
|
||||
}));
|
||||
});
|
||||
});
|
||||
1
node_modules/twirp-ts/build/twirp/__tests__/errors.test.d.ts
generated
vendored
Normal file
1
node_modules/twirp-ts/build/twirp/__tests__/errors.test.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
70
node_modules/twirp-ts/build/twirp/__tests__/errors.test.js
generated
vendored
Normal file
70
node_modules/twirp-ts/build/twirp/__tests__/errors.test.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const errors_1 = require("../errors");
|
||||
describe("Twirp errors", () => {
|
||||
it("will render a full error", () => {
|
||||
const innerError = new Error("some error");
|
||||
const twirpError = new errors_1.TwirpError(errors_1.TwirpErrorCode.NotFound, "not found");
|
||||
twirpError.withCause(innerError, true);
|
||||
twirpError.withMeta("meta1", "value1");
|
||||
twirpError.withMeta("meta2", "value2");
|
||||
expect(twirpError.toJSON()).toEqual(JSON.stringify({
|
||||
code: errors_1.TwirpErrorCode.NotFound,
|
||||
msg: "not found",
|
||||
meta: {
|
||||
cause: "some error",
|
||||
meta1: "value1",
|
||||
meta2: "value2",
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
||||
describe("Standard Errors", () => {
|
||||
it("will render not found error", () => {
|
||||
const twirpError = new errors_1.NotFoundError("not found");
|
||||
expect(twirpError.toJSON()).toEqual(JSON.stringify({
|
||||
code: errors_1.TwirpErrorCode.NotFound,
|
||||
msg: "not found",
|
||||
meta: {}
|
||||
}));
|
||||
});
|
||||
it("will render invalid argument error", () => {
|
||||
const twirpError = new errors_1.InvalidArgumentError("field", "error");
|
||||
expect(twirpError.toJSON()).toEqual(JSON.stringify({
|
||||
code: errors_1.TwirpErrorCode.InvalidArgument,
|
||||
msg: "field error",
|
||||
meta: {
|
||||
argument: "field",
|
||||
}
|
||||
}));
|
||||
});
|
||||
it("will render required error", () => {
|
||||
const twirpError = new errors_1.RequiredArgumentError("field");
|
||||
expect(twirpError.toJSON()).toEqual(JSON.stringify({
|
||||
code: errors_1.TwirpErrorCode.InvalidArgument,
|
||||
msg: "field is required",
|
||||
meta: {
|
||||
argument: "field",
|
||||
}
|
||||
}));
|
||||
});
|
||||
it("will render internal server error", () => {
|
||||
const twirpError = new errors_1.InternalServerError("internal");
|
||||
expect(twirpError.toJSON()).toEqual(JSON.stringify({
|
||||
code: errors_1.TwirpErrorCode.Internal,
|
||||
msg: "internal",
|
||||
meta: {}
|
||||
}));
|
||||
});
|
||||
it("will render internal server error with inner", () => {
|
||||
const inner = new Error("inner");
|
||||
const twirpError = new errors_1.InternalServerErrorWith(inner);
|
||||
expect(twirpError.toJSON()).toEqual(JSON.stringify({
|
||||
code: errors_1.TwirpErrorCode.Internal,
|
||||
msg: "inner",
|
||||
meta: {
|
||||
cause: "Error"
|
||||
}
|
||||
}));
|
||||
});
|
||||
});
|
||||
1
node_modules/twirp-ts/build/twirp/__tests__/gateway.test.d.ts
generated
vendored
Normal file
1
node_modules/twirp-ts/build/twirp/__tests__/gateway.test.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
174
node_modules/twirp-ts/build/twirp/__tests__/gateway.test.js
generated
vendored
Normal file
174
node_modules/twirp-ts/build/twirp/__tests__/gateway.test.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const http_1 = __importDefault(require("http"));
|
||||
const service_twirp_1 = require("../__mocks__/service.twirp");
|
||||
const service_1 = require("../__mocks__/service");
|
||||
const gateway_twirp_1 = require("../__mocks__/gateway.twirp");
|
||||
const supertest_1 = __importDefault(require("supertest"));
|
||||
const http_terminator_1 = require("http-terminator");
|
||||
describe("Gateway", () => {
|
||||
let server;
|
||||
let twirpServer;
|
||||
let gateway;
|
||||
beforeEach(() => {
|
||||
twirpServer = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return service_1.Hat.create({
|
||||
id: "1",
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: request.inches,
|
||||
});
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
gateway = gateway_twirp_1.createGateway();
|
||||
const twirpRewrite = gateway.twirpRewrite();
|
||||
server = http_1.default.createServer((req, resp) => {
|
||||
twirpRewrite(req, resp, () => {
|
||||
twirpServer.httpHandler()(req, resp);
|
||||
});
|
||||
});
|
||||
});
|
||||
it("call custom POST http endpoint that maps to MakeHat", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const response = yield supertest_1.default(server)
|
||||
.post('/hat')
|
||||
.send({
|
||||
inches: 30,
|
||||
})
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(response.body).toEqual({
|
||||
id: "1",
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: 30,
|
||||
});
|
||||
}));
|
||||
it("will map url parameter to request message", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const response = yield supertest_1.default(server)
|
||||
.get('/hat/12345')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(response.body).toEqual({
|
||||
hat_id: "12345",
|
||||
});
|
||||
}));
|
||||
it("will map query string parameters to request message", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const response = yield supertest_1.default(server)
|
||||
.get('/hat')
|
||||
.query({
|
||||
'filters[0].order_by': "desc",
|
||||
'filters[0].pagination.limit': 10,
|
||||
'filters[0].pagination.offset': 2,
|
||||
'filters[1].order_by': "asc",
|
||||
'filters[1].pagination.limit': 5,
|
||||
'filters[1].pagination.offset': 6,
|
||||
})
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(response.body).toEqual({
|
||||
filters: [
|
||||
{
|
||||
order_by: "desc",
|
||||
pagination: {
|
||||
limit: 10,
|
||||
offset: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
order_by: "asc",
|
||||
pagination: {
|
||||
limit: 5,
|
||||
offset: 6,
|
||||
},
|
||||
}
|
||||
]
|
||||
});
|
||||
}));
|
||||
it("will do a reverse proxy request to the handler", (done) => {
|
||||
const server = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return service_1.Hat.create({
|
||||
id: "1",
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: 100,
|
||||
variants: [],
|
||||
});
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
const gateway = gateway_twirp_1.createGateway();
|
||||
const twirpServerPort = 9999;
|
||||
const twirpServer = http_1.default.createServer(server.httpHandler());
|
||||
const httpTerminator1 = http_terminator_1.createHttpTerminator({
|
||||
server: twirpServer,
|
||||
});
|
||||
const gatewayServerPort = 9998;
|
||||
const gatewayServer = http_1.default.createServer(gateway.reverseProxy({
|
||||
baseUrl: "http://localhost:9999/twirp",
|
||||
}));
|
||||
const httpTerminator2 = http_terminator_1.createHttpTerminator({
|
||||
server: gatewayServer,
|
||||
});
|
||||
// twirp server
|
||||
twirpServer.listen(twirpServerPort, () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
// reverse proxy server
|
||||
gatewayServer.listen(gatewayServerPort, () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const response = yield supertest_1.default(gatewayServer)
|
||||
.post('/hat')
|
||||
.send({
|
||||
inches: 30,
|
||||
})
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(response.body).toEqual({
|
||||
id: "1",
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: 100,
|
||||
});
|
||||
yield Promise.all([
|
||||
httpTerminator1.terminate(),
|
||||
httpTerminator2.terminate(),
|
||||
]);
|
||||
done();
|
||||
}));
|
||||
}));
|
||||
});
|
||||
});
|
||||
1
node_modules/twirp-ts/build/twirp/__tests__/hooks.d.ts
generated
vendored
Normal file
1
node_modules/twirp-ts/build/twirp/__tests__/hooks.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
76
node_modules/twirp-ts/build/twirp/__tests__/hooks.js
generated
vendored
Normal file
76
node_modules/twirp-ts/build/twirp/__tests__/hooks.js
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const hooks_1 = require("../hooks");
|
||||
const errors_1 = require("../errors");
|
||||
const request_1 = require("../request");
|
||||
describe("Hooks behaviour", () => {
|
||||
it("can chain multiple hooks together", () => {
|
||||
const hook1Spy = jest.fn();
|
||||
const hooks1 = {
|
||||
requestReceived: (ctx) => {
|
||||
hook1Spy("received");
|
||||
},
|
||||
requestRouted: (ctx) => {
|
||||
hook1Spy("routed");
|
||||
},
|
||||
requestPrepared: (ctx) => {
|
||||
hook1Spy("prepared");
|
||||
},
|
||||
requestSent: (ctx) => {
|
||||
hook1Spy("sent");
|
||||
},
|
||||
responseSent: (ctx) => {
|
||||
hook1Spy("sent");
|
||||
},
|
||||
responsePrepared: (ctx) => {
|
||||
hook1Spy("prepared");
|
||||
},
|
||||
error: (ctx, err) => {
|
||||
hook1Spy("error");
|
||||
}
|
||||
};
|
||||
const hook2Spy = jest.fn();
|
||||
const hooks2 = {
|
||||
requestReceived: (ctx) => {
|
||||
hook2Spy("received");
|
||||
},
|
||||
requestRouted: (ctx) => {
|
||||
hook2Spy("routed");
|
||||
},
|
||||
requestPrepared: (ctx) => {
|
||||
hook2Spy("prepared");
|
||||
},
|
||||
requestSent: (ctx) => {
|
||||
hook2Spy("sent");
|
||||
},
|
||||
responseSent: (ctx) => {
|
||||
hook2Spy("sent");
|
||||
},
|
||||
responsePrepared: (ctx) => {
|
||||
hook2Spy("prepared");
|
||||
},
|
||||
error: (ctx, err) => {
|
||||
hook2Spy("error");
|
||||
}
|
||||
};
|
||||
const emptyHook = {};
|
||||
const chainedHook = hooks_1.chainHooks(hooks1, hooks2, emptyHook);
|
||||
expect(chainedHook).not.toBeNull();
|
||||
const hookNames = ["requestReceived", "requestRouted", "requestPrepared", "requestSent", "responseSent", "responsePrepared", "error"];
|
||||
hookNames.map(hookName => {
|
||||
const ctx = {
|
||||
req: jest.fn(),
|
||||
res: jest.fn(),
|
||||
contentType: request_1.TwirpContentType.Unknown,
|
||||
packageName: "",
|
||||
serviceName: "",
|
||||
methodName: "",
|
||||
};
|
||||
const hook = chainedHook[hookName];
|
||||
if (!hook) {
|
||||
throw new Error(`hook ${hookName} must be present`);
|
||||
}
|
||||
hook(ctx, new errors_1.InternalServerError("test"));
|
||||
});
|
||||
});
|
||||
});
|
||||
1
node_modules/twirp-ts/build/twirp/__tests__/interceptor.test.d.ts
generated
vendored
Normal file
1
node_modules/twirp-ts/build/twirp/__tests__/interceptor.test.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
44
node_modules/twirp-ts/build/twirp/__tests__/interceptor.test.js
generated
vendored
Normal file
44
node_modules/twirp-ts/build/twirp/__tests__/interceptor.test.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const interceptors_1 = require("../interceptors");
|
||||
const request_1 = require("../request");
|
||||
describe("Interceptor", () => {
|
||||
it("will chain interceptors", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const spy = jest.fn();
|
||||
const interceptor0 = (ctx, typedRequest, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
spy();
|
||||
const response = yield next(ctx, typedRequest);
|
||||
spy();
|
||||
return response;
|
||||
});
|
||||
const spy1 = jest.fn();
|
||||
const interceptor1 = (ctx, typedRequest, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
spy1();
|
||||
return next(ctx, typedRequest);
|
||||
});
|
||||
const chain = interceptors_1.chainInterceptors(interceptor0, interceptor1);
|
||||
const ctx = {
|
||||
req: jest.fn(),
|
||||
res: jest.fn(),
|
||||
contentType: request_1.TwirpContentType.Unknown,
|
||||
packageName: "",
|
||||
methodName: "",
|
||||
serviceName: "",
|
||||
};
|
||||
const response = yield chain(ctx, {}, (ctx1, typedRequest) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
return { test: "test" };
|
||||
}));
|
||||
expect(response).toEqual({ test: "test" });
|
||||
expect(spy).toBeCalledTimes(2);
|
||||
expect(spy1).toBeCalledTimes(1);
|
||||
}));
|
||||
});
|
||||
1
node_modules/twirp-ts/build/twirp/__tests__/server.test.d.ts
generated
vendored
Normal file
1
node_modules/twirp-ts/build/twirp/__tests__/server.test.d.ts
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export {};
|
||||
272
node_modules/twirp-ts/build/twirp/__tests__/server.test.js
generated
vendored
Normal file
272
node_modules/twirp-ts/build/twirp/__tests__/server.test.js
generated
vendored
Normal file
@@ -0,0 +1,272 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const http = __importStar(require("http"));
|
||||
const supertest_1 = __importDefault(require("supertest"));
|
||||
const service_twirp_1 = require("../__mocks__/service.twirp");
|
||||
const service_1 = require("../__mocks__/service");
|
||||
const errors_1 = require("../errors");
|
||||
describe("Server twirp specification", () => {
|
||||
let server;
|
||||
let twirpServer;
|
||||
beforeEach(() => {
|
||||
twirpServer = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return service_1.Hat.create({
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: 3,
|
||||
});
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
server = http.createServer(twirpServer.httpHandler());
|
||||
});
|
||||
it("support only POST requests", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const unsupportedMethods = ["get", "put", "patch", "delete", "options"];
|
||||
const tests = unsupportedMethods.map((method) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const dynamicSupertest = supertest_1.default(server);
|
||||
const resp = yield dynamicSupertest[method]("/invalid-url")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(404);
|
||||
expect(resp.body).toEqual({
|
||||
code: errors_1.TwirpErrorCode.BadRoute,
|
||||
msg: `unsupported method ${method.toUpperCase()} (only POST is allowed)`,
|
||||
meta: {
|
||||
twirp_invalid_route: `${method.toUpperCase()} /invalid-url`,
|
||||
}
|
||||
});
|
||||
}));
|
||||
yield Promise.all(tests);
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
}));
|
||||
it("support only application/json and application/protobuf content-type", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const resp = yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'invalid/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(404);
|
||||
expect(resp.body).toEqual({
|
||||
code: "bad_route",
|
||||
meta: {
|
||||
twirp_invalid_route: "POST /twirp/twirp.example.haberdasher.Haberdasher/MakeHat"
|
||||
},
|
||||
msg: "unexpected Content-Type: invalid/json"
|
||||
});
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/protobuf')
|
||||
.expect('Content-Type', "application/protobuf")
|
||||
.expect(200);
|
||||
}));
|
||||
describe("url must match [<prefix>]/[<package>.]<Service>/<Method>", () => {
|
||||
it("will error if url is malformed", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const resp = yield supertest_1.default(server).post("/invalid-url-format")
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(404);
|
||||
expect(resp.body).toEqual({
|
||||
code: errors_1.TwirpErrorCode.BadRoute,
|
||||
msg: `no handler for path /invalid-url-format`,
|
||||
meta: {
|
||||
twirp_invalid_route: `POST /invalid-url-format`,
|
||||
}
|
||||
});
|
||||
}));
|
||||
it("succeeds when url is properly constructed", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
}));
|
||||
it("must respect the prefix", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const resp = yield supertest_1.default(server).post("/twirp-not-existing/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(404);
|
||||
expect(resp.body).toEqual({
|
||||
code: "bad_route",
|
||||
meta: {
|
||||
twirp_invalid_route: "POST /twirp-not-existing/twirp.example.haberdasher.Haberdasher/MakeHat"
|
||||
},
|
||||
msg: "invalid path prefix /twirp-not-existing, expected /twirp, on path /twirp-not-existing/twirp.example.haberdasher.Haberdasher/MakeHat"
|
||||
});
|
||||
}));
|
||||
it("must have a specified handler", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const resp = yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHatDoesntExists")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(404);
|
||||
expect(resp.body).toEqual({
|
||||
code: "bad_route",
|
||||
meta: {
|
||||
twirp_invalid_route: "POST /twirp/twirp.example.haberdasher.Haberdasher/MakeHatDoesntExists"
|
||||
},
|
||||
msg: "no handler for path /twirp/twirp.example.haberdasher.Haberdasher/MakeHatDoesntExists"
|
||||
});
|
||||
}));
|
||||
it("support rawBody Buffer", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
server = http.createServer((req, res) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
req.rawBody = Buffer.from(JSON.stringify({
|
||||
hatId: '1234',
|
||||
}));
|
||||
yield twirpServer.httpHandler()(req, res);
|
||||
}));
|
||||
const response = yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/FindHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(response.body).toEqual({
|
||||
hat_id: '1234'
|
||||
});
|
||||
}));
|
||||
});
|
||||
});
|
||||
describe("Hooks & Interceptors", () => {
|
||||
let server;
|
||||
let twirpServer;
|
||||
beforeEach(() => {
|
||||
twirpServer = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return service_1.Hat.create({
|
||||
name: "cap",
|
||||
color: "blue",
|
||||
inches: 3,
|
||||
});
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
server = http.createServer(twirpServer.httpHandler());
|
||||
});
|
||||
it("can add interceptors", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const interceptorSpy = jest.fn();
|
||||
twirpServer.use((ctx, req, next) => __awaiter(void 0, void 0, void 0, function* () {
|
||||
interceptorSpy();
|
||||
const resp = yield next(ctx, next);
|
||||
interceptorSpy();
|
||||
return resp;
|
||||
}));
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(interceptorSpy).toBeCalledTimes(2);
|
||||
}));
|
||||
it("can add hooks", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
const hookSpy = jest.fn();
|
||||
twirpServer.use({
|
||||
requestReceived: (ctx) => {
|
||||
hookSpy("received");
|
||||
},
|
||||
requestRouted: (ctx) => {
|
||||
hookSpy("routed");
|
||||
},
|
||||
requestPrepared: (ctx) => {
|
||||
hookSpy("prepared");
|
||||
},
|
||||
requestSent: (ctx) => {
|
||||
hookSpy("sent");
|
||||
},
|
||||
error: (ctx, err) => {
|
||||
hookSpy("error"); // will not be called
|
||||
}
|
||||
});
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(200);
|
||||
expect(hookSpy).toBeCalledTimes(4);
|
||||
expect(hookSpy).toBeCalledWith("received");
|
||||
expect(hookSpy).toBeCalledWith("routed");
|
||||
expect(hookSpy).toBeCalledWith("prepared");
|
||||
expect(hookSpy).toBeCalledWith("sent");
|
||||
}));
|
||||
it("will invoke the error hook when an error occurs", () => __awaiter(void 0, void 0, void 0, function* () {
|
||||
twirpServer = service_twirp_1.createHaberdasherServer({
|
||||
MakeHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
throw new errors_1.TwirpError(errors_1.TwirpErrorCode.Internal, "test error");
|
||||
});
|
||||
},
|
||||
FindHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
},
|
||||
ListHat(ctx, request) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
return request;
|
||||
});
|
||||
}
|
||||
});
|
||||
const hookSpy = jest.fn();
|
||||
twirpServer.use({
|
||||
error: (ctx, err) => {
|
||||
hookSpy("error"); // will not be called
|
||||
}
|
||||
});
|
||||
server = http.createServer(twirpServer.httpHandler());
|
||||
yield supertest_1.default(server).post("/twirp/twirp.example.haberdasher.Haberdasher/MakeHat")
|
||||
.set('Content-Type', 'application/json')
|
||||
.expect('Content-Type', "application/json")
|
||||
.expect(500);
|
||||
expect(hookSpy).toBeCalledWith("error");
|
||||
}));
|
||||
});
|
||||
11
node_modules/twirp-ts/build/twirp/context.d.ts
generated
vendored
Normal file
11
node_modules/twirp-ts/build/twirp/context.d.ts
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
/// <reference types="node" />
|
||||
import * as http from "http";
|
||||
import { TwirpContentType } from "./request";
|
||||
export interface TwirpContext<Request = http.IncomingMessage, Response = http.ServerResponse> {
|
||||
readonly packageName: string;
|
||||
readonly serviceName: string;
|
||||
readonly methodName: string;
|
||||
readonly contentType: TwirpContentType;
|
||||
readonly req: Request;
|
||||
readonly res: Response;
|
||||
}
|
||||
2
node_modules/twirp-ts/build/twirp/context.js
generated
vendored
Normal file
2
node_modules/twirp-ts/build/twirp/context.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
104
node_modules/twirp-ts/build/twirp/errors.d.ts
generated
vendored
Normal file
104
node_modules/twirp-ts/build/twirp/errors.d.ts
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
* Represents a twirp error
|
||||
*/
|
||||
export declare class TwirpError extends Error {
|
||||
readonly msg: string;
|
||||
readonly code: TwirpErrorCode;
|
||||
readonly meta: Record<string, string>;
|
||||
private _originalCause?;
|
||||
constructor(code: TwirpErrorCode, msg: string);
|
||||
/**
|
||||
* Adds a metadata kv to the error
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
withMeta(key: string, value: string): this;
|
||||
/**
|
||||
* Returns a single metadata value
|
||||
* return "" if not found
|
||||
* @param key
|
||||
*/
|
||||
getMeta(key: string): string;
|
||||
/**
|
||||
* Add the original error cause
|
||||
* @param err
|
||||
* @param addMeta
|
||||
*/
|
||||
withCause(err: Error, addMeta?: boolean): this;
|
||||
cause(): Error | undefined;
|
||||
/**
|
||||
* Returns the error representation to JSON
|
||||
*/
|
||||
toJSON(): string;
|
||||
/**
|
||||
* Create a twirp error from an object
|
||||
* @param obj
|
||||
*/
|
||||
static fromObject(obj: Record<string, any>): TwirpError;
|
||||
}
|
||||
/**
|
||||
* NotFoundError constructor for the common NotFound error.
|
||||
*/
|
||||
export declare class NotFoundError extends TwirpError {
|
||||
constructor(msg: string);
|
||||
}
|
||||
/**
|
||||
* InvalidArgumentError constructor for the common InvalidArgument error. Can be
|
||||
* used when an argument has invalid format, is a number out of range, is a bad
|
||||
* option, etc).
|
||||
*/
|
||||
export declare class InvalidArgumentError extends TwirpError {
|
||||
constructor(argument: string, validationMsg: string);
|
||||
}
|
||||
/**
|
||||
* RequiredArgumentError is a more specific constructor for InvalidArgument
|
||||
* error. Should be used when the argument is required (expected to have a
|
||||
* non-zero value).
|
||||
*/
|
||||
export declare class RequiredArgumentError extends InvalidArgumentError {
|
||||
constructor(argument: string);
|
||||
}
|
||||
/**
|
||||
* InternalError constructor for the common Internal error. Should be used to
|
||||
* specify that something bad or unexpected happened.
|
||||
*/
|
||||
export declare class InternalServerError extends TwirpError {
|
||||
constructor(msg: string);
|
||||
}
|
||||
/**
|
||||
* InternalErrorWith makes an internal error, wrapping the original error and using it
|
||||
* for the error message, and with metadata "cause" with the original error type.
|
||||
* This function is used by Twirp services to wrap non-Twirp errors as internal errors.
|
||||
* The wrapped error can be extracted later with err.cause()
|
||||
*/
|
||||
export declare class InternalServerErrorWith extends InternalServerError {
|
||||
constructor(err: Error);
|
||||
}
|
||||
/**
|
||||
* A standard BadRoute Error
|
||||
*/
|
||||
export declare class BadRouteError extends TwirpError {
|
||||
constructor(msg: string, method: string, url: string);
|
||||
}
|
||||
export declare enum TwirpErrorCode {
|
||||
Canceled = "canceled",
|
||||
Unknown = "unknown",
|
||||
InvalidArgument = "invalid_argument",
|
||||
Malformed = "malformed",
|
||||
DeadlineExceeded = "deadline_exceeded",
|
||||
NotFound = "not_found",
|
||||
BadRoute = "bad_route",
|
||||
AlreadyExists = "already_exists",
|
||||
PermissionDenied = "permission_denied",
|
||||
Unauthenticated = "unauthenticated",
|
||||
ResourceExhausted = "resource_exhausted",
|
||||
FailedPrecondition = "failed_precondition",
|
||||
Aborted = "aborted",
|
||||
OutOfRange = "out_of_range",
|
||||
Unimplemented = "unimplemented",
|
||||
Internal = "internal",
|
||||
Unavailable = "unavailable",
|
||||
DataLoss = "data_loss"
|
||||
}
|
||||
export declare function httpStatusFromErrorCode(code: TwirpErrorCode): number;
|
||||
export declare function isValidErrorCode(code: TwirpErrorCode): boolean;
|
||||
271
node_modules/twirp-ts/build/twirp/errors.js
generated
vendored
Normal file
271
node_modules/twirp-ts/build/twirp/errors.js
generated
vendored
Normal file
@@ -0,0 +1,271 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isValidErrorCode = exports.httpStatusFromErrorCode = exports.TwirpErrorCode = exports.BadRouteError = exports.InternalServerErrorWith = exports.InternalServerError = exports.RequiredArgumentError = exports.InvalidArgumentError = exports.NotFoundError = exports.TwirpError = void 0;
|
||||
/**
|
||||
* Represents a twirp error
|
||||
*/
|
||||
class TwirpError extends Error {
|
||||
constructor(code, msg) {
|
||||
super(msg);
|
||||
this.code = TwirpErrorCode.Internal;
|
||||
this.meta = {};
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
Object.setPrototypeOf(this, TwirpError.prototype);
|
||||
}
|
||||
/**
|
||||
* Adds a metadata kv to the error
|
||||
* @param key
|
||||
* @param value
|
||||
*/
|
||||
withMeta(key, value) {
|
||||
this.meta[key] = value;
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Returns a single metadata value
|
||||
* return "" if not found
|
||||
* @param key
|
||||
*/
|
||||
getMeta(key) {
|
||||
return this.meta[key] || "";
|
||||
}
|
||||
/**
|
||||
* Add the original error cause
|
||||
* @param err
|
||||
* @param addMeta
|
||||
*/
|
||||
withCause(err, addMeta = false) {
|
||||
this._originalCause = err;
|
||||
if (addMeta) {
|
||||
this.withMeta("cause", err.message);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
cause() {
|
||||
return this._originalCause;
|
||||
}
|
||||
/**
|
||||
* Returns the error representation to JSON
|
||||
*/
|
||||
toJSON() {
|
||||
try {
|
||||
return JSON.stringify({
|
||||
code: this.code,
|
||||
msg: this.msg,
|
||||
meta: this.meta,
|
||||
});
|
||||
}
|
||||
catch (e) {
|
||||
return `{"code": "internal", "msg": "There was an error but it could not be serialized into JSON"}`;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Create a twirp error from an object
|
||||
* @param obj
|
||||
*/
|
||||
static fromObject(obj) {
|
||||
const code = obj["code"] || TwirpErrorCode.Unknown;
|
||||
const msg = obj["msg"] || "unknown";
|
||||
const error = new TwirpError(code, msg);
|
||||
if (obj["meta"]) {
|
||||
Object.keys(obj["meta"]).forEach((key) => {
|
||||
error.withMeta(key, obj["meta"][key]);
|
||||
});
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
exports.TwirpError = TwirpError;
|
||||
/**
|
||||
* NotFoundError constructor for the common NotFound error.
|
||||
*/
|
||||
class NotFoundError extends TwirpError {
|
||||
constructor(msg) {
|
||||
super(TwirpErrorCode.NotFound, msg);
|
||||
}
|
||||
}
|
||||
exports.NotFoundError = NotFoundError;
|
||||
/**
|
||||
* InvalidArgumentError constructor for the common InvalidArgument error. Can be
|
||||
* used when an argument has invalid format, is a number out of range, is a bad
|
||||
* option, etc).
|
||||
*/
|
||||
class InvalidArgumentError extends TwirpError {
|
||||
constructor(argument, validationMsg) {
|
||||
super(TwirpErrorCode.InvalidArgument, argument + " " + validationMsg);
|
||||
this.withMeta("argument", argument);
|
||||
}
|
||||
}
|
||||
exports.InvalidArgumentError = InvalidArgumentError;
|
||||
/**
|
||||
* RequiredArgumentError is a more specific constructor for InvalidArgument
|
||||
* error. Should be used when the argument is required (expected to have a
|
||||
* non-zero value).
|
||||
*/
|
||||
class RequiredArgumentError extends InvalidArgumentError {
|
||||
constructor(argument) {
|
||||
super(argument, "is required");
|
||||
}
|
||||
}
|
||||
exports.RequiredArgumentError = RequiredArgumentError;
|
||||
/**
|
||||
* InternalError constructor for the common Internal error. Should be used to
|
||||
* specify that something bad or unexpected happened.
|
||||
*/
|
||||
class InternalServerError extends TwirpError {
|
||||
constructor(msg) {
|
||||
super(TwirpErrorCode.Internal, msg);
|
||||
}
|
||||
}
|
||||
exports.InternalServerError = InternalServerError;
|
||||
/**
|
||||
* InternalErrorWith makes an internal error, wrapping the original error and using it
|
||||
* for the error message, and with metadata "cause" with the original error type.
|
||||
* This function is used by Twirp services to wrap non-Twirp errors as internal errors.
|
||||
* The wrapped error can be extracted later with err.cause()
|
||||
*/
|
||||
class InternalServerErrorWith extends InternalServerError {
|
||||
constructor(err) {
|
||||
super(err.message);
|
||||
this.withMeta("cause", err.name);
|
||||
this.withCause(err);
|
||||
}
|
||||
}
|
||||
exports.InternalServerErrorWith = InternalServerErrorWith;
|
||||
/**
|
||||
* A standard BadRoute Error
|
||||
*/
|
||||
class BadRouteError extends TwirpError {
|
||||
constructor(msg, method, url) {
|
||||
super(TwirpErrorCode.BadRoute, msg);
|
||||
this.withMeta("twirp_invalid_route", method + " " + url);
|
||||
}
|
||||
}
|
||||
exports.BadRouteError = BadRouteError;
|
||||
var TwirpErrorCode;
|
||||
(function (TwirpErrorCode) {
|
||||
// Canceled indicates the operation was cancelled (typically by the caller).
|
||||
TwirpErrorCode["Canceled"] = "canceled";
|
||||
// Unknown error. For example when handling errors raised by APIs that do not
|
||||
// return enough error information.
|
||||
TwirpErrorCode["Unknown"] = "unknown";
|
||||
// InvalidArgument indicates client specified an invalid argument. It
|
||||
// indicates arguments that are problematic regardless of the state of the
|
||||
// system (i.e. a malformed file name, required argument, number out of range,
|
||||
// etc.).
|
||||
TwirpErrorCode["InvalidArgument"] = "invalid_argument";
|
||||
// Malformed indicates an error occurred while decoding the client's request.
|
||||
// This may mean that the message was encoded improperly, or that there is a
|
||||
// disagreement in message format between the client and server.
|
||||
TwirpErrorCode["Malformed"] = "malformed";
|
||||
// DeadlineExceeded means operation expired before completion. For operations
|
||||
// that change the state of the system, this error may be returned even if the
|
||||
// operation has completed successfully (timeout).
|
||||
TwirpErrorCode["DeadlineExceeded"] = "deadline_exceeded";
|
||||
// NotFound means some requested entity was not found.
|
||||
TwirpErrorCode["NotFound"] = "not_found";
|
||||
// BadRoute means that the requested URL path wasn't routable to a Twirp
|
||||
// service and method. This is returned by the generated server, and usually
|
||||
// shouldn't be returned by applications. Instead, applications should use
|
||||
// NotFound or Unimplemented.
|
||||
TwirpErrorCode["BadRoute"] = "bad_route";
|
||||
// AlreadyExists means an attempt to create an entity failed because one
|
||||
// already exists.
|
||||
TwirpErrorCode["AlreadyExists"] = "already_exists";
|
||||
// PermissionDenied indicates the caller does not have permission to execute
|
||||
// the specified operation. It must not be used if the caller cannot be
|
||||
// identified (Unauthenticated).
|
||||
TwirpErrorCode["PermissionDenied"] = "permission_denied";
|
||||
// Unauthenticated indicates the request does not have valid authentication
|
||||
// credentials for the operation.
|
||||
TwirpErrorCode["Unauthenticated"] = "unauthenticated";
|
||||
// ResourceExhausted indicates some resource has been exhausted, perhaps a
|
||||
// per-user quota, or perhaps the entire file system is out of space.
|
||||
TwirpErrorCode["ResourceExhausted"] = "resource_exhausted";
|
||||
// FailedPrecondition indicates operation was rejected because the system is
|
||||
// not in a state required for the operation's execution. For example, doing
|
||||
// an rmdir operation on a directory that is non-empty, or on a non-directory
|
||||
// object, or when having conflicting read-modify-write on the same resource.
|
||||
TwirpErrorCode["FailedPrecondition"] = "failed_precondition";
|
||||
// Aborted indicates the operation was aborted, typically due to a concurrency
|
||||
// issue like sequencer check failures, transaction aborts, etc.
|
||||
TwirpErrorCode["Aborted"] = "aborted";
|
||||
// OutOfRange means operation was attempted past the valid range. For example,
|
||||
// seeking or reading past end of a paginated collection.
|
||||
//
|
||||
// Unlike InvalidArgument, this error indicates a problem that may be fixed if
|
||||
// the system state changes (i.e. adding more items to the collection).
|
||||
//
|
||||
// There is a fair bit of overlap between FailedPrecondition and OutOfRange.
|
||||
// We recommend using OutOfRange (the more specific error) when it applies so
|
||||
// that callers who are iterating through a space can easily look for an
|
||||
// OutOfRange error to detect when they are done.
|
||||
TwirpErrorCode["OutOfRange"] = "out_of_range";
|
||||
// Unimplemented indicates operation is not implemented or not
|
||||
// supported/enabled in this service.
|
||||
TwirpErrorCode["Unimplemented"] = "unimplemented";
|
||||
// Internal errors. When some invariants expected by the underlying system
|
||||
// have been broken. In other words, something bad happened in the library or
|
||||
// backend service. Do not confuse with HTTP Internal Server Error; an
|
||||
// Internal error could also happen on the client code, i.e. when parsing a
|
||||
// server response.
|
||||
TwirpErrorCode["Internal"] = "internal";
|
||||
// Unavailable indicates the service is currently unavailable. This is a most
|
||||
// likely a transient condition and may be corrected by retrying with a
|
||||
// backoff.
|
||||
TwirpErrorCode["Unavailable"] = "unavailable";
|
||||
// DataLoss indicates unrecoverable data loss or corruption.
|
||||
TwirpErrorCode["DataLoss"] = "data_loss";
|
||||
})(TwirpErrorCode = exports.TwirpErrorCode || (exports.TwirpErrorCode = {}));
|
||||
// ServerHTTPStatusFromErrorCode maps a Twirp error type into a similar HTTP
|
||||
// response status. It is used by the Twirp server handler to set the HTTP
|
||||
// response status code. Returns 0 if the ErrorCode is invalid.
|
||||
function httpStatusFromErrorCode(code) {
|
||||
switch (code) {
|
||||
case TwirpErrorCode.Canceled:
|
||||
return 408; // RequestTimeout
|
||||
case TwirpErrorCode.Unknown:
|
||||
return 500; // Internal Server Error
|
||||
case TwirpErrorCode.InvalidArgument:
|
||||
return 400; // BadRequest
|
||||
case TwirpErrorCode.Malformed:
|
||||
return 400; // BadRequest
|
||||
case TwirpErrorCode.DeadlineExceeded:
|
||||
return 408; // RequestTimeout
|
||||
case TwirpErrorCode.NotFound:
|
||||
return 404; // Not Found
|
||||
case TwirpErrorCode.BadRoute:
|
||||
return 404; // Not Found
|
||||
case TwirpErrorCode.AlreadyExists:
|
||||
return 409; // Conflict
|
||||
case TwirpErrorCode.PermissionDenied:
|
||||
return 403; // Forbidden
|
||||
case TwirpErrorCode.Unauthenticated:
|
||||
return 401; // Unauthorized
|
||||
case TwirpErrorCode.ResourceExhausted:
|
||||
return 429; // Too Many Requests
|
||||
case TwirpErrorCode.FailedPrecondition:
|
||||
return 412; // Precondition Failed
|
||||
case TwirpErrorCode.Aborted:
|
||||
return 409; // Conflict
|
||||
case TwirpErrorCode.OutOfRange:
|
||||
return 400; // Bad Request
|
||||
case TwirpErrorCode.Unimplemented:
|
||||
return 501; // Not Implemented
|
||||
case TwirpErrorCode.Internal:
|
||||
return 500; // Internal Server Error
|
||||
case TwirpErrorCode.Unavailable:
|
||||
return 503; // Service Unavailable
|
||||
case TwirpErrorCode.DataLoss:
|
||||
return 500; // Internal Server Error
|
||||
default:
|
||||
return 0; // Invalid!
|
||||
}
|
||||
}
|
||||
exports.httpStatusFromErrorCode = httpStatusFromErrorCode;
|
||||
// IsValidErrorCode returns true if is one of the valid predefined constants.
|
||||
function isValidErrorCode(code) {
|
||||
return httpStatusFromErrorCode(code) != 0;
|
||||
}
|
||||
exports.isValidErrorCode = isValidErrorCode;
|
||||
72
node_modules/twirp-ts/build/twirp/gateway.d.ts
generated
vendored
Normal file
72
node_modules/twirp-ts/build/twirp/gateway.d.ts
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/// <reference types="node" />
|
||||
import * as http from "http";
|
||||
import { MatchFunction, MatchResult } from "path-to-regexp";
|
||||
import { HttpClientOptions } from "./http.client";
|
||||
export declare enum Pattern {
|
||||
POST = "post",
|
||||
GET = "get",
|
||||
PATCH = "patch",
|
||||
PUT = "put",
|
||||
DELETE = "delete"
|
||||
}
|
||||
export interface HttpRoute {
|
||||
serviceName: string;
|
||||
methodName: string;
|
||||
packageName: string;
|
||||
matchingPath: string;
|
||||
matcher: MatchFunction;
|
||||
httpMethod: Pattern;
|
||||
bodyKey?: string;
|
||||
responseBodyKey?: string;
|
||||
additionalBindings?: HttpRoute;
|
||||
}
|
||||
declare type RouteRules = {
|
||||
[key in Pattern]: HttpRoute[];
|
||||
};
|
||||
/**
|
||||
* The Gateway proxies http requests to Twirp Compliant
|
||||
* handlers
|
||||
*/
|
||||
export declare class Gateway {
|
||||
readonly routes: RouteRules;
|
||||
constructor(routes: RouteRules);
|
||||
/**
|
||||
* Middleware that rewrite the current request
|
||||
* to a Twirp compliant request
|
||||
*/
|
||||
twirpRewrite(prefix?: string): (req: http.IncomingMessage, resp: http.ServerResponse, next: (err?: Error | undefined) => void) => void;
|
||||
/**
|
||||
* Rewrite an incoming request to a Twirp compliant request
|
||||
* @param req
|
||||
* @param resp
|
||||
* @param prefix
|
||||
*/
|
||||
rewrite(req: http.IncomingMessage, resp: http.ServerResponse, prefix?: string): Promise<void>;
|
||||
/**
|
||||
* Create a reverse proxy handler to
|
||||
* proxy http requests to Twirp Compliant handlers
|
||||
* @param httpClientOption
|
||||
*/
|
||||
reverseProxy(httpClientOption: HttpClientOptions): (req: http.IncomingMessage, res: http.ServerResponse) => Promise<void>;
|
||||
/**
|
||||
* Prepares twirp body requests using http.google.annotions
|
||||
* compliant spec
|
||||
*
|
||||
* @param req
|
||||
* @param match
|
||||
* @param route
|
||||
* @protected
|
||||
*/
|
||||
protected prepareTwirpBody(req: http.IncomingMessage, match: MatchResult, route: HttpRoute): Promise<Record<string, any>>;
|
||||
/**
|
||||
* Matches a route
|
||||
* @param req
|
||||
*/
|
||||
matchRoute(req: http.IncomingMessage): [MatchResult, HttpRoute];
|
||||
/**
|
||||
* Parse query string
|
||||
* @param queryString
|
||||
*/
|
||||
parseQueryString(queryString: string): object;
|
||||
}
|
||||
export {};
|
||||
207
node_modules/twirp-ts/build/twirp/gateway.js
generated
vendored
Normal file
207
node_modules/twirp-ts/build/twirp/gateway.js
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __rest = (this && this.__rest) || function (s, e) {
|
||||
var t = {};
|
||||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
||||
t[p] = s[p];
|
||||
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
||||
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
||||
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
||||
t[p[i]] = s[p[i]];
|
||||
}
|
||||
return t;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.Gateway = exports.Pattern = void 0;
|
||||
const querystring_1 = require("querystring");
|
||||
const dotObject = __importStar(require("dot-object"));
|
||||
const request_1 = require("./request");
|
||||
const errors_1 = require("./errors");
|
||||
const http_client_1 = require("./http.client");
|
||||
const server_1 = require("./server");
|
||||
var Pattern;
|
||||
(function (Pattern) {
|
||||
Pattern["POST"] = "post";
|
||||
Pattern["GET"] = "get";
|
||||
Pattern["PATCH"] = "patch";
|
||||
Pattern["PUT"] = "put";
|
||||
Pattern["DELETE"] = "delete";
|
||||
})(Pattern = exports.Pattern || (exports.Pattern = {}));
|
||||
/**
|
||||
* The Gateway proxies http requests to Twirp Compliant
|
||||
* handlers
|
||||
*/
|
||||
class Gateway {
|
||||
constructor(routes) {
|
||||
this.routes = routes;
|
||||
}
|
||||
/**
|
||||
* Middleware that rewrite the current request
|
||||
* to a Twirp compliant request
|
||||
*/
|
||||
twirpRewrite(prefix = "/twirp") {
|
||||
return (req, resp, next) => {
|
||||
this.rewrite(req, resp, prefix)
|
||||
.then(() => next())
|
||||
.catch((e) => {
|
||||
if (e instanceof errors_1.TwirpError) {
|
||||
if (e.code !== errors_1.TwirpErrorCode.NotFound) {
|
||||
server_1.writeError(resp, e);
|
||||
}
|
||||
else {
|
||||
next();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Rewrite an incoming request to a Twirp compliant request
|
||||
* @param req
|
||||
* @param resp
|
||||
* @param prefix
|
||||
*/
|
||||
rewrite(req, resp, prefix = "/twirp") {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const [match, route] = this.matchRoute(req);
|
||||
const body = yield this.prepareTwirpBody(req, match, route);
|
||||
const twirpUrl = `${prefix}/${route.packageName}.${route.serviceName}/${route.methodName}`;
|
||||
req.url = twirpUrl;
|
||||
req.originalUrl = twirpUrl;
|
||||
req.method = "POST";
|
||||
req.headers["content-type"] = "application/json";
|
||||
req.rawBody = Buffer.from(JSON.stringify(body));
|
||||
if (route.responseBodyKey) {
|
||||
const endFn = resp.end.bind(resp);
|
||||
resp.end = function (chunk) {
|
||||
if (resp.statusCode === 200) {
|
||||
endFn(`{ "${route.responseBodyKey}": ${chunk} }`);
|
||||
}
|
||||
else {
|
||||
endFn(chunk);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Create a reverse proxy handler to
|
||||
* proxy http requests to Twirp Compliant handlers
|
||||
* @param httpClientOption
|
||||
*/
|
||||
reverseProxy(httpClientOption) {
|
||||
const client = http_client_1.NodeHttpRPC(httpClientOption);
|
||||
return (req, res) => __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const [match, route] = this.matchRoute(req);
|
||||
const body = yield this.prepareTwirpBody(req, match, route);
|
||||
const response = yield client.request(`${route.packageName}.${route.serviceName}`, route.methodName, "application/json", body);
|
||||
res.statusCode = 200;
|
||||
res.setHeader("content-type", "application/json");
|
||||
let jsonResponse;
|
||||
if (route.responseBodyKey) {
|
||||
jsonResponse = JSON.stringify({ [route.responseBodyKey]: response });
|
||||
}
|
||||
else {
|
||||
jsonResponse = JSON.stringify(response);
|
||||
}
|
||||
res.end(jsonResponse);
|
||||
}
|
||||
catch (e) {
|
||||
server_1.writeError(res, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Prepares twirp body requests using http.google.annotions
|
||||
* compliant spec
|
||||
*
|
||||
* @param req
|
||||
* @param match
|
||||
* @param route
|
||||
* @protected
|
||||
*/
|
||||
prepareTwirpBody(req, match, route) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const _a = match.params, { query_string } = _a, params = __rest(_a, ["query_string"]);
|
||||
let requestBody = Object.assign({}, params);
|
||||
if (query_string && route.bodyKey !== "*") {
|
||||
const queryParams = this.parseQueryString(query_string);
|
||||
requestBody = Object.assign(Object.assign({}, queryParams), requestBody);
|
||||
}
|
||||
let body = {};
|
||||
if (route.bodyKey) {
|
||||
const data = yield request_1.getRequestData(req);
|
||||
try {
|
||||
const jsonBody = JSON.parse(data.toString() || "{}");
|
||||
if (route.bodyKey === "*") {
|
||||
body = jsonBody;
|
||||
}
|
||||
else {
|
||||
body[route.bodyKey] = jsonBody;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
const msg = "the json request could not be decoded";
|
||||
throw new errors_1.TwirpError(errors_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
|
||||
}
|
||||
}
|
||||
return Object.assign(Object.assign({}, body), requestBody);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Matches a route
|
||||
* @param req
|
||||
*/
|
||||
matchRoute(req) {
|
||||
var _a;
|
||||
const httpMethod = (_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase();
|
||||
if (!httpMethod) {
|
||||
throw new errors_1.BadRouteError(`method not allowed`, req.method || "", req.url || "");
|
||||
}
|
||||
const routes = this.routes[httpMethod];
|
||||
for (const route of routes) {
|
||||
const match = route.matcher(req.url || "/");
|
||||
if (match) {
|
||||
return [match, route];
|
||||
}
|
||||
}
|
||||
throw new errors_1.NotFoundError(`url ${req.url} not found`);
|
||||
}
|
||||
/**
|
||||
* Parse query string
|
||||
* @param queryString
|
||||
*/
|
||||
parseQueryString(queryString) {
|
||||
const queryParams = querystring_1.parse(queryString.replace("?", ""));
|
||||
return dotObject.object(queryParams);
|
||||
}
|
||||
}
|
||||
exports.Gateway = Gateway;
|
||||
15
node_modules/twirp-ts/build/twirp/hooks.d.ts
generated
vendored
Normal file
15
node_modules/twirp-ts/build/twirp/hooks.d.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
import { TwirpContext } from "./context";
|
||||
import { TwirpError } from "./errors";
|
||||
export interface ServerHooks<T extends TwirpContext = TwirpContext> {
|
||||
requestReceived?: (ctx: T) => void | Promise<void>;
|
||||
requestRouted?: (ctx: T) => void | Promise<void>;
|
||||
/**@deprecated Use responsePrepared instead*/
|
||||
requestPrepared?: (ctx: T) => void | Promise<void>;
|
||||
responsePrepared?: (ctx: T) => void | Promise<void>;
|
||||
/**@deprecated Use responseSent instead*/
|
||||
requestSent?: (ctx: T) => void | Promise<void>;
|
||||
responseSent?: (ctx: T) => void | Promise<void>;
|
||||
error?: (ctx: T, err: TwirpError) => void | Promise<void>;
|
||||
}
|
||||
export declare function chainHooks<T extends TwirpContext = TwirpContext>(...hooks: ServerHooks<T>[]): ServerHooks<T> | null;
|
||||
export declare function isHook<T extends TwirpContext = TwirpContext>(object: any): object is ServerHooks<T>;
|
||||
114
node_modules/twirp-ts/build/twirp/hooks.js
generated
vendored
Normal file
114
node_modules/twirp-ts/build/twirp/hooks.js
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isHook = exports.chainHooks = void 0;
|
||||
// ChainHooks creates a new ServerHook which chains the callbacks in
|
||||
// each of the constituent hooks passed in. Each hook function will be
|
||||
// called in the order of the ServerHooks values passed in.
|
||||
//
|
||||
// For the erroring hooks, RequestReceived and RequestRouted, any returned
|
||||
// errors prevent processing by later hooks.
|
||||
function chainHooks(...hooks) {
|
||||
if (hooks.length === 0) {
|
||||
return null;
|
||||
}
|
||||
if (hooks.length === 1) {
|
||||
return hooks[0];
|
||||
}
|
||||
const serverHook = {
|
||||
requestReceived(ctx) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.requestReceived) {
|
||||
continue;
|
||||
}
|
||||
yield hook.requestReceived(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
requestPrepared(ctx) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.requestPrepared) {
|
||||
continue;
|
||||
}
|
||||
console.warn("hook requestPrepared is deprecated and will be removed in the next release. " +
|
||||
"Please use responsePrepared instead.");
|
||||
yield hook.requestPrepared(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
responsePrepared(ctx) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.responsePrepared) {
|
||||
continue;
|
||||
}
|
||||
yield hook.responsePrepared(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
requestSent(ctx) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.requestSent) {
|
||||
continue;
|
||||
}
|
||||
console.warn("hook requestSent is deprecated and will be removed in the next release. " +
|
||||
"Please use responseSent instead.");
|
||||
yield hook.requestSent(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
responseSent(ctx) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.responseSent) {
|
||||
continue;
|
||||
}
|
||||
yield hook.responseSent(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
requestRouted(ctx) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.requestRouted) {
|
||||
continue;
|
||||
}
|
||||
yield hook.requestRouted(ctx);
|
||||
}
|
||||
});
|
||||
},
|
||||
error(ctx, err) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
for (const hook of hooks) {
|
||||
if (!hook.error) {
|
||||
continue;
|
||||
}
|
||||
yield hook.error(ctx, err);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
return serverHook;
|
||||
}
|
||||
exports.chainHooks = chainHooks;
|
||||
function isHook(object) {
|
||||
return ("requestReceived" in object ||
|
||||
"requestPrepared" in object ||
|
||||
"requestSent" in object ||
|
||||
"requestRouted" in object ||
|
||||
"responsePrepared" in object ||
|
||||
"responseSent" in object ||
|
||||
"error" in object);
|
||||
}
|
||||
exports.isHook = isHook;
|
||||
24
node_modules/twirp-ts/build/twirp/http.client.d.ts
generated
vendored
Normal file
24
node_modules/twirp-ts/build/twirp/http.client.d.ts
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/// <reference types="node" />
|
||||
import * as http from "http";
|
||||
import * as https from "https";
|
||||
import { TwirpError } from "./errors";
|
||||
export interface Rpc {
|
||||
request(service: string, method: string, contentType: "application/json" | "application/protobuf", data: object | Uint8Array): Promise<object | Uint8Array>;
|
||||
}
|
||||
export declare type HttpClientOptions = Omit<http.RequestOptions | https.RequestOptions, "path" | "host" | "port"> & {
|
||||
baseUrl: string;
|
||||
};
|
||||
/**
|
||||
* a node HTTP RPC implementation
|
||||
* @param options
|
||||
* @constructor
|
||||
*/
|
||||
export declare const NodeHttpRPC: (options: HttpClientOptions) => Rpc;
|
||||
export declare function wrapErrorResponseToTwirpError(errorResponse: string): TwirpError;
|
||||
export declare type FetchRPCOptions = Omit<RequestInit, "body" | "method"> & {
|
||||
baseUrl: string;
|
||||
};
|
||||
/**
|
||||
* a browser fetch RPC implementation
|
||||
*/
|
||||
export declare const FetchRPC: (options: FetchRPCOptions) => Rpc;
|
||||
112
node_modules/twirp-ts/build/twirp/http.client.js
generated
vendored
Normal file
112
node_modules/twirp-ts/build/twirp/http.client.js
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
||||
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
||||
}) : function(o, v) {
|
||||
o["default"] = v;
|
||||
});
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
||||
__setModuleDefault(result, mod);
|
||||
return result;
|
||||
};
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.FetchRPC = exports.wrapErrorResponseToTwirpError = exports.NodeHttpRPC = void 0;
|
||||
const http = __importStar(require("http"));
|
||||
const https = __importStar(require("https"));
|
||||
const url_1 = require("url");
|
||||
const errors_1 = require("./errors");
|
||||
/**
|
||||
* a node HTTP RPC implementation
|
||||
* @param options
|
||||
* @constructor
|
||||
*/
|
||||
const NodeHttpRPC = (options) => ({
|
||||
request(service, method, contentType, data) {
|
||||
let client;
|
||||
return new Promise((resolve, rejected) => {
|
||||
const responseChunks = [];
|
||||
const requestData = contentType === "application/protobuf"
|
||||
? Buffer.from(data)
|
||||
: JSON.stringify(data);
|
||||
const url = new url_1.URL(options.baseUrl);
|
||||
const isHttps = url.protocol === "https:";
|
||||
if (isHttps) {
|
||||
client = https;
|
||||
}
|
||||
else {
|
||||
client = http;
|
||||
}
|
||||
const prefix = url.pathname !== "/" ? url.pathname : "";
|
||||
const req = client
|
||||
.request(Object.assign(Object.assign({}, (options ? options : {})), { method: "POST", protocol: url.protocol, host: url.hostname, port: url.port ? url.port : isHttps ? 443 : 80, path: `${prefix}/${service}/${method}`, headers: Object.assign(Object.assign({}, (options.headers ? options.headers : {})), { "Content-Type": contentType, "Content-Length": contentType === "application/protobuf"
|
||||
? Buffer.byteLength(requestData)
|
||||
: Buffer.from(requestData).byteLength }) }), (res) => {
|
||||
res.on("data", (chunk) => responseChunks.push(chunk));
|
||||
res.on("end", () => {
|
||||
const data = Buffer.concat(responseChunks);
|
||||
if (res.statusCode != 200) {
|
||||
rejected(wrapErrorResponseToTwirpError(data.toString()));
|
||||
}
|
||||
else {
|
||||
if (contentType === "application/json") {
|
||||
resolve(JSON.parse(data.toString()));
|
||||
}
|
||||
else {
|
||||
resolve(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
res.on("error", (err) => {
|
||||
rejected(err);
|
||||
});
|
||||
})
|
||||
.on("error", (err) => {
|
||||
rejected(err);
|
||||
});
|
||||
req.end(requestData);
|
||||
});
|
||||
},
|
||||
});
|
||||
exports.NodeHttpRPC = NodeHttpRPC;
|
||||
function wrapErrorResponseToTwirpError(errorResponse) {
|
||||
return errors_1.TwirpError.fromObject(JSON.parse(errorResponse));
|
||||
}
|
||||
exports.wrapErrorResponseToTwirpError = wrapErrorResponseToTwirpError;
|
||||
/**
|
||||
* a browser fetch RPC implementation
|
||||
*/
|
||||
const FetchRPC = (options) => ({
|
||||
request(service, method, contentType, data) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const headers = new Headers(options.headers);
|
||||
headers.set("content-type", contentType);
|
||||
const response = yield fetch(`${options.baseUrl}/${service}/${method}`, Object.assign(Object.assign({}, options), { method: "POST", headers, body: data instanceof Uint8Array ? data : JSON.stringify(data) }));
|
||||
if (response.status === 200) {
|
||||
if (contentType === "application/json") {
|
||||
return yield response.json();
|
||||
}
|
||||
return new Uint8Array(yield response.arrayBuffer());
|
||||
}
|
||||
throw errors_1.TwirpError.fromObject(yield response.json());
|
||||
});
|
||||
},
|
||||
});
|
||||
exports.FetchRPC = FetchRPC;
|
||||
8
node_modules/twirp-ts/build/twirp/index.d.ts
generated
vendored
Normal file
8
node_modules/twirp-ts/build/twirp/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export * from "./context";
|
||||
export * from "./server";
|
||||
export * from "./interceptors";
|
||||
export * from "./hooks";
|
||||
export * from "./errors";
|
||||
export * from "./gateway";
|
||||
export * from "./http.client";
|
||||
export { TwirpContentType, TwirpRequest } from "./request";
|
||||
22
node_modules/twirp-ts/build/twirp/index.js
generated
vendored
Normal file
22
node_modules/twirp-ts/build/twirp/index.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
||||
}) : (function(o, m, k, k2) {
|
||||
if (k2 === undefined) k2 = k;
|
||||
o[k2] = m[k];
|
||||
}));
|
||||
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
||||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.TwirpContentType = void 0;
|
||||
__exportStar(require("./context"), exports);
|
||||
__exportStar(require("./server"), exports);
|
||||
__exportStar(require("./interceptors"), exports);
|
||||
__exportStar(require("./hooks"), exports);
|
||||
__exportStar(require("./errors"), exports);
|
||||
__exportStar(require("./gateway"), exports);
|
||||
__exportStar(require("./http.client"), exports);
|
||||
var request_1 = require("./request");
|
||||
Object.defineProperty(exports, "TwirpContentType", { enumerable: true, get: function () { return request_1.TwirpContentType; } });
|
||||
4
node_modules/twirp-ts/build/twirp/interceptors.d.ts
generated
vendored
Normal file
4
node_modules/twirp-ts/build/twirp/interceptors.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import { TwirpContext } from "./context";
|
||||
export declare type Next<Context extends TwirpContext = TwirpContext, Request = any, Response = any> = (ctx: Context, typedRequest: Request) => Promise<Response>;
|
||||
export declare type Interceptor<Context extends TwirpContext, Request, Response> = (ctx: Context, typedRequest: Request, next: Next<Context, Request, Response>) => Promise<Response>;
|
||||
export declare function chainInterceptors<Context extends TwirpContext, Request, Response>(...interceptors: Interceptor<Context, Request, Response>[]): Interceptor<Context, Request, Response> | undefined;
|
||||
34
node_modules/twirp-ts/build/twirp/interceptors.js
generated
vendored
Normal file
34
node_modules/twirp-ts/build/twirp/interceptors.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.chainInterceptors = void 0;
|
||||
// chains multiple Interceptors into a single Interceptor.
|
||||
// The first interceptor wraps the second one, and so on.
|
||||
// Returns null if interceptors is empty.
|
||||
function chainInterceptors(...interceptors) {
|
||||
if (interceptors.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (interceptors.length === 1) {
|
||||
return interceptors[0];
|
||||
}
|
||||
const first = interceptors[0];
|
||||
return (ctx, request, handler) => __awaiter(this, void 0, void 0, function* () {
|
||||
let next = handler;
|
||||
for (let i = interceptors.length - 1; i > 0; i--) {
|
||||
next = ((next) => (ctx, typedRequest) => {
|
||||
return interceptors[i](ctx, typedRequest, next);
|
||||
})(next);
|
||||
}
|
||||
return first(ctx, request, next);
|
||||
});
|
||||
}
|
||||
exports.chainInterceptors = chainInterceptors;
|
||||
43
node_modules/twirp-ts/build/twirp/request.d.ts
generated
vendored
Normal file
43
node_modules/twirp-ts/build/twirp/request.d.ts
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/// <reference types="node" />
|
||||
import { TwirpContext } from "./context";
|
||||
import http from "http";
|
||||
/**
|
||||
* Supported Twirp Content-Type
|
||||
*/
|
||||
export declare enum TwirpContentType {
|
||||
Protobuf = 0,
|
||||
JSON = 1,
|
||||
Unknown = 2
|
||||
}
|
||||
/**
|
||||
* Represent a Twirp request
|
||||
*/
|
||||
export interface TwirpRequest {
|
||||
prefix?: string;
|
||||
pkgService: string;
|
||||
method: string;
|
||||
contentType: TwirpContentType;
|
||||
mimeContentType: string;
|
||||
}
|
||||
/**
|
||||
* Get supported content-type
|
||||
* @param mimeType
|
||||
*/
|
||||
export declare function getContentType(mimeType: string | undefined): TwirpContentType;
|
||||
/**
|
||||
* Validate a twirp request
|
||||
* @param ctx
|
||||
* @param request
|
||||
* @param pathPrefix
|
||||
*/
|
||||
export declare function validateRequest(ctx: TwirpContext, request: http.IncomingMessage, pathPrefix: string): TwirpRequest;
|
||||
/**
|
||||
* Get request data from the body
|
||||
* @param req
|
||||
*/
|
||||
export declare function getRequestData(req: http.IncomingMessage): Promise<Buffer>;
|
||||
/**
|
||||
* Parses twirp url path
|
||||
* @param path
|
||||
*/
|
||||
export declare function parseTwirpPath(path: string): Omit<TwirpRequest, "contentType" | "mimeContentType">;
|
||||
117
node_modules/twirp-ts/build/twirp/request.js
generated
vendored
Normal file
117
node_modules/twirp-ts/build/twirp/request.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseTwirpPath = exports.getRequestData = exports.validateRequest = exports.getContentType = exports.TwirpContentType = void 0;
|
||||
const errors_1 = require("./errors");
|
||||
/**
|
||||
* Supported Twirp Content-Type
|
||||
*/
|
||||
var TwirpContentType;
|
||||
(function (TwirpContentType) {
|
||||
TwirpContentType[TwirpContentType["Protobuf"] = 0] = "Protobuf";
|
||||
TwirpContentType[TwirpContentType["JSON"] = 1] = "JSON";
|
||||
TwirpContentType[TwirpContentType["Unknown"] = 2] = "Unknown";
|
||||
})(TwirpContentType = exports.TwirpContentType || (exports.TwirpContentType = {}));
|
||||
/**
|
||||
* Get supported content-type
|
||||
* @param mimeType
|
||||
*/
|
||||
function getContentType(mimeType) {
|
||||
switch (mimeType) {
|
||||
case "application/protobuf":
|
||||
return TwirpContentType.Protobuf;
|
||||
case "application/json":
|
||||
return TwirpContentType.JSON;
|
||||
default:
|
||||
return TwirpContentType.Unknown;
|
||||
}
|
||||
}
|
||||
exports.getContentType = getContentType;
|
||||
/**
|
||||
* Validate a twirp request
|
||||
* @param ctx
|
||||
* @param request
|
||||
* @param pathPrefix
|
||||
*/
|
||||
function validateRequest(ctx, request, pathPrefix) {
|
||||
if (request.method !== "POST") {
|
||||
const msg = `unsupported method ${request.method} (only POST is allowed)`;
|
||||
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
|
||||
}
|
||||
const path = parseTwirpPath(request.url || "");
|
||||
if (path.pkgService !==
|
||||
(ctx.packageName ? ctx.packageName + "." : "") + ctx.serviceName) {
|
||||
const msg = `no handler for path ${request.url}`;
|
||||
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
|
||||
}
|
||||
if (path.prefix !== pathPrefix) {
|
||||
const msg = `invalid path prefix ${path.prefix}, expected ${pathPrefix}, on path ${request.url}`;
|
||||
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
|
||||
}
|
||||
const mimeContentType = request.headers["content-type"] || "";
|
||||
if (ctx.contentType === TwirpContentType.Unknown) {
|
||||
const msg = `unexpected Content-Type: ${request.headers["content-type"]}`;
|
||||
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
|
||||
}
|
||||
return Object.assign(Object.assign({}, path), { mimeContentType, contentType: ctx.contentType });
|
||||
}
|
||||
exports.validateRequest = validateRequest;
|
||||
/**
|
||||
* Get request data from the body
|
||||
* @param req
|
||||
*/
|
||||
function getRequestData(req) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reqWithRawBody = req;
|
||||
if (reqWithRawBody.rawBody instanceof Buffer) {
|
||||
resolve(reqWithRawBody.rawBody);
|
||||
return;
|
||||
}
|
||||
const chunks = [];
|
||||
req.on("data", (chunk) => chunks.push(chunk));
|
||||
req.on("end", () => __awaiter(this, void 0, void 0, function* () {
|
||||
const data = Buffer.concat(chunks);
|
||||
resolve(data);
|
||||
}));
|
||||
req.on("error", (err) => {
|
||||
if (req.aborted) {
|
||||
reject(new errors_1.TwirpError(errors_1.TwirpErrorCode.DeadlineExceeded, "failed to read request: deadline exceeded"));
|
||||
}
|
||||
else {
|
||||
reject(new errors_1.TwirpError(errors_1.TwirpErrorCode.Malformed, err.message).withCause(err));
|
||||
}
|
||||
});
|
||||
req.on("close", () => {
|
||||
reject(new errors_1.TwirpError(errors_1.TwirpErrorCode.Canceled, "failed to read request: context canceled"));
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.getRequestData = getRequestData;
|
||||
/**
|
||||
* Parses twirp url path
|
||||
* @param path
|
||||
*/
|
||||
function parseTwirpPath(path) {
|
||||
const parts = path.split("/");
|
||||
if (parts.length < 2) {
|
||||
return {
|
||||
pkgService: "",
|
||||
method: "",
|
||||
prefix: "",
|
||||
};
|
||||
}
|
||||
return {
|
||||
method: parts[parts.length - 1],
|
||||
pkgService: parts[parts.length - 2],
|
||||
prefix: parts.slice(0, parts.length - 2).join("/"),
|
||||
};
|
||||
}
|
||||
exports.parseTwirpPath = parseTwirpPath;
|
||||
104
node_modules/twirp-ts/build/twirp/server.d.ts
generated
vendored
Normal file
104
node_modules/twirp-ts/build/twirp/server.d.ts
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/// <reference types="node" />
|
||||
import * as http from "http";
|
||||
import { TwirpContext } from "./context";
|
||||
import { ServerHooks } from "./hooks";
|
||||
import { Interceptor } from "./interceptors";
|
||||
import { TwirpError } from "./errors";
|
||||
/**
|
||||
* Twirp Server options
|
||||
*/
|
||||
interface TwirpServerOptions<T extends object, S extends TwirpContext = TwirpContext> {
|
||||
service: T;
|
||||
packageName: string;
|
||||
serviceName: string;
|
||||
methodList: keys<T>;
|
||||
matchRoute: (method: string, events: RouterEvents<S>) => TwirpHandler<T, S>;
|
||||
}
|
||||
/**
|
||||
* httpHandler options
|
||||
*/
|
||||
export interface HttpHandlerOptions {
|
||||
prefix?: string | false;
|
||||
}
|
||||
/**
|
||||
* Handles a twirp request
|
||||
*/
|
||||
export declare type TwirpHandler<T, S extends TwirpContext = TwirpContext> = (ctx: S, service: T, data: Buffer, interceptors?: Interceptor<S, any, any>[]) => Promise<Uint8Array | string>;
|
||||
/**
|
||||
* Callback events for route matching
|
||||
*/
|
||||
export interface RouterEvents<T extends TwirpContext = TwirpContext> {
|
||||
onMatch: (ctx: T) => Promise<void> | void;
|
||||
onNotFound: () => Promise<void> | void;
|
||||
}
|
||||
declare type keys<T extends object> = Array<keyof T>;
|
||||
/**
|
||||
* Runtime server implementation of a TwirpServer
|
||||
*/
|
||||
export declare class TwirpServer<T extends object, S extends TwirpContext = TwirpContext> {
|
||||
readonly packageName: string;
|
||||
readonly serviceName: string;
|
||||
readonly methodList: keys<T>;
|
||||
private service;
|
||||
private pathPrefix;
|
||||
private hooks;
|
||||
private interceptors;
|
||||
private matchRoute;
|
||||
constructor(options: TwirpServerOptions<T, S>);
|
||||
/**
|
||||
* Returns the prefix for this server
|
||||
*/
|
||||
get prefix(): string;
|
||||
/**
|
||||
* The http handler for twirp complaint endpoints
|
||||
* @param options
|
||||
*/
|
||||
httpHandler(options?: HttpHandlerOptions): (req: http.IncomingMessage, resp: http.ServerResponse) => Promise<void>;
|
||||
/**
|
||||
* Adds interceptors or hooks to the request stack
|
||||
* @param middlewares
|
||||
*/
|
||||
use(...middlewares: (ServerHooks<S> | Interceptor<S, any, any>)[]): this;
|
||||
/**
|
||||
* Adds a prefix to the service url path
|
||||
* @param prefix
|
||||
*/
|
||||
withPrefix(prefix: string | false): this;
|
||||
/**
|
||||
* Returns the regex matching path for this twirp server
|
||||
*/
|
||||
matchingPath(): RegExp;
|
||||
/**
|
||||
* Returns the base URI for this twirp server
|
||||
*/
|
||||
baseURI(): string;
|
||||
/**
|
||||
* Create a twirp context
|
||||
* @param req
|
||||
* @param res
|
||||
* @private
|
||||
*/
|
||||
protected createContext(req: http.IncomingMessage, res: http.ServerResponse): S;
|
||||
/**
|
||||
* Twrip server http handler implementation
|
||||
* @param req
|
||||
* @param resp
|
||||
* @private
|
||||
*/
|
||||
private _httpHandler;
|
||||
/**
|
||||
* Invoke a hook
|
||||
* @param hookName
|
||||
* @param ctx
|
||||
* @param err
|
||||
* @protected
|
||||
*/
|
||||
protected invokeHook(hookName: keyof ServerHooks<S>, ctx: S, err?: TwirpError): Promise<void>;
|
||||
}
|
||||
/**
|
||||
* Write http error response
|
||||
* @param res
|
||||
* @param error
|
||||
*/
|
||||
export declare function writeError(res: http.ServerResponse, error: Error | TwirpError): void;
|
||||
export {};
|
||||
195
node_modules/twirp-ts/build/twirp/server.js
generated
vendored
Normal file
195
node_modules/twirp-ts/build/twirp/server.js
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeError = exports.TwirpServer = void 0;
|
||||
const hooks_1 = require("./hooks");
|
||||
const request_1 = require("./request");
|
||||
const errors_1 = require("./errors");
|
||||
/**
|
||||
* Runtime server implementation of a TwirpServer
|
||||
*/
|
||||
class TwirpServer {
|
||||
constructor(options) {
|
||||
this.pathPrefix = "/twirp";
|
||||
this.hooks = [];
|
||||
this.interceptors = [];
|
||||
this.packageName = options.packageName;
|
||||
this.serviceName = options.serviceName;
|
||||
this.methodList = options.methodList;
|
||||
this.matchRoute = options.matchRoute;
|
||||
this.service = options.service;
|
||||
}
|
||||
/**
|
||||
* Returns the prefix for this server
|
||||
*/
|
||||
get prefix() {
|
||||
return this.pathPrefix;
|
||||
}
|
||||
/**
|
||||
* The http handler for twirp complaint endpoints
|
||||
* @param options
|
||||
*/
|
||||
httpHandler(options) {
|
||||
return (req, resp) => {
|
||||
// setup prefix
|
||||
if ((options === null || options === void 0 ? void 0 : options.prefix) !== undefined) {
|
||||
this.withPrefix(options.prefix);
|
||||
}
|
||||
return this._httpHandler(req, resp);
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Adds interceptors or hooks to the request stack
|
||||
* @param middlewares
|
||||
*/
|
||||
use(...middlewares) {
|
||||
middlewares.forEach((middleware) => {
|
||||
if (hooks_1.isHook(middleware)) {
|
||||
this.hooks.push(middleware);
|
||||
return this;
|
||||
}
|
||||
this.interceptors.push(middleware);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Adds a prefix to the service url path
|
||||
* @param prefix
|
||||
*/
|
||||
withPrefix(prefix) {
|
||||
if (prefix === false) {
|
||||
this.pathPrefix = "";
|
||||
}
|
||||
else {
|
||||
this.pathPrefix = prefix;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
/**
|
||||
* Returns the regex matching path for this twirp server
|
||||
*/
|
||||
matchingPath() {
|
||||
const baseRegex = this.baseURI().replace(/\./g, "\\.");
|
||||
return new RegExp(`${baseRegex}\/(${this.methodList.join("|")})`);
|
||||
}
|
||||
/**
|
||||
* Returns the base URI for this twirp server
|
||||
*/
|
||||
baseURI() {
|
||||
return `${this.pathPrefix}/${this.packageName ? this.packageName + "." : ""}${this.serviceName}`;
|
||||
}
|
||||
/**
|
||||
* Create a twirp context
|
||||
* @param req
|
||||
* @param res
|
||||
* @private
|
||||
*/
|
||||
createContext(req, res) {
|
||||
return {
|
||||
packageName: this.packageName,
|
||||
serviceName: this.serviceName,
|
||||
methodName: "",
|
||||
contentType: request_1.getContentType(req.headers["content-type"]),
|
||||
req: req,
|
||||
res: res,
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Twrip server http handler implementation
|
||||
* @param req
|
||||
* @param resp
|
||||
* @private
|
||||
*/
|
||||
_httpHandler(req, resp) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const ctx = this.createContext(req, resp);
|
||||
try {
|
||||
yield this.invokeHook("requestReceived", ctx);
|
||||
const { method, mimeContentType } = request_1.validateRequest(ctx, req, this.pathPrefix || "");
|
||||
const handler = this.matchRoute(method, {
|
||||
onMatch: (ctx) => {
|
||||
return this.invokeHook("requestRouted", ctx);
|
||||
},
|
||||
onNotFound: () => {
|
||||
const msg = `no handler for path ${req.url}`;
|
||||
throw new errors_1.BadRouteError(msg, req.method || "", req.url || "");
|
||||
},
|
||||
});
|
||||
const body = yield request_1.getRequestData(req);
|
||||
const response = yield handler(ctx, this.service, body, this.interceptors);
|
||||
yield Promise.all([
|
||||
this.invokeHook("responsePrepared", ctx),
|
||||
// keep backwards compatibility till next release
|
||||
this.invokeHook("requestPrepared", ctx),
|
||||
]);
|
||||
resp.statusCode = 200;
|
||||
resp.setHeader("Content-Type", mimeContentType);
|
||||
resp.end(response);
|
||||
}
|
||||
catch (e) {
|
||||
yield this.invokeHook("error", ctx, mustBeTwirpError(e));
|
||||
if (!resp.headersSent) {
|
||||
writeError(resp, e);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
yield Promise.all([
|
||||
this.invokeHook("responseSent", ctx),
|
||||
// keep backwards compatibility till next release
|
||||
this.invokeHook("requestSent", ctx),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Invoke a hook
|
||||
* @param hookName
|
||||
* @param ctx
|
||||
* @param err
|
||||
* @protected
|
||||
*/
|
||||
invokeHook(hookName, ctx, err) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
if (this.hooks.length === 0) {
|
||||
return;
|
||||
}
|
||||
const chainedHooks = hooks_1.chainHooks(...this.hooks);
|
||||
const hook = chainedHooks === null || chainedHooks === void 0 ? void 0 : chainedHooks[hookName];
|
||||
if (hook) {
|
||||
yield hook(ctx, err || new errors_1.InternalServerError("internal server error"));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
exports.TwirpServer = TwirpServer;
|
||||
/**
|
||||
* Write http error response
|
||||
* @param res
|
||||
* @param error
|
||||
*/
|
||||
function writeError(res, error) {
|
||||
const twirpError = mustBeTwirpError(error);
|
||||
res.setHeader("Content-Type", "application/json");
|
||||
res.statusCode = errors_1.httpStatusFromErrorCode(twirpError.code);
|
||||
res.end(twirpError.toJSON());
|
||||
}
|
||||
exports.writeError = writeError;
|
||||
/**
|
||||
* Make sure that the error passed is a TwirpError
|
||||
* otherwise it will wrap it into an InternalError
|
||||
* @param err
|
||||
*/
|
||||
function mustBeTwirpError(err) {
|
||||
if (err instanceof errors_1.TwirpError) {
|
||||
return err;
|
||||
}
|
||||
return new errors_1.InternalServerErrorWith(err);
|
||||
}
|
||||
Reference in New Issue
Block a user