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
10 changes: 1 addition & 9 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,7 @@ It's good idea to install the [VSCode extension](https://marketplace.visualstudi

## Adding to an existing project

To add ZenStack to an existing Next.js + Typescript project, follow the steps below:

1. Install zenstack cli

```bash
npm install --save-dev zenstack
```

2. Initialize the project
To add ZenStack to an existing Next.js + Typescript project, run command below:

```bash
npx zenstack init
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "zenstack-monorepo",
"version": "0.3.9",
"version": "0.3.10",
"description": "",
"scripts": {
"build": "pnpm -r build",
Expand Down
2 changes: 1 addition & 1 deletion packages/internal/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@zenstackhq/internal",
"version": "0.3.9",
"version": "0.3.10",
"displayName": "ZenStack Internal Library",
"description": "ZenStack internal runtime library. This package is for supporting runtime functionality of ZenStack and not supposed to be used directly.",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion packages/runtime/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zenstackhq/runtime",
"displayName": "ZenStack Runtime Library",
"version": "0.3.9",
"version": "0.3.10",
"description": "This package contains runtime library for consuming client and server side code generated by ZenStack.",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion packages/schema/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"publisher": "zenstack",
"displayName": "ZenStack Language Tools",
"description": "A toolkit for modeling data and access policies in full-stack development with Next.js and Typescript",
"version": "0.3.9",
"version": "0.3.10",
"author": {
"name": "ZenStack Team"
},
Expand Down
87 changes: 87 additions & 0 deletions packages/schema/src/cli/cli-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,93 @@ import { GENERATED_CODE_PATH } from '../generator/constants';
import { Context, GeneratorError } from '../generator/types';
import { CliError } from './cli-error';

/**
* Initializes an existing project for ZenStack
*/
export async function initProject(projectPath: string) {
const schema = path.join(projectPath, 'zenstack', 'schema.zmodel');
if (fs.existsSync(schema)) {
console.warn(colors.yellow(`Model already exists: ${schema}`));
throw new CliError(`schema file already exists`);
}

// create a default model
if (!fs.existsSync(path.join(projectPath, 'zenstack'))) {
fs.mkdirSync(path.join(projectPath, 'zenstack'));
}

fs.writeFileSync(
schema,
`// This is a sample model to get you started.
// Learn how to model you app: https://zenstack.dev/#/modeling-your-app.

/*
* A sample data source using local sqlite db.
* See how to use a different db: https://zenstack.dev/#/zmodel-data-source.
*/
datasource db {
provider = 'sqlite'
url = 'file:./todo.db'
}

/*
* User model
*/
model User {
id String @id @default(cuid())
email String @unique @email
password String @password @omit @length(8, 16)
posts Post[]

// everybody can signup
@@allow('create', true)

// full access by self
@@allow('all', auth() == this)
}

/*
* Post model
*/
model Post {
id String @id @default(cuid())
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
title String @length(1, 256)
content String
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId String?

// allow read for all signin users
@@allow('read', auth() != null && published)

// full access by author
@@allow('all', author == auth())
}
`
);

// add zenstack/schema.prisma to .gitignore
const gitIgnorePath = path.join(projectPath, '.gitignore');
let gitIgnoreContent = '';
if (fs.existsSync(gitIgnorePath)) {
gitIgnoreContent =
fs.readFileSync(gitIgnorePath, { encoding: 'utf-8' }) + '\n';
}

if (!gitIgnoreContent.includes('zenstack/schema.prisma')) {
gitIgnoreContent += 'zenstack/schema.prisma\n';
fs.writeFileSync(gitIgnorePath, gitIgnoreContent);
}

console.log(`Sample model generated at: ${colors.green(schema)}

Please check the following guide on how to model your app:
https://zenstack.dev/#/modeling-your-app.
`);
}

/**
* Loads a zmodel document from a file.
* @param fileName File name
Expand Down
18 changes: 17 additions & 1 deletion packages/schema/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ import { ZModelLanguageMetaData } from '../language-server/generated/module';
import telemetry from '../telemetry';
import { execSync } from '../utils/exec-utils';
import { CliError } from './cli-error';
import { runGenerator } from './cli-util';
import { initProject, runGenerator } from './cli-util';

export const initAction = async (projectPath: string): Promise<void> => {
await telemetry.trackSpan(
'cli:command:start',
'cli:command:complete',
'cli:command:error',
{ command: 'init' },
() => initProject(projectPath)
);
};

export const generateAction = async (options: {
schema: string;
Expand Down Expand Up @@ -108,6 +118,12 @@ export default async function (): Promise<void> {

//#region wraps Prisma commands

program
.command('init')
.description('Set up a new ZenStack project.')
.argument('<path>', 'project path')
.action(initAction);

program
.command('generate')
.description(
Expand Down
9 changes: 9 additions & 0 deletions packages/schema/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import cuid from 'cuid';
import * as os from 'os';
import sleep from 'sleep-promise';
import exitHook from 'async-exit-hook';
import { CliError } from './cli/cli-error';
import { CommanderError } from 'commander';

/**
* Telemetry events
Expand Down Expand Up @@ -57,6 +59,13 @@ export class Telemetry {
// a small delay to ensure telemetry is sent
await sleep(this.exitWait);
}

if (err instanceof CliError || err instanceof CommanderError) {
// error already handled
} else {
throw err;
}

process.exit(1);
});
}
Expand Down
2 changes: 1 addition & 1 deletion samples/todo/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "todo",
"version": "0.3.9",
"version": "0.3.10",
"private": true,
"scripts": {
"dev": "next dev",
Expand Down