zenstack 0.3.10 → 0.3.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/cli/index.js +174 -174
- package/package.json +2 -2
- package/src/cli/cli-util.ts +36 -27
- package/src/cli/index.ts +8 -0
- package/src/generator/constants.ts +1 -1
- package/src/generator/prisma/query-guard-generator.ts +3 -3
- package/src/generator/react-hooks/index.ts +4 -2
- package/src/generator/service/index.ts +2 -2
- package/src/utils/pkg-utils.ts +63 -0
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publisher": "zenstack",
|
|
4
4
|
"displayName": "ZenStack Language Tools",
|
|
5
5
|
"description": "A toolkit for modeling data and access policies in full-stack development with Next.js and Typescript",
|
|
6
|
-
"version": "0.3.
|
|
6
|
+
"version": "0.3.11",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "ZenStack Team"
|
|
9
9
|
},
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
},
|
|
66
66
|
"main": "./bundle/extension.js",
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@zenstackhq/
|
|
68
|
+
"@zenstackhq/runtime": "0.3.11",
|
|
69
69
|
"async-exit-hook": "^2.0.1",
|
|
70
70
|
"change-case": "^4.1.2",
|
|
71
71
|
"chevrotain": "^9.1.0",
|
package/src/cli/cli-util.ts
CHANGED
|
@@ -6,8 +6,9 @@ import fs from 'fs';
|
|
|
6
6
|
import { LangiumServices } from 'langium';
|
|
7
7
|
import { NodeFileSystem } from 'langium/node';
|
|
8
8
|
import path from 'path';
|
|
9
|
-
import {
|
|
9
|
+
import { installPackage } from 'src/utils/pkg-utils';
|
|
10
10
|
import { URI } from 'vscode-uri';
|
|
11
|
+
import { ZenStackGenerator } from '../generator';
|
|
11
12
|
import { GENERATED_CODE_PATH } from '../generator/constants';
|
|
12
13
|
import { Context, GeneratorError } from '../generator/types';
|
|
13
14
|
import { CliError } from './cli-error';
|
|
@@ -17,19 +18,19 @@ import { CliError } from './cli-error';
|
|
|
17
18
|
*/
|
|
18
19
|
export async function initProject(projectPath: string) {
|
|
19
20
|
const schema = path.join(projectPath, 'zenstack', 'schema.zmodel');
|
|
21
|
+
let schemaGenerated = false;
|
|
22
|
+
|
|
20
23
|
if (fs.existsSync(schema)) {
|
|
21
24
|
console.warn(colors.yellow(`Model already exists: ${schema}`));
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
fs.mkdirSync(path.join(projectPath, 'zenstack'));
|
|
28
|
-
}
|
|
25
|
+
} else {
|
|
26
|
+
// create a default model
|
|
27
|
+
if (!fs.existsSync(path.join(projectPath, 'zenstack'))) {
|
|
28
|
+
fs.mkdirSync(path.join(projectPath, 'zenstack'));
|
|
29
|
+
}
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
fs.writeFileSync(
|
|
32
|
+
schema,
|
|
33
|
+
`// This is a sample model to get you started.
|
|
33
34
|
// Learn how to model you app: https://zenstack.dev/#/modeling-your-app.
|
|
34
35
|
|
|
35
36
|
/*
|
|
@@ -77,26 +78,34 @@ model Post {
|
|
|
77
78
|
@@allow('all', author == auth())
|
|
78
79
|
}
|
|
79
80
|
`
|
|
80
|
-
|
|
81
|
+
);
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
// add zenstack/schema.prisma to .gitignore
|
|
84
|
+
const gitIgnorePath = path.join(projectPath, '.gitignore');
|
|
85
|
+
let gitIgnoreContent = '';
|
|
86
|
+
if (fs.existsSync(gitIgnorePath)) {
|
|
87
|
+
gitIgnoreContent =
|
|
88
|
+
fs.readFileSync(gitIgnorePath, { encoding: 'utf-8' }) + '\n';
|
|
89
|
+
}
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
if (!gitIgnoreContent.includes('zenstack/schema.prisma')) {
|
|
92
|
+
gitIgnoreContent += 'zenstack/schema.prisma\n';
|
|
93
|
+
fs.writeFileSync(gitIgnorePath, gitIgnoreContent);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
schemaGenerated = true;
|
|
93
97
|
}
|
|
94
98
|
|
|
95
|
-
|
|
99
|
+
installPackage('zenstack', true, undefined, projectPath);
|
|
100
|
+
installPackage('@zenstackhq/runtime', false, undefined, projectPath);
|
|
101
|
+
|
|
102
|
+
if (schemaGenerated) {
|
|
103
|
+
console.log(`Sample model generated at: ${colors.green(schema)}
|
|
96
104
|
|
|
97
|
-
Please check the following guide on how to model your app:
|
|
98
|
-
|
|
99
|
-
`);
|
|
105
|
+
Please check the following guide on how to model your app:
|
|
106
|
+
https://zenstack.dev/#/modeling-your-app.
|
|
107
|
+
`);
|
|
108
|
+
}
|
|
100
109
|
}
|
|
101
110
|
|
|
102
111
|
/**
|
|
@@ -164,7 +173,7 @@ export async function loadDocument(
|
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
export async function runGenerator(
|
|
167
|
-
options: { schema: string },
|
|
176
|
+
options: { schema: string; packageManager: string },
|
|
168
177
|
includedGenerators?: string[],
|
|
169
178
|
clearOutput = true
|
|
170
179
|
) {
|
package/src/cli/index.ts
CHANGED
|
@@ -21,6 +21,7 @@ export const initAction = async (projectPath: string): Promise<void> => {
|
|
|
21
21
|
|
|
22
22
|
export const generateAction = async (options: {
|
|
23
23
|
schema: string;
|
|
24
|
+
packageManager: string;
|
|
24
25
|
}): Promise<void> => {
|
|
25
26
|
await telemetry.trackSpan(
|
|
26
27
|
'cli:command:start',
|
|
@@ -116,11 +117,17 @@ export default async function (): Promise<void> {
|
|
|
116
117
|
`schema file (with extension ${schemaExtensions})`
|
|
117
118
|
).default('./zenstack/schema.zmodel');
|
|
118
119
|
|
|
120
|
+
const pmOption = new Option(
|
|
121
|
+
'--package-manager, -p',
|
|
122
|
+
'package manager to use: "npm", "yarn" or "pnpm"'
|
|
123
|
+
).default('auto detect');
|
|
124
|
+
|
|
119
125
|
//#region wraps Prisma commands
|
|
120
126
|
|
|
121
127
|
program
|
|
122
128
|
.command('init')
|
|
123
129
|
.description('Set up a new ZenStack project.')
|
|
130
|
+
.addOption(pmOption)
|
|
124
131
|
.argument('<path>', 'project path')
|
|
125
132
|
.action(initAction);
|
|
126
133
|
|
|
@@ -130,6 +137,7 @@ export default async function (): Promise<void> {
|
|
|
130
137
|
'Generates RESTful API and Typescript client for your data model.'
|
|
131
138
|
)
|
|
132
139
|
.addOption(schemaOption)
|
|
140
|
+
.addOption(pmOption)
|
|
133
141
|
.action(generateAction);
|
|
134
142
|
|
|
135
143
|
const migrate = program
|
|
@@ -10,12 +10,12 @@ import {
|
|
|
10
10
|
PolicyKind,
|
|
11
11
|
PolicyOperationKind,
|
|
12
12
|
RuntimeAttribute,
|
|
13
|
-
} from '@zenstackhq/
|
|
13
|
+
} from '@zenstackhq/runtime/server';
|
|
14
14
|
import path from 'path';
|
|
15
15
|
import { Project, SourceFile, VariableDeclarationKind } from 'ts-morph';
|
|
16
16
|
import {
|
|
17
17
|
GUARD_FIELD_NAME,
|
|
18
|
-
|
|
18
|
+
RUNTIME_PACKAGE,
|
|
19
19
|
UNKNOWN_USER_ID,
|
|
20
20
|
} from '../constants';
|
|
21
21
|
import { Context } from '../types';
|
|
@@ -38,7 +38,7 @@ export default class QueryGuardGenerator {
|
|
|
38
38
|
|
|
39
39
|
sf.addImportDeclaration({
|
|
40
40
|
namedImports: [{ name: 'QueryContext' }],
|
|
41
|
-
moduleSpecifier:
|
|
41
|
+
moduleSpecifier: `${RUNTIME_PACKAGE}/server`,
|
|
42
42
|
isTypeOnly: true,
|
|
43
43
|
});
|
|
44
44
|
|
|
@@ -5,7 +5,7 @@ import { paramCase } from 'change-case';
|
|
|
5
5
|
import { DataModel } from '@lang/generated/ast';
|
|
6
6
|
import colors from 'colors';
|
|
7
7
|
import { extractDataModelsWithAllowRules } from '../ast-utils';
|
|
8
|
-
import { API_ROUTE_NAME } from '../constants';
|
|
8
|
+
import { API_ROUTE_NAME, RUNTIME_PACKAGE } from '../constants';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Generate react data query hooks code
|
|
@@ -51,7 +51,9 @@ export default class ReactHooksGenerator implements Generator {
|
|
|
51
51
|
moduleSpecifier: '../../.prisma',
|
|
52
52
|
});
|
|
53
53
|
sf.addStatements([
|
|
54
|
-
`import
|
|
54
|
+
`import * as request from '${RUNTIME_PACKAGE}/lib/request';`,
|
|
55
|
+
`import { ServerErrorCode, RequestOptions } from '${RUNTIME_PACKAGE}/lib/types';`,
|
|
56
|
+
`import { validate } from '${RUNTIME_PACKAGE}/lib/validation';`,
|
|
55
57
|
`import { type SWRResponse } from 'swr';`,
|
|
56
58
|
`import { ${this.getValidator(
|
|
57
59
|
model,
|
|
@@ -2,7 +2,7 @@ import { Context, Generator } from '../types';
|
|
|
2
2
|
import { Project } from 'ts-morph';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import colors from 'colors';
|
|
5
|
-
import {
|
|
5
|
+
import { RUNTIME_PACKAGE } from '../constants';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Generates ZenStack service code
|
|
@@ -22,7 +22,7 @@ export default class ServiceGenerator implements Generator {
|
|
|
22
22
|
|
|
23
23
|
sf.addStatements([
|
|
24
24
|
`import { PrismaClient } from "../.prisma";`,
|
|
25
|
-
`import { DefaultService } from "${
|
|
25
|
+
`import { DefaultService } from "${RUNTIME_PACKAGE}/lib/service";`,
|
|
26
26
|
]);
|
|
27
27
|
|
|
28
28
|
const cls = sf.addClass({
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { execSync } from './exec-utils';
|
|
4
|
+
|
|
5
|
+
type PackageManagers = 'npm' | 'yarn' | 'pnpm';
|
|
6
|
+
|
|
7
|
+
function getPackageManager(projectPath = '.'): PackageManagers {
|
|
8
|
+
if (fs.existsSync(path.join(projectPath, 'yarn.lock'))) {
|
|
9
|
+
return 'yarn';
|
|
10
|
+
} else if (fs.existsSync(path.join(projectPath, 'pnpm-lock.yaml'))) {
|
|
11
|
+
return 'pnpm';
|
|
12
|
+
} else {
|
|
13
|
+
return 'npm';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function installPackage(
|
|
18
|
+
pkg: string,
|
|
19
|
+
dev: boolean,
|
|
20
|
+
pkgManager: PackageManagers | undefined = undefined,
|
|
21
|
+
projectPath = '.'
|
|
22
|
+
) {
|
|
23
|
+
const manager = pkgManager ?? getPackageManager(projectPath);
|
|
24
|
+
console.log(`Installing package "${pkg}" with ${manager}`);
|
|
25
|
+
switch (manager) {
|
|
26
|
+
case 'yarn':
|
|
27
|
+
execSync(
|
|
28
|
+
`yarn add --cwd "${projectPath}" ${
|
|
29
|
+
dev ? ' --save-dev' : ''
|
|
30
|
+
} ${pkg}`
|
|
31
|
+
);
|
|
32
|
+
break;
|
|
33
|
+
|
|
34
|
+
case 'pnpm':
|
|
35
|
+
execSync(
|
|
36
|
+
`pnpm add -C "${projectPath}" ${
|
|
37
|
+
dev ? ' --save-dev' : ''
|
|
38
|
+
} ${pkg}`
|
|
39
|
+
);
|
|
40
|
+
break;
|
|
41
|
+
|
|
42
|
+
default:
|
|
43
|
+
execSync(
|
|
44
|
+
`npm install --prefix "${projectPath}" ${
|
|
45
|
+
dev ? ' --save-dev' : ''
|
|
46
|
+
} ${pkg}`
|
|
47
|
+
);
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function ensurePackage(
|
|
53
|
+
pkg: string,
|
|
54
|
+
dev: boolean,
|
|
55
|
+
pkgManager: PackageManagers | undefined = undefined,
|
|
56
|
+
projectPath = '.'
|
|
57
|
+
) {
|
|
58
|
+
try {
|
|
59
|
+
require(pkg);
|
|
60
|
+
} catch {
|
|
61
|
+
installPackage(pkg, dev, pkgManager, projectPath);
|
|
62
|
+
}
|
|
63
|
+
}
|