pg-to-ts
Version:
Generate TypeScript-friendly interfaces and constants from (postgres) SQL database schema
187 lines • 10.1 kB
JavaScript
;
/**
* Generate TypeScript interface definitions from your Postgres schema
* pg-to-ts is derived from PYST/schemats, which was a fork of SweetIQ/schemats.
*/
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 __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Options = exports.typescriptOfSchema = exports.typescriptOfTable = void 0;
var typescript_1 = require("./typescript");
var options_1 = __importDefault(require("./options"));
exports.Options = options_1.default;
var typescript_formatter_1 = require("typescript-formatter");
var schemaPostgres_1 = require("./schemaPostgres");
// eslint-disable-next-line @typescript-eslint/no-var-requires
var pkgVersion = require('../package.json').version;
function buildHeader(db, tables, schema, options) {
var commands = [
'pg-to-ts',
'generate',
'-c',
db.connectionString.replace(/:\/\/.*@/, '://username:password@'),
];
if (options.camelCase)
commands.push('-C');
if (tables.length > 0) {
tables.forEach(function (t) {
commands.push('-t', t);
});
}
if (schema) {
commands.push('-s', schema);
}
return "\n /**\n * AUTO-GENERATED FILE - DO NOT EDIT!\n *\n * This file was automatically generated by pg-to-ts v.".concat(pkgVersion, "\n * $ ").concat(commands.join(' '), "\n *\n */\n\n ");
}
function typescriptOfTable(db, table, schema, options) {
if (options === void 0) { options = new options_1.default(); }
return __awaiter(this, void 0, void 0, function () {
var tableTypes;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, db.getTableTypes(table, schema, options)];
case 1:
tableTypes = _a.sent();
return [2 /*return*/, (0, typescript_1.generateTableInterface)(table, tableTypes, schema, options)];
}
});
});
}
exports.typescriptOfTable = typescriptOfTable;
function typescriptOfSchema(dbIn, tables, excludedTables, inSchema, options) {
if (tables === void 0) { tables = []; }
if (excludedTables === void 0) { excludedTables = []; }
if (inSchema === void 0) { inSchema = null; }
if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var db, schema, optionsObject, enumTypes, _a, interfacePromises, interfaceTuples, tablesToNames, interfaces, typesToImport, _i, _b, types, importTs, symbols, tableNames, typeMaps, tableMap, output, formatterOption, processedResult;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
db = typeof dbIn === 'string' ? new schemaPostgres_1.PostgresDatabase(dbIn) : dbIn;
schema = inSchema !== null && inSchema !== void 0 ? inSchema : db.getDefaultSchema();
if (!(tables.length === 0)) return [3 /*break*/, 2];
return [4 /*yield*/, db.getSchemaTables(schema)];
case 1:
tables = (_c.sent()).filter(function (t) { return excludedTables.indexOf(t) == -1; });
_c.label = 2;
case 2:
optionsObject = new options_1.default(options);
_a = typescript_1.generateEnumType;
return [4 /*yield*/, db.getEnumTypes(schema)];
case 3:
enumTypes = _a.apply(void 0, [_c.sent(), optionsObject]);
interfacePromises = tables.map(function (table) {
return typescriptOfTable(db, table, schema, optionsObject);
});
return [4 /*yield*/, Promise.all(interfacePromises)];
case 4:
interfaceTuples = _c.sent();
tablesToNames = {};
tables.forEach(function (table, i) {
tablesToNames[table] = interfaceTuples[i][1];
});
interfaces = interfaceTuples
.map(function (_a) {
var ts = _a[0];
return (0, typescript_1.attachJoinTypes)(ts, tablesToNames);
})
.join('');
typesToImport = new Set();
for (_i = 0, _b = interfaceTuples.map(function (_a) {
var types = _a[2];
return types;
}); _i < _b.length; _i++) {
types = _b[_i];
types.forEach(typesToImport.add, typesToImport);
}
importTs = '';
if (options.jsonTypesFile && typesToImport.size) {
symbols = Array.from(typesToImport).join(', ');
importTs = "import {".concat(symbols, "} from \"").concat(options.jsonTypesFile, "\";\n\n");
}
tableNames = interfaceTuples.map(function (_a) {
var names = _a[1];
return names;
});
typeMaps = tableNames
.map(function (names) { return "\n ".concat(names.var, ": {\n select: ").concat(names.type, ";\n input: ").concat(names.input, ";\n };"); })
.join('');
tableMap = tableNames.map(function (names) { return names.var; }).join(',\n ');
output = '/* tslint:disable */\n/* eslint-disable */\n\n';
if (optionsObject.options.writeHeader) {
output += buildHeader(db, tables, schema, options);
}
// TODO(danvk): This is a better type than unknown, but typescript-json-schema chokes on it.
// type Json =
// | string
// | number
// | boolean
// | null
// | { [property: string]: Json }
// | Json[];
output += importTs;
output += "\n export type Json = unknown;\n ";
output += enumTypes;
output += interfaces;
output += "\n\n export interface TableTypes {".concat(typeMaps, "\n }\n\n export const tables = {\n ").concat(tableMap, ",\n }\n ");
formatterOption = {
replace: false,
verify: false,
tsconfig: true,
tslint: true,
editorconfig: true,
tsfmt: true,
vscode: false,
tsconfigFile: null,
tslintFile: null,
vscodeFile: null,
tsfmtFile: null,
};
return [4 /*yield*/, (0, typescript_formatter_1.processString)('schema.ts', output, formatterOption)];
case 5:
processedResult = _c.sent();
return [2 /*return*/, processedResult.dest.replace(/ {4}/g, ' ')];
}
});
});
}
exports.typescriptOfSchema = typescriptOfSchema;
//# sourceMappingURL=index.js.map