zenstack
Version:
FullStack enhancement for Prisma ORM: seamless integration from database to UI
247 lines • 11.8 kB
JavaScript
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
;