UNPKG

zenstack

Version:

FullStack enhancement for Prisma ORM: seamless integration from database to UI

247 lines 11.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (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 }); exports.repl = repl; /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-var-requires */ const colors_1 = __importDefault(require("colors")); const path_1 = __importDefault(require("path")); const util_1 = require("util"); // inspired by: https://github.com/Kinjalrk2k/prisma-console /** * CLI action for starting a REPL session */ function repl(projectPath, options) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c; if (!((_a = process === null || process === void 0 ? void 0 : process.stdout) === null || _a === void 0 ? void 0 : _a.isTTY) && ((_b = process === null || process === void 0 ? void 0 : process.versions) === null || _b === void 0 ? void 0 : _b.bun)) { console.error('REPL on Bun is only available in a TTY terminal at this time. Please use npm/npx to run the command in this context instead of bun/bunx.'); return; } const prettyRepl = yield Promise.resolve().then(() => __importStar(require('pretty-repl'))); console.log('Welcome to ZenStack REPL. See help with the ".help" command.'); console.log('Global variables:'); console.log(` ${colors_1.default.blue('db')} to access enhanced PrismaClient`); console.log(` ${colors_1.default.blue('prisma')} to access raw PrismaClient`); console.log(` ${colors_1.default.blue('user')} to inspect the current user`); console.log('Commands:'); console.log(` ${colors_1.default.magenta('.auth { id: ... }')} - set current user`); console.log(` ${colors_1.default.magenta('.table')} - toggle table output`); console.log(` ${colors_1.default.magenta('.debug')} - toggle debug output`); console.log(); console.log(`Running as anonymous user. Use ".auth" to set current user.`); let PrismaClient; const prismaClientModule = (_c = options.prismaClient) !== null && _c !== void 0 ? _c : '@prisma/client'; try { // try direct require const module = require(prismaClientModule); PrismaClient = module.PrismaClient; } catch (err) { if (!path_1.default.isAbsolute(prismaClientModule)) { // try relative require const module = require(path_1.default.join(projectPath, prismaClientModule)); PrismaClient = module.PrismaClient; } else { throw err; } } const { enhance } = options.loadPath ? require(path_1.default.join(path_1.default.resolve(options.loadPath), 'enhance')) : require('@zenstackhq/runtime'); let debug = !!options.debug; let table = !!options.table; let prisma; // eslint-disable-next-line @typescript-eslint/no-unused-vars let db; let user; const replServer = prettyRepl.start({ prompt: `[${colors_1.default.cyan('anonymous')}] > `, eval: (cmd, _context, _filename, callback) => __awaiter(this, void 0, void 0, function* () { try { let r = undefined; let isPrismaCall = false; if (/^\s*user\s*=[^=]/.test(cmd)) { // assigning to user variable, reset auth eval(cmd); setAuth(user); } else if (/^\s*await\s+/.test(cmd)) { // eval can't handle top-level await, so we wrap it in an async function cmd = `(async () => (${cmd}))()`; r = eval(cmd); if (isPrismaPromise(r)) { isPrismaCall = true; } r = yield r; } else { r = eval(cmd); if (isPrismaPromise(r)) { isPrismaCall = true; // automatically await Prisma promises r = yield r; } } if (isPrismaCall && table) { console.table(r); callback(null, undefined); } else { callback(null, r); } } catch (err) { if (err.code) { console.error(colors_1.default.red(err.message)); console.error('Code:', err.code); if (err.meta) { console.error('Meta:', err.meta); } callback(null, undefined); } else { callback(err, undefined); } } }), }); // .table command replServer.defineCommand('table', { help: 'Toggle table output', action(value) { if (value && value !== 'on' && value !== 'off' && value !== 'true' && value !== 'false') { console.error('Invalid argument. Usage: .table [on|off|true|false]'); this.displayPrompt(); return; } this.clearBufferedCommand(); table = value ? value === 'on' || value === 'true' : !table; console.log('Table output:', table); this.displayPrompt(); }, }); // .debug command replServer.defineCommand('debug', { help: 'Toggle debug output', action(value) { return __awaiter(this, void 0, void 0, function* () { if (value && value !== 'on' && value !== 'off' && value !== 'true' && value !== 'false') { console.error('Invalid argument. Usage: .debug [on|off|true|false]'); this.displayPrompt(); return; } this.clearBufferedCommand(); debug = value ? value === 'on' || value === 'true' : !debug; console.log('Debug mode:', debug); yield createClient(); setPrompt(); this.displayPrompt(); }); }, }); // .auth command replServer.defineCommand('auth', { help: 'Set current user. Run without argument to switch to anonymous. Pass an user object to set current user. Run ".auth info" to show current user.', action(value) { this.clearBufferedCommand(); try { if (!(value === null || value === void 0 ? void 0 : value.trim())) { // set anonymous setAuth(undefined); console.log(`Auth user: anonymous. Use ".auth { id: ... }" to change.`); } else if (value.trim() === 'info') { // refresh auth user setAuth(user); console.log(`Current user: ${user ? (0, util_1.inspect)(user) : 'anonymous'}`); } else { // set current user const user = eval(`(${value})`); if (!user || typeof user !== 'object') { console.error(`Invalid argument. Pass a user object like { id: ... }`); this.displayPrompt(); return; } setAuth(user); console.log(`Auth user: ${(0, util_1.inspect)(user)}. Use ".auth" to switch to anonymous.`); } } catch (err) { console.error('Unable to set auth user:', err.message); } this.displayPrompt(); }, }); replServer.setupHistory(path_1.default.join(projectPath, './.zenstack_repl_history'), (err) => { if (err) { console.error('unable to setup REPL history:', err); } }); setPrompt(); yield createClient(); function createClient() { return __awaiter(this, void 0, void 0, function* () { if (prisma) { prisma.$disconnect(); } prisma = new PrismaClient(debug ? { log: ['info'] } : undefined); // https://github.com/prisma/prisma/issues/18292 prisma[Symbol.for('nodejs.util.inspect.custom')] = 'PrismaClient'; db = enhance(prisma, { user }, { logPrismaQuery: debug }); replServer.context.prisma = prisma; replServer.context.db = db; }); } function setPrompt() { const userInfo = user ? (user.id ? `user#${user.id.toString().slice(-8)}` : (0, util_1.inspect)(user)) : 'anonymous'; replServer.setPrompt(`[${debug ? colors_1.default.yellow('D ') : ''}${colors_1.default.cyan(userInfo)}] > `); } function setAuth(_user) { user = _user; // recreate enhanced PrismaClient db = replServer.context.db = enhance(prisma, { user }, { logPrismaQuery: debug }); setPrompt(); } }); } function isPrismaPromise(r) { return (r === null || r === void 0 ? void 0 : r[Symbol.toStringTag]) === 'PrismaPromise' || (r === null || r === void 0 ? void 0 : r[Symbol.toStringTag]) === 'ZenStackPromise'; } //# sourceMappingURL=repl.js.map