Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
packages/language/src/generated/**
**/schema.ts
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zenstack-v3",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"description": "ZenStack",
"packageManager": "pnpm@10.12.1",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"publisher": "zenstack",
"displayName": "ZenStack CLI",
"description": "FullStack database toolkit with built-in access control and automatic API generation.",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"type": "module",
"author": {
"name": "ZenStack Team"
Expand Down
32 changes: 32 additions & 0 deletions packages/cli/src/actions/action-utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { findUp } from '@zenstackhq/common-helpers';
import { loadDocument } from '@zenstackhq/language';
import { PrismaSchemaGenerator } from '@zenstackhq/sdk';
import colors from 'colors';
Expand All @@ -13,6 +14,14 @@ export function getSchemaFile(file?: string) {
return file;
}

const pkgJsonConfig = getPkgJsonConfig(process.cwd());
if (pkgJsonConfig.schema) {
if (!fs.existsSync(pkgJsonConfig.schema)) {
throw new CliError(`Schema file not found: ${pkgJsonConfig.schema}`);
}
return pkgJsonConfig.schema;
}

if (fs.existsSync('./zenstack/schema.zmodel')) {
return './zenstack/schema.zmodel';
} else if (fs.existsSync('./schema.zmodel')) {
Expand Down Expand Up @@ -51,3 +60,26 @@ export async function generateTempPrismaSchema(zmodelPath: string) {
fs.writeFileSync(prismaSchemaFile, prismaSchema);
return prismaSchemaFile;
}

export function getPkgJsonConfig(startPath: string) {
const result: { schema: string | undefined; output: string | undefined } = { schema: undefined, output: undefined };
const pkgJsonFile = findUp(['package.json'], startPath, false);

if (!pkgJsonFile) {
return result;
}

let pkgJson: any = undefined;
try {
pkgJson = JSON.parse(fs.readFileSync(pkgJsonFile, 'utf8'));
} catch {
return result;
}

if (pkgJson.zenstack && typeof pkgJson.zenstack === 'object') {
result.schema = pkgJson.zenstack.schema && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.schema);
result.output = pkgJson.zenstack.output && path.resolve(path.dirname(pkgJsonFile), pkgJson.zenstack.output);
}

return result;
}
15 changes: 9 additions & 6 deletions packages/cli/src/actions/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,16 @@ async function runPush(options: Options) {

try {
// run prisma db push
const cmd = `prisma db push --schema "${prismaSchemaFile}"${
options.acceptDataLoss ? ' --accept-data-loss' : ''
}${options.forceReset ? ' --force-reset' : ''} --skip-generate`;
const cmd = [
'prisma db push',
` --schema "${prismaSchemaFile}"`,
options.acceptDataLoss ? ' --accept-data-loss' : '',
options.forceReset ? ' --force-reset' : '',
' --skip-generate',
].join('');

try {
await execPackage(cmd, {
stdio: 'inherit',
});
await execPackage(cmd);
} catch (err) {
handleSubProcessError(err);
}
Expand Down
16 changes: 14 additions & 2 deletions packages/cli/src/actions/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { PrismaSchemaGenerator, TsSchemaGenerator, type CliGenerator } from '@ze
import colors from 'colors';
import fs from 'node:fs';
import path from 'node:path';
import { getSchemaFile, loadSchemaDocument } from './action-utils';
import { getPkgJsonConfig, getSchemaFile, loadSchemaDocument } from './action-utils';

type Options = {
schema?: string;
Expand All @@ -20,7 +20,7 @@ export async function run(options: Options) {
const schemaFile = getSchemaFile(options.schema);

const model = await loadSchemaDocument(schemaFile);
const outputPath = options.output ?? path.dirname(schemaFile);
const outputPath = getOutputPath(options, schemaFile);

// generate TS schema
const tsSchemaFile = path.join(outputPath, 'schema.ts');
Expand Down Expand Up @@ -55,6 +55,18 @@ const client = new ZenStackClient(schema, {
}
}

function getOutputPath(options: Options, schemaFile: string) {
if (options.output) {
return options.output;
}
const pkgJsonConfig = getPkgJsonConfig(process.cwd());
if (pkgJsonConfig.output) {
return pkgJsonConfig.output;
} else {
return path.dirname(schemaFile);
}
}

async function runPlugins(model: Model, outputPath: string, tsSchemaFile: string) {
const plugins = model.declarations.filter(isPlugin);
for (const plugin of plugins) {
Expand Down
33 changes: 18 additions & 15 deletions packages/cli/src/actions/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,42 +53,45 @@ export async function run(command: string, options: CommonOptions) {

async function runDev(prismaSchemaFile: string, options: DevOptions) {
try {
await execPackage(
`prisma migrate dev --schema "${prismaSchemaFile}" --skip-generate${options.name ? ` --name ${options.name}` : ''}${options.createOnly ? ' --create-only' : ''}`,
{
stdio: 'inherit',
},
);
const cmd = [
'prisma migrate dev',
` --schema "${prismaSchemaFile}"`,
' --skip-generate',
options.name ? ` --name ${options.name}` : '',
options.createOnly ? ' --create-only' : '',
].join('');

await execPackage(cmd);
} catch (err) {
handleSubProcessError(err);
}
}

async function runReset(prismaSchemaFile: string, options: ResetOptions) {
try {
await execPackage(`prisma migrate reset --schema "${prismaSchemaFile}"${options.force ? ' --force' : ''}`, {
stdio: 'inherit',
});
const cmd = ['prisma migrate reset', ` --schema "${prismaSchemaFile}"`, options.force ? ' --force' : ''].join(
'',
);

await execPackage(cmd);
} catch (err) {
handleSubProcessError(err);
}
}

async function runDeploy(prismaSchemaFile: string, _options: DeployOptions) {
try {
await execPackage(`prisma migrate deploy --schema "${prismaSchemaFile}"`, {
stdio: 'inherit',
});
const cmd = ['prisma migrate deploy', ` --schema "${prismaSchemaFile}"`].join('');

await execPackage(cmd);
} catch (err) {
handleSubProcessError(err);
}
}

async function runStatus(prismaSchemaFile: string, _options: StatusOptions) {
try {
await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`, {
stdio: 'inherit',
});
await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`);
} catch (err) {
handleSubProcessError(err);
}
Expand Down
15 changes: 15 additions & 0 deletions packages/cli/test/generate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,19 @@ describe('CLI generate command test', () => {
runCli('generate --save-prisma-schema "../prisma/schema.prisma"', workDir);
expect(fs.existsSync(path.join(workDir, 'prisma/schema.prisma'))).toBe(true);
});

it('should respect package.json config', () => {
const workDir = createProject(model);
fs.mkdirSync(path.join(workDir, 'foo'));
fs.renameSync(path.join(workDir, 'zenstack/schema.zmodel'), path.join(workDir, 'foo/schema.zmodel'));
fs.rmdirSync(path.join(workDir, 'zenstack'));
const pkgJson = JSON.parse(fs.readFileSync(path.join(workDir, 'package.json'), 'utf8'));
pkgJson.zenstack = {
schema: './foo/schema.zmodel',
output: './bar',
};
fs.writeFileSync(path.join(workDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
runCli('generate', workDir);
expect(fs.existsSync(path.join(workDir, 'bar/schema.ts'))).toBe(true);
});
});
2 changes: 1 addition & 1 deletion packages/common-helpers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/common-helpers",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"description": "ZenStack Common Helpers",
"type": "module",
"scripts": {
Expand Down
34 changes: 34 additions & 0 deletions packages/common-helpers/src/find-up.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import fs from 'fs';
import path from 'path';

/**
* A type named FindUp that takes a type parameter e which extends boolean.
*/
export type FindUpResult<Multiple extends boolean> = Multiple extends true ? string[] | undefined : string | undefined;

/**
* Find and return file paths by searching parent directories based on the given names list and current working directory (cwd) path.
* Optionally return a single path or multiple paths.
* If multiple allowed, return all paths found.
* If no paths are found, return undefined.
*
* @param names An array of strings representing names to search for within the directory
* @param cwd A string representing the current working directory
* @param multiple A boolean flag indicating whether to search for multiple levels. Useful for finding node_modules directories...
* @param An array of strings representing the accumulated results used in multiple results
* @returns Path(s) to a specific file or folder within the directory or parent directories
*/
export function findUp<Multiple extends boolean = false>(
names: string[],
cwd: string = process.cwd(),
multiple: Multiple = false as Multiple,
result: string[] = [],
): FindUpResult<Multiple> {
if (!names.some((name) => !!name)) return undefined;
const target = names.find((name) => fs.existsSync(path.join(cwd, name)));
if (multiple === false && target) return path.join(cwd, target) as FindUpResult<Multiple>;
if (target) result.push(path.join(cwd, target));
const up = path.resolve(cwd, '..');
if (up === cwd) return (multiple && result.length > 0 ? result : undefined) as FindUpResult<Multiple>; // it'll fail anyway
return findUp(names, up, multiple, result);
}
1 change: 1 addition & 0 deletions packages/common-helpers/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './find-up';
export * from './is-plain-object';
export * from './lower-case-first';
export * from './param-case';
Expand Down
16 changes: 10 additions & 6 deletions packages/common-helpers/src/param-case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ const DEFAULT_STRIP_REGEXP = /[^A-Z0-9]+/gi;

export function paramCase(input: string) {
const result = input
.replace(DEFAULT_SPLIT_REGEXP_1, "$1\0$2")
.replace(DEFAULT_SPLIT_REGEXP_2, "$1\0$2")
.replace(DEFAULT_STRIP_REGEXP, "\0");
.replace(DEFAULT_SPLIT_REGEXP_1, '$1\0$2')
.replace(DEFAULT_SPLIT_REGEXP_2, '$1\0$2')
.replace(DEFAULT_STRIP_REGEXP, '\0');

let start = 0;
let end = result.length;

while (result.charAt(start) === "\0") start++;
while (result.charAt(end - 1) === "\0") end--;
while (result.charAt(start) === '\0') start++;
while (result.charAt(end - 1) === '\0') end--;

return result.slice(start, end).split("\0").map((str) => str.toLowerCase()).join("-");
return result
.slice(start, end)
.split('\0')
.map((str) => str.toLowerCase())
.join('-');
}
2 changes: 1 addition & 1 deletion packages/create-zenstack/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-zenstack",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"description": "Create a new ZenStack project",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-config/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/eslint-config",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"type": "module",
"private": true,
"license": "MIT"
Expand Down
2 changes: 1 addition & 1 deletion packages/ide/vscode/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "zenstack",
"publisher": "zenstack",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"displayName": "ZenStack Language Tools",
"description": "VSCode extension for ZenStack ZModel language",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion packages/language/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/language",
"description": "ZenStack ZModel language specification",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"license": "MIT",
"author": "ZenStack Team",
"files": [
Expand Down
6 changes: 3 additions & 3 deletions packages/language/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,9 @@ export function getObjectLiteral<T>(expr: Expression | ConfigExpr | undefined):
return result as T;
}

export function getLiteralArray<
T extends string | number | boolean | any = any,
>(expr: Expression | ConfigExpr | undefined): T[] | undefined {
export function getLiteralArray<T extends string | number | boolean | any = any>(
expr: Expression | ConfigExpr | undefined,
): T[] | undefined {
const arr = getArray(expr);
if (!arr) {
return undefined;
Expand Down
18 changes: 14 additions & 4 deletions packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/runtime",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"description": "ZenStack Runtime",
"type": "module",
"scripts": {
Expand Down Expand Up @@ -39,6 +39,16 @@
"default": "./dist/schema.cjs"
}
},
"./helpers": {
"import": {
"types": "./dist/helpers.d.ts",
"default": "./dist/helpers.js"
},
"require": {
"types": "./dist/helpers.d.cts",
"default": "./dist/helpers.cjs"
}
},
"./plugins/policy": {
"import": {
"types": "./dist/plugins/policy.d.ts",
Expand All @@ -63,12 +73,12 @@
"nanoid": "^5.0.9",
"ts-pattern": "catalog:",
"ulid": "^3.0.0",
"uuid": "^11.0.5"
"uuid": "^11.0.5",
"zod": "catalog:"
},
"peerDependencies": {
"better-sqlite3": "^11.8.1",
"pg": "^8.13.1",
"zod": "catalog:"
"pg": "^8.13.1"
},
"peerDependenciesMeta": {
"better-sqlite3": {
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime/src/client/client-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { CountOperationHandler } from './crud/operations/count';
import { CreateOperationHandler } from './crud/operations/create';
import { DeleteOperationHandler } from './crud/operations/delete';
import { FindOperationHandler } from './crud/operations/find';
import { GroupByeOperationHandler } from './crud/operations/group-by';
import { GroupByOperationHandler } from './crud/operations/group-by';
import { UpdateOperationHandler } from './crud/operations/update';
import { InputValidator } from './crud/validator';
import { NotFoundError, QueryError } from './errors';
Expand Down Expand Up @@ -504,7 +504,7 @@ function createModelCrudHandler<Schema extends SchemaDef, Model extends GetModel
},

groupBy: (args: unknown) => {
return createPromise('groupBy', args, new GroupByeOperationHandler(client, model, inputValidator));
return createPromise('groupBy', args, new GroupByOperationHandler(client, model, inputValidator));
},
} as ModelOperations<Schema, Model>;
}
Loading