stable-ts-type
Version:
Obtain the most stable type code of 'typescript' through multiple network requests
177 lines (176 loc) • 8.01 kB
JavaScript
;
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.generate = exports.simpleGenerate = exports.Generator = void 0;
const axios_1 = __importDefault(require("axios"));
const prefer_delay_1 = require("prefer-delay");
const eventemitter2_1 = __importDefault(require("eventemitter2"));
const merge_1 = __importDefault(require("merge"));
const json2type_1 = __importDefault(require("./json2type"));
const fetch_1 = __importDefault(require("./fetch"));
const type_opts_1 = require("./type-opts");
const utils_1 = require("./utils");
const input_1 = require("./input");
const TOP_TYPE_NAME = 'Response'; // quicktype@21.0.13的ts转换直接定死了大驼峰,没法改风格
const defaultGenerateOpts = {
requestInterval: 0,
topTypeName: TOP_TYPE_NAME,
quickTypeOpts: type_opts_1.defaultTypeOpts,
requireMockSort: 'random',
};
var GenerateEvent;
(function (GenerateEvent) {
GenerateEvent["CHUNK_DONE_EVENT"] = "CHUNK_DONE";
GenerateEvent["DONE_EVENT"] = "DONE";
GenerateEvent["ERROR_EVENT"] = "ERROR";
})(GenerateEvent || (GenerateEvent = {}));
class Generator {
constructor(input, opts = {}) {
this.opts = {};
this.jsonExamples = [];
this.requestInputs = [];
this.eventEmitter = new eventemitter2_1.default();
this.stopped = false;
// status
this.code = '';
this.jsonList = [];
this.opts = merge_1.default.recursive(true, defaultGenerateOpts, opts);
const easyInputs = Generator.getEasyInputs(Array.isArray(input) ? input : [input]);
this.jsonExamples = easyInputs.jsonExamples;
this.requestInputs = (0, input_1.getOnceMockInputList)(easyInputs.requestInputs, opts.requireMockSort);
if (this.opts.on) {
// @ts-ignore
this.eventEmitter.onAny(this.opts.on);
}
const CancelToken = axios_1.default.CancelToken;
const { token: fetchCancelToken, cancel: fetchCancel } = CancelToken.source();
this.fetch = (0, prefer_delay_1.promiseDelay)((request, requestConfig, requestMock) => (0, fetch_1.default)(request, Object.assign(Object.assign({}, requestConfig), { cancelToken: fetchCancelToken }), requestMock), opts.requestInterval);
this.fetchCancel = () => fetchCancel('the stable-ts-type generator has been interrupted');
}
onGenerateChunk(jsonList) {
return __awaiter(this, void 0, void 0, function* () {
const { opts, eventEmitter, stopped } = this;
if (stopped)
return;
this.jsonList.push(...jsonList);
const code = yield (0, json2type_1.default)(opts.topTypeName, [JSON.stringify(this.jsonList)], opts.quickTypeOpts);
this.code = code;
eventEmitter.emit(GenerateEvent.CHUNK_DONE_EVENT, code);
});
}
generate() {
return __awaiter(this, void 0, void 0, function* () {
const { jsonExamples, requestInputs, eventEmitter, fetch } = this;
const promises = [];
const p = this.onGenerateChunk(jsonExamples)
.catch((error) => {
this.eventEmitter.emit(GenerateEvent.ERROR_EVENT, error);
});
promises.push(p);
for (const fetchInput of requestInputs) {
// @ts-ignore
const p = fetch(fetchInput.value, {}, fetchInput.mock)
.then(data => {
if ((0, utils_1.isValidJSON)(data)) {
return data;
}
const showFetchInput = {
type: fetchInput.type,
value: fetchInput.value,
};
throw (0, utils_1.simpleError)(`json conversion failed, from fetchInput: ${JSON.stringify(showFetchInput, null, 2)}`);
})
.then(json => this.onGenerateChunk([json]))
.catch((error) => {
this.eventEmitter.emit(GenerateEvent.ERROR_EVENT, error);
});
promises.push(p);
}
yield Promise.all(promises);
eventEmitter.emit(GenerateEvent.DONE_EVENT, this.code);
});
}
stop() {
this.stopped = true;
this.eventEmitter.removeAllListeners();
this.fetchCancel();
}
static getEasyInputs(inputs) {
const jsonExamplesInput = inputs
.filter(input => input.type === 'example-json');
const jsonExamples = jsonExamplesInput
.map(input => typeof input.value === 'string'
? (0, utils_1.easyJSONParse)(input.value)
: input.value);
const requestInputs = inputs
.filter(input => input.type !== 'example-json');
return {
jsonExamples,
requestInputs,
};
}
}
exports.Generator = Generator;
Generator.CHUNK_DONE_EVENT = GenerateEvent.CHUNK_DONE_EVENT;
Generator.DONE_EVENT = GenerateEvent.DONE_EVENT;
Generator.ERROR_EVENT = GenerateEvent.ERROR_EVENT;
const simpleGenerate = (input, opts = {}) => __awaiter(void 0, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const inputs = Array.isArray(input) ? input : [input];
const generator = new Generator(inputs, Object.assign(Object.assign({}, opts), { on: (event, codeOrError) => {
switch (event) {
case 'DONE':
resolve(codeOrError);
break;
case 'ERROR':
reject(codeOrError);
break;
}
} }));
generator.generate();
});
});
exports.simpleGenerate = simpleGenerate;
/** @deprecated */
const generate = (input, opts = {}) => __awaiter(void 0, void 0, void 0, function* () {
var _a;
const inputs = Array.isArray(input) ? input : [input];
const quickTypeOpts = Object.assign({}, type_opts_1.defaultTypeOpts, opts.quickTypeOpts);
const jsonExamplesInput = inputs
.filter(input => input.type === 'example-json');
const jsonExamples = jsonExamplesInput
.map(input => typeof input.value === 'string'
? (0, utils_1.easyJSONParse)(input.value)
: JSON.stringify(input.value));
const requiredFetchInputs = inputs
.filter(input => input.type !== 'example-json');
// @ts-ignore
const fetches = requiredFetchInputs.map(input => (0, fetch_1.default)(input.value));
const respDataList = yield Promise.all(fetches);
try {
const respDataStrList = respDataList.map(data => JSON.stringify(data));
const typeCode = yield (0, json2type_1.default)((_a = opts.topTypeName) !== null && _a !== void 0 ? _a : TOP_TYPE_NAME, [
...jsonExamples,
...respDataStrList,
], quickTypeOpts);
return typeCode;
}
catch (error) {
throw (0, utils_1.simpleError)(`failed to generate typeCode, json-list: ${JSON.stringify([
...respDataList,
...jsonExamplesInput.map(item => item.value),
], null, 2)}`);
}
});
exports.generate = generate;