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: 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.27",
"version": "3.0.0-alpha.28",
"description": "ZenStack",
"packageManager": "[email protected]",
"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.27",
"version": "3.0.0-alpha.28",
"type": "module",
"author": {
"name": "ZenStack Team"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type Options = {
};

/**
* CLI action for validating schema without generation
* CLI action for checking a schema's validity.
*/
export async function run(options: Options) {
const schemaFile = getSchemaFile(options.schema);
Expand Down
7 changes: 2 additions & 5 deletions packages/cli/src/actions/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { getPkgJsonConfig, getSchemaFile, loadSchemaDocument } from './action-ut
type Options = {
schema?: string;
output?: string;
silent?: boolean;
};

/**
Expand All @@ -28,9 +27,8 @@ export async function run(options: Options) {

await runPlugins(schemaFile, model, outputPath);

if (!options.silent) {
console.log(colors.green(`Generation completed successfully in ${Date.now() - start}ms.\n`));
console.log(`You can now create a ZenStack client with it.
console.log(colors.green(`Generation completed successfully in ${Date.now() - start}ms.\n`));
console.log(`You can now create a ZenStack client with it.

\`\`\`ts
import { ZenStackClient } from '@zenstackhq/runtime';
Expand All @@ -40,7 +38,6 @@ const client = new ZenStackClient(schema, {
dialect: { ... }
});
\`\`\``);
}
}

function getOutputPath(options: Options, schemaFile: string) {
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/src/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { run as generate } from './generate';
import { run as info } from './info';
import { run as init } from './init';
import { run as migrate } from './migrate';
import { run as validate } from './validate';
import { run as check } from './check';

export { db, generate, info, init, migrate, validate };
export { db, generate, info, init, migrate, check };
29 changes: 16 additions & 13 deletions packages/cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ const initAction = async (projectPath: string): Promise<void> => {
await actions.init(projectPath);
};

const validateAction = async (options: Parameters<typeof actions.validate>[0]): Promise<void> => {
await actions.validate(options);
const checkAction = async (options: Parameters<typeof actions.check>[0]): Promise<void> => {
await actions.check(options);
};

export function createProgram() {
Expand All @@ -40,26 +40,25 @@ export function createProgram() {
.description(
`${colors.bold.blue(
'ζ',
)} ZenStack is a database access toolkit for TypeScript apps.\n\nDocumentation: https://zenstack.dev.`,
)} ZenStack is the data layer for modern TypeScript apps.\n\nDocumentation: https://zenstack.dev.`,
)
.showHelpAfterError()
.showSuggestionAfterError();

const schemaOption = new Option(
'--schema <file>',
`schema file (with extension ${schemaExtensions}). Defaults to "schema.zmodel" unless specified in package.json.`,
`schema file (with extension ${schemaExtensions}). Defaults to "zenstack/schema.zmodel" unless specified in package.json.`,
);

program
.command('generate')
.description('Run code generation.')
.description('Run code generation plugins.')
.addOption(schemaOption)
.addOption(new Option('--silent', 'do not print any output'))
.addOption(new Option('-o, --output <path>', 'default output directory for core plugins'))
.addOption(new Option('-o, --output <path>', 'default output directory for code generation'))
.action(generateAction);

const migrateCommand = program.command('migrate').description('Update the database schema with migrations.');
const migrationsOption = new Option('--migrations <path>', 'path for migrations');
const migrateCommand = program.command('migrate').description('Run database schema migration related tasks.');
const migrationsOption = new Option('--migrations <path>', 'path that contains the "migrations" directory');

migrateCommand
.command('dev')
Expand Down Expand Up @@ -98,22 +97,22 @@ export function createProgram() {
.addOption(migrationsOption)
.addOption(new Option('--applied <migration>', 'record a specific migration as applied'))
.addOption(new Option('--rolled-back <migration>', 'record a specific migration as rolled back'))
.description('Resolve issues with database migrations in deployment databases')
.description('Resolve issues with database migrations in deployment databases.')
.action((options) => migrateAction('resolve', options));

const dbCommand = program.command('db').description('Manage your database schema during development.');

dbCommand
.command('push')
.description('Push the state from your schema to your database')
.description('Push the state from your schema to your database.')
.addOption(schemaOption)
.addOption(new Option('--accept-data-loss', 'ignore data loss warnings'))
.addOption(new Option('--force-reset', 'force a reset of the database before push'))
.action((options) => dbAction('push', options));

program
.command('info')
.description('Get information of installed ZenStack and related packages.')
.description('Get information of installed ZenStack packages.')
.argument('[path]', 'project path', '.')
.action(infoAction);

Expand All @@ -123,7 +122,11 @@ export function createProgram() {
.argument('[path]', 'project path', '.')
.action(initAction);

program.command('validate').description('Validate a ZModel schema.').addOption(schemaOption).action(validateAction);
program
.command('check')
.description('Check a ZModel schema for syntax or semantic errors.')
.addOption(schemaOption)
.action(checkAction);

return program;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,29 @@ describe('CLI validate command test', () => {
const workDir = createProject(validModel);

// Should not throw an error
expect(() => runCli('validate', workDir)).not.toThrow();
expect(() => runCli('check', workDir)).not.toThrow();
});

it('should fail validation for invalid schema', () => {
const workDir = createProject(invalidModel);

// Should throw an error due to validation failure
expect(() => runCli('validate', workDir)).toThrow();
expect(() => runCli('check', workDir)).toThrow();
});

it('should respect custom schema location', () => {
const workDir = createProject(validModel);
fs.renameSync(path.join(workDir, 'zenstack/schema.zmodel'), path.join(workDir, 'zenstack/custom.zmodel'));

// Should not throw an error when using custom schema path
expect(() => runCli('validate --schema ./zenstack/custom.zmodel', workDir)).not.toThrow();
expect(() => runCli('check --schema ./zenstack/custom.zmodel', workDir)).not.toThrow();
});

it('should fail when schema file does not exist', () => {
const workDir = createProject(validModel);

// Should throw an error when schema file doesn't exist
expect(() => runCli('validate --schema ./nonexistent.zmodel', workDir)).toThrow();
expect(() => runCli('check --schema ./nonexistent.zmodel', workDir)).toThrow();
});

it('should respect package.json config', () => {
Expand All @@ -78,7 +78,7 @@ describe('CLI validate command test', () => {
fs.writeFileSync(path.join(workDir, 'package.json'), JSON.stringify(pkgJson, null, 2));

// Should not throw an error when using package.json config
expect(() => runCli('validate', workDir)).not.toThrow();
expect(() => runCli('check', workDir)).not.toThrow();
});

it('should validate schema with syntax errors', () => {
Expand All @@ -96,6 +96,6 @@ model User {
const workDir = createProject(modelWithSyntaxError, false);

// Should throw an error due to syntax error
expect(() => runCli('validate', workDir)).toThrow();
expect(() => runCli('check', workDir)).toThrow();
});
});
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.27",
"version": "3.0.0-alpha.28",
"description": "ZenStack Common Helpers",
"type": "module",
"scripts": {
Expand Down
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.27",
"version": "3.0.0-alpha.28",
"description": "Create a new ZenStack project",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/dialects/sql.js/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/kysely-sql-js",
"version": "3.0.0-alpha.27",
"version": "3.0.0-alpha.28",
"description": "Kysely dialect for sql.js",
"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.27",
"version": "3.0.0-alpha.28",
"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.27",
"version": "3.0.0-alpha.28",
"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.27",
"version": "3.0.0-alpha.28",
"license": "MIT",
"author": "ZenStack Team",
"files": [
Expand Down
81 changes: 6 additions & 75 deletions packages/language/res/stdlib.zmodel
Original file line number Diff line number Diff line change
Expand Up @@ -424,73 +424,39 @@ attribute @@fulltext(_ fields: FieldReference[], map: String?) @@@prisma

// String type modifiers

enum MSSQLServerTypes {
Max
}

attribute @db.String(_ x: Int?) @@@targetField([StringField]) @@@prisma
attribute @db.Text() @@@targetField([StringField]) @@@prisma
attribute @db.NText() @@@targetField([StringField]) @@@prisma
attribute @db.Char(_ x: Int?) @@@targetField([StringField]) @@@prisma
attribute @db.NChar(_ x: Int?) @@@targetField([StringField]) @@@prisma
attribute @db.VarChar(_ x: Any?) @@@targetField([StringField]) @@@prisma
attribute @db.NVarChar(_ x: Any?) @@@targetField([StringField]) @@@prisma
attribute @db.CatalogSingleChar() @@@targetField([StringField]) @@@prisma
attribute @db.TinyText() @@@targetField([StringField]) @@@prisma
attribute @db.MediumText() @@@targetField([StringField]) @@@prisma
attribute @db.LongText() @@@targetField([StringField]) @@@prisma
attribute @db.Bit(_ x: Int?) @@@targetField([StringField, BooleanField, BytesField]) @@@prisma
attribute @db.VarBit(_ x: Int?) @@@targetField([StringField]) @@@prisma
attribute @db.Uuid() @@@targetField([StringField]) @@@prisma
attribute @db.UniqueIdentifier() @@@targetField([StringField]) @@@prisma
attribute @db.Xml() @@@targetField([StringField]) @@@prisma
attribute @db.Inet() @@@targetField([StringField]) @@@prisma
attribute @db.Citext() @@@targetField([StringField]) @@@prisma

// Boolean type modifiers

attribute @db.Boolean() @@@targetField([BooleanField]) @@@prisma
attribute @db.TinyInt(_ x: Int?) @@@targetField([BooleanField, IntField]) @@@prisma
attribute @db.Bool() @@@targetField([BooleanField]) @@@prisma

// Int type modifiers

attribute @db.Int() @@@targetField([IntField]) @@@prisma
attribute @db.Integer() @@@targetField([IntField]) @@@prisma
attribute @db.SmallInt() @@@targetField([IntField]) @@@prisma
attribute @db.Oid() @@@targetField([IntField]) @@@prisma
attribute @db.UnsignedInt() @@@targetField([IntField]) @@@prisma
attribute @db.UnsignedSmallInt() @@@targetField([IntField]) @@@prisma
attribute @db.MediumInt() @@@targetField([IntField]) @@@prisma
attribute @db.UnsignedMediumInt() @@@targetField([IntField]) @@@prisma
attribute @db.UnsignedTinyInt() @@@targetField([IntField]) @@@prisma
attribute @db.Year() @@@targetField([IntField]) @@@prisma
attribute @db.Int4() @@@targetField([IntField]) @@@prisma
attribute @db.Int2() @@@targetField([IntField]) @@@prisma

// BigInt type modifiers

attribute @db.BigInt() @@@targetField([BigIntField]) @@@prisma
attribute @db.UnsignedBigInt() @@@targetField([BigIntField]) @@@prisma
attribute @db.Int8() @@@targetField([BigIntField]) @@@prisma

// Float/Decimal type modifiers
attribute @db.DoublePrecision() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Real() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Float() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Decimal(_ p: Int?, _ s: Int?) @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Double() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Money() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.SmallMoney() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Float8() @@@targetField([FloatField, DecimalField]) @@@prisma
attribute @db.Float4() @@@targetField([FloatField, DecimalField]) @@@prisma

// DateTime type modifiers

attribute @db.DateTime(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
attribute @db.DateTime2() @@@targetField([DateTimeField]) @@@prisma
attribute @db.SmallDateTime() @@@targetField([DateTimeField]) @@@prisma
attribute @db.DateTimeOffset() @@@targetField([DateTimeField]) @@@prisma
attribute @db.Timestamp(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
attribute @db.Timestamptz(_ x: Int?) @@@targetField([DateTimeField]) @@@prisma
attribute @db.Date() @@@targetField([DateTimeField]) @@@prisma
Expand All @@ -504,49 +470,14 @@ attribute @db.JsonB() @@@targetField([JsonField]) @@@prisma

// Bytes type modifiers

attribute @db.Bytes() @@@targetField([BytesField]) @@@prisma
attribute @db.ByteA() @@@targetField([BytesField]) @@@prisma
attribute @db.LongBlob() @@@targetField([BytesField]) @@@prisma
attribute @db.Binary() @@@targetField([BytesField]) @@@prisma
attribute @db.VarBinary(_ x: Int?) @@@targetField([BytesField]) @@@prisma
attribute @db.TinyBlob() @@@targetField([BytesField]) @@@prisma
attribute @db.Blob() @@@targetField([BytesField]) @@@prisma
attribute @db.MediumBlob() @@@targetField([BytesField]) @@@prisma
attribute @db.Image() @@@targetField([BytesField]) @@@prisma

/**
* Specifies the schema to use in a multi-schema database. https://www.prisma.io/docs/guides/database/multi-schema.
*
* @param: The name of the database schema.
*/
attribute @@schema(_ name: String) @@@prisma

/**
* Indicates that the field is a password field and needs to be hashed before persistence.
*
* ZenStack uses `bcryptjs` library to hash password. You can use the `saltLength` parameter
* to configure the cost of hashing, or use `salt` parameter to provide an explicit salt.
* By default, salt length of 12 is used.
*
* @see https://www.npmjs.com/package/bcryptjs for details
*
* @param saltLength: length of salt to use (cost factor for the hash function)
* @param salt: salt to use (a pregenerated valid salt)
*/
attribute @password(saltLength: Int?, salt: String?) @@@targetField([StringField])


/**
* Indicates that the field is encrypted when storing in the DB and should be decrypted when read
*
* ZenStack uses the Web Crypto API to encrypt and decrypt the field.
*/
attribute @encrypted() @@@targetField([StringField])

/**
* Indicates that the field should be omitted when read from the generated services.
*/
attribute @omit()
// /**
// * Specifies the schema to use in a multi-schema database. https://www.prisma.io/docs/guides/database/multi-schema.
// *
// * @param: The name of the database schema.
// */
// attribute @@schema(_ name: String) @@@prisma

//////////////////////////////////////////////
// Begin validation attributes and functions
Expand Down
2 changes: 1 addition & 1 deletion 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.27",
"version": "3.0.0-alpha.28",
"description": "ZenStack Runtime",
"type": "module",
"scripts": {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/src/client/client-impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import type { ToKysely } from './query-builder';
import { ResultProcessor } from './result-processor';

/**
* ZenStack client.
* ZenStack ORM client.
*/
export const ZenStackClient = function <Schema extends SchemaDef>(
this: any,
Expand Down
Loading