diff --git a/package.json b/package.json index 5456734..2da4c52 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@zenstackhq/proxy", - "version": "0.2.6", + "version": "0.2.7", "description": "A CLI tool to run an Express server that proxies CRUD requests to a ZenStack backend", "main": "index.js", "publishConfig": { @@ -20,7 +20,12 @@ "clean": "rimraf dist", "build": "pnpm clean && tsc && copyfiles -F \"bin/*\" dist && copyfiles ./README.md ./LICENSE ./package.json dist && pnpm pack dist --pack-destination ../build" }, - "keywords": ["zenstack", "proxy", "express", "cli"], + "keywords": [ + "zenstack", + "proxy", + "express", + "cli" + ], "author": "", "license": "MIT", "dependencies": { @@ -53,4 +58,4 @@ "require": "./index.js" } } -} +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 93d4712..d9645ad 100644 --- a/src/index.ts +++ b/src/index.ts @@ -20,7 +20,7 @@ export function createProgram() { program .option('-z, --zenstack ', 'Path to ZenStack generated folder') - .option('-p, --port ', 'Port number for the server', '8008') + .option('-p, --port ', 'Port number for the server', '2311') .option('-s, --schema ', 'Path to ZModel schema file', 'schema.zmodel') .option('-d, --datasource-url ', 'Datasource URL (overrides schema configuration)') .option('-l, --log ', 'Query log levels (e.g., query, info, warn, error)') diff --git a/src/server.ts b/src/server.ts index 74fcdc8..83b9dc3 100644 --- a/src/server.ts +++ b/src/server.ts @@ -4,7 +4,7 @@ import cors from 'cors' import { ZenStackMiddleware } from '@zenstackhq/server/express' import { ZModelConfig } from './zmodel-parser' import { getNodeModulesFolder, getPrismaVersion, getZenStackVersion } from './utils/version-utils' -import { blue, grey } from 'colors' +import { blue, grey, red } from 'colors' import semver from 'semver' import { CliError } from './cli-error' @@ -168,23 +168,29 @@ async function loadZenStackModules( enums = prismaModule.$Enums || {} } - let zenstackAbsPath = zenstackPath + const zenstackAbsPath = zenstackPath ? path.isAbsolute(zenstackPath) ? zenstackPath : path.join(process.cwd(), zenstackPath) : undefined - if (zenstackAbsPath) { - const modelMetaPath = path.join(zenstackAbsPath, 'model-meta') + let modelMetaPath: string | undefined + try { + if (zenstackAbsPath) { + modelMetaPath = path.join(zenstackAbsPath, 'model-meta') + } else { + modelMetaPath = '@zenstackhq/runtime/model-meta' + } modelMeta = require(modelMetaPath).default - } else { - modelMeta = require('@zenstackhq/runtime/model-meta').default + } catch { + throw new CliError( + `Failed to load ZenStack generated model meta from: ${modelMetaPath}\n` + + `Please run \`zenstack generate\` first or specify the correct output directory of ZenStack generated modules using the \`-z\` option.` + ) } if (!modelMeta.models) { - throw new CliError( - 'ZenStack generated modules not found. Please make sure `zenstack generate` has been run or specify the correct path using the `-z` option.' - ) + throw new CliError(`Generated model meta not found. Please run \`zenstack generate\` first.`) } const zenstackVersion = getZenStackVersion() @@ -247,6 +253,19 @@ export async function startServer(options: ServerOptions) { console.log(`ZenStack Studio is running at: ${blue('https://studio.zenstack.dev')}`) }) + server.on('error', (err: NodeJS.ErrnoException) => { + if (err.code === 'EADDRINUSE') { + console.error( + red( + `Port ${options.port} is already in use. Please choose a different port using -p option.` + ) + ) + } else { + throw new CliError(`Failed to start the server: ${err.message}`) + } + process.exit(1) + }) + // Graceful shutdown process.on('SIGTERM', async () => { server.close(() => {