@zenstackhq/cli 3.0.0-alpha.1 → 3.0.0-alpha.10
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/.turbo/turbo-build.log +22 -23
- package/bin/cli +1 -1
- package/dist/index.cjs +174 -158
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +174 -166
- package/dist/index.js.map +1 -1
- package/eslint.config.js +4 -0
- package/package.json +13 -15
- package/src/actions/action-utils.ts +46 -8
- package/src/actions/db.ts +30 -29
- package/src/actions/generate.ts +32 -18
- package/src/actions/info.ts +9 -18
- package/src/actions/init.ts +7 -28
- package/src/actions/migrate.ts +59 -64
- package/src/actions/templates.ts +6 -1
- package/src/index.ts +18 -39
- package/src/utils/exec-utils.ts +2 -5
- package/src/utils/version-utils.ts +9 -9
- package/test/db.test.ts +18 -0
- package/test/generate.test.ts +59 -0
- package/test/init.test.ts +13 -0
- package/test/migrate.test.ts +41 -0
- package/test/ts-schema-gen.test.ts +0 -1
- package/test/utils.ts +23 -0
- package/tsconfig.json +1 -1
- package/.turbo/turbo-lint.log +0 -18
package/src/actions/migrate.ts
CHANGED
|
@@ -1,109 +1,104 @@
|
|
|
1
|
-
import
|
|
1
|
+
import fs from 'node:fs';
|
|
2
2
|
import { execPackage } from '../utils/exec-utils';
|
|
3
|
-
import { getSchemaFile } from './action-utils';
|
|
4
|
-
import { run as runGenerate } from './generate';
|
|
3
|
+
import { generateTempPrismaSchema, getSchemaFile } from './action-utils';
|
|
5
4
|
|
|
6
5
|
type CommonOptions = {
|
|
7
6
|
schema?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
type DevOptions = CommonOptions & {
|
|
8
10
|
name?: string;
|
|
11
|
+
createOnly?: boolean;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
type ResetOptions = CommonOptions & {
|
|
15
|
+
force?: boolean;
|
|
9
16
|
};
|
|
10
17
|
|
|
18
|
+
type DeployOptions = CommonOptions;
|
|
19
|
+
|
|
20
|
+
type StatusOptions = CommonOptions;
|
|
21
|
+
|
|
11
22
|
/**
|
|
12
23
|
* CLI action for migration-related commands
|
|
13
24
|
*/
|
|
14
25
|
export async function run(command: string, options: CommonOptions) {
|
|
15
26
|
const schemaFile = getSchemaFile(options.schema);
|
|
27
|
+
const prismaSchemaFile = await generateTempPrismaSchema(schemaFile);
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
switch (command) {
|
|
31
|
+
case 'dev':
|
|
32
|
+
await runDev(prismaSchemaFile, options as DevOptions);
|
|
33
|
+
break;
|
|
16
34
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
case 'reset':
|
|
34
|
-
await runReset(prismaSchemaFile, options as any);
|
|
35
|
-
break;
|
|
36
|
-
|
|
37
|
-
case 'deploy':
|
|
38
|
-
await runDeploy(prismaSchemaFile, options);
|
|
39
|
-
break;
|
|
40
|
-
|
|
41
|
-
case 'status':
|
|
42
|
-
await runStatus(prismaSchemaFile, options);
|
|
43
|
-
break;
|
|
35
|
+
case 'reset':
|
|
36
|
+
await runReset(prismaSchemaFile, options as ResetOptions);
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
case 'deploy':
|
|
40
|
+
await runDeploy(prismaSchemaFile, options as DeployOptions);
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
case 'status':
|
|
44
|
+
await runStatus(prismaSchemaFile, options as StatusOptions);
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
} finally {
|
|
48
|
+
if (fs.existsSync(prismaSchemaFile)) {
|
|
49
|
+
fs.unlinkSync(prismaSchemaFile);
|
|
50
|
+
}
|
|
44
51
|
}
|
|
45
52
|
}
|
|
46
53
|
|
|
47
|
-
async function runDev(prismaSchemaFile: string,
|
|
54
|
+
async function runDev(prismaSchemaFile: string, options: DevOptions) {
|
|
48
55
|
try {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
|
|
56
|
+
const cmd = [
|
|
57
|
+
'prisma migrate dev',
|
|
58
|
+
` --schema "${prismaSchemaFile}"`,
|
|
59
|
+
' --skip-generate',
|
|
60
|
+
options.name ? ` --name ${options.name}` : '',
|
|
61
|
+
options.createOnly ? ' --create-only' : '',
|
|
62
|
+
].join('');
|
|
63
|
+
|
|
64
|
+
await execPackage(cmd);
|
|
55
65
|
} catch (err) {
|
|
56
66
|
handleSubProcessError(err);
|
|
57
67
|
}
|
|
58
68
|
}
|
|
59
69
|
|
|
60
|
-
async function runReset(prismaSchemaFile: string, options:
|
|
70
|
+
async function runReset(prismaSchemaFile: string, options: ResetOptions) {
|
|
61
71
|
try {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
options.force ? ' --force' : ''
|
|
65
|
-
}`,
|
|
66
|
-
{
|
|
67
|
-
stdio: 'inherit',
|
|
68
|
-
}
|
|
72
|
+
const cmd = ['prisma migrate reset', ` --schema "${prismaSchemaFile}"`, options.force ? ' --force' : ''].join(
|
|
73
|
+
'',
|
|
69
74
|
);
|
|
75
|
+
|
|
76
|
+
await execPackage(cmd);
|
|
70
77
|
} catch (err) {
|
|
71
78
|
handleSubProcessError(err);
|
|
72
79
|
}
|
|
73
80
|
}
|
|
74
81
|
|
|
75
|
-
async function runDeploy(prismaSchemaFile: string, _options:
|
|
82
|
+
async function runDeploy(prismaSchemaFile: string, _options: DeployOptions) {
|
|
76
83
|
try {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
stdio: 'inherit',
|
|
81
|
-
}
|
|
82
|
-
);
|
|
84
|
+
const cmd = ['prisma migrate deploy', ` --schema "${prismaSchemaFile}"`].join('');
|
|
85
|
+
|
|
86
|
+
await execPackage(cmd);
|
|
83
87
|
} catch (err) {
|
|
84
88
|
handleSubProcessError(err);
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
91
|
|
|
88
|
-
async function runStatus(prismaSchemaFile: string, _options:
|
|
92
|
+
async function runStatus(prismaSchemaFile: string, _options: StatusOptions) {
|
|
89
93
|
try {
|
|
90
|
-
await execPackage(
|
|
91
|
-
`prisma migrate status --schema "${prismaSchemaFile}"`,
|
|
92
|
-
{
|
|
93
|
-
stdio: 'inherit',
|
|
94
|
-
}
|
|
95
|
-
);
|
|
94
|
+
await execPackage(`prisma migrate status --schema "${prismaSchemaFile}"`);
|
|
96
95
|
} catch (err) {
|
|
97
96
|
handleSubProcessError(err);
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
99
|
|
|
101
100
|
function handleSubProcessError(err: unknown) {
|
|
102
|
-
if (
|
|
103
|
-
err instanceof Error &&
|
|
104
|
-
'status' in err &&
|
|
105
|
-
typeof err.status === 'number'
|
|
106
|
-
) {
|
|
101
|
+
if (err instanceof Error && 'status' in err && typeof err.status === 'number') {
|
|
107
102
|
process.exit(err.status);
|
|
108
103
|
} else {
|
|
109
104
|
process.exit(1);
|
package/src/actions/templates.ts
CHANGED
|
@@ -28,9 +28,14 @@ model Post {
|
|
|
28
28
|
|
|
29
29
|
export const STARTER_MAIN_TS = `import { ZenStackClient } from '@zenstackhq/runtime';
|
|
30
30
|
import { schema } from './zenstack/schema';
|
|
31
|
+
import SQLite from 'better-sqlite3';
|
|
31
32
|
|
|
32
33
|
async function main() {
|
|
33
|
-
const client = new ZenStackClient(schema
|
|
34
|
+
const client = new ZenStackClient(schema, {
|
|
35
|
+
dialectConfig: {
|
|
36
|
+
database: new SQLite('./zenstack/dev.db'),
|
|
37
|
+
},
|
|
38
|
+
});
|
|
34
39
|
const user = await client.user.create({
|
|
35
40
|
data: {
|
|
36
41
|
email: 'test@zenstack.dev',
|
package/src/index.ts
CHANGED
|
@@ -4,9 +4,7 @@ import { Command, Option } from 'commander';
|
|
|
4
4
|
import * as actions from './actions';
|
|
5
5
|
import { getVersion } from './utils/version-utils';
|
|
6
6
|
|
|
7
|
-
const generateAction = async (
|
|
8
|
-
options: Parameters<typeof actions.generate>[0]
|
|
9
|
-
): Promise<void> => {
|
|
7
|
+
const generateAction = async (options: Parameters<typeof actions.generate>[0]): Promise<void> => {
|
|
10
8
|
await actions.generate(options);
|
|
11
9
|
};
|
|
12
10
|
|
|
@@ -36,60 +34,52 @@ export function createProgram() {
|
|
|
36
34
|
program
|
|
37
35
|
.description(
|
|
38
36
|
`${colors.bold.blue(
|
|
39
|
-
'ζ'
|
|
40
|
-
)} ZenStack is a Prisma power pack for building full-stack apps.\n\nDocumentation: https://zenstack.dev
|
|
37
|
+
'ζ',
|
|
38
|
+
)} ZenStack is a Prisma power pack for building full-stack apps.\n\nDocumentation: https://zenstack.dev.`,
|
|
41
39
|
)
|
|
42
40
|
.showHelpAfterError()
|
|
43
41
|
.showSuggestionAfterError();
|
|
44
42
|
|
|
45
43
|
const schemaOption = new Option(
|
|
46
44
|
'--schema <file>',
|
|
47
|
-
`schema file (with extension ${schemaExtensions}). Defaults to "schema.zmodel" unless specified in package.json
|
|
45
|
+
`schema file (with extension ${schemaExtensions}). Defaults to "schema.zmodel" unless specified in package.json.`,
|
|
48
46
|
);
|
|
49
47
|
|
|
50
48
|
program
|
|
51
49
|
.command('generate')
|
|
52
50
|
.description('Run code generation.')
|
|
53
51
|
.addOption(schemaOption)
|
|
52
|
+
.addOption(new Option('--silent', 'do not print any output'))
|
|
54
53
|
.addOption(
|
|
55
54
|
new Option(
|
|
56
|
-
'-
|
|
57
|
-
'default output directory
|
|
58
|
-
)
|
|
55
|
+
'--save-prisma-schema [path]',
|
|
56
|
+
'save a Prisma schema file, by default into the output directory',
|
|
57
|
+
),
|
|
59
58
|
)
|
|
59
|
+
.addOption(new Option('-o, --output <path>', 'default output directory for core plugins'))
|
|
60
60
|
.action(generateAction);
|
|
61
61
|
|
|
62
|
-
const migrateCommand = program
|
|
63
|
-
.command('migrate')
|
|
64
|
-
.description('Update the database schema with migrations.');
|
|
62
|
+
const migrateCommand = program.command('migrate').description('Update the database schema with migrations.');
|
|
65
63
|
|
|
66
64
|
migrateCommand
|
|
67
65
|
.command('dev')
|
|
68
66
|
.addOption(schemaOption)
|
|
69
67
|
.addOption(new Option('-n, --name <name>', 'migration name'))
|
|
70
|
-
.addOption(
|
|
71
|
-
|
|
72
|
-
)
|
|
73
|
-
.description(
|
|
74
|
-
'Create a migration from changes in schema and apply it to the database.'
|
|
75
|
-
)
|
|
68
|
+
.addOption(new Option('--create-only', 'only create migration, do not apply'))
|
|
69
|
+
.description('Create a migration from changes in schema and apply it to the database.')
|
|
76
70
|
.action((options) => migrateAction('dev', options));
|
|
77
71
|
|
|
78
72
|
migrateCommand
|
|
79
73
|
.command('reset')
|
|
80
74
|
.addOption(schemaOption)
|
|
81
75
|
.addOption(new Option('--force', 'skip the confirmation prompt'))
|
|
82
|
-
.description(
|
|
83
|
-
'Reset your database and apply all migrations, all data will be lost.'
|
|
84
|
-
)
|
|
76
|
+
.description('Reset your database and apply all migrations, all data will be lost.')
|
|
85
77
|
.action((options) => migrateAction('reset', options));
|
|
86
78
|
|
|
87
79
|
migrateCommand
|
|
88
80
|
.command('deploy')
|
|
89
81
|
.addOption(schemaOption)
|
|
90
|
-
.description(
|
|
91
|
-
'Deploy your pending migrations to your production/staging database.'
|
|
92
|
-
)
|
|
82
|
+
.description('Deploy your pending migrations to your production/staging database.')
|
|
93
83
|
.action((options) => migrateAction('deploy', options));
|
|
94
84
|
|
|
95
85
|
migrateCommand
|
|
@@ -98,30 +88,19 @@ export function createProgram() {
|
|
|
98
88
|
.description('check the status of your database migrations.')
|
|
99
89
|
.action((options) => migrateAction('status', options));
|
|
100
90
|
|
|
101
|
-
const dbCommand = program
|
|
102
|
-
.command('db')
|
|
103
|
-
.description('Manage your database schema during development.');
|
|
91
|
+
const dbCommand = program.command('db').description('Manage your database schema during development.');
|
|
104
92
|
|
|
105
93
|
dbCommand
|
|
106
94
|
.command('push')
|
|
107
95
|
.description('Push the state from your schema to your database')
|
|
108
96
|
.addOption(schemaOption)
|
|
109
|
-
.addOption(
|
|
110
|
-
|
|
111
|
-
)
|
|
112
|
-
.addOption(
|
|
113
|
-
new Option(
|
|
114
|
-
'--force-reset',
|
|
115
|
-
'force a reset of the database before push'
|
|
116
|
-
)
|
|
117
|
-
)
|
|
97
|
+
.addOption(new Option('--accept-data-loss', 'ignore data loss warnings'))
|
|
98
|
+
.addOption(new Option('--force-reset', 'force a reset of the database before push'))
|
|
118
99
|
.action((options) => dbAction('push', options));
|
|
119
100
|
|
|
120
101
|
program
|
|
121
102
|
.command('info')
|
|
122
|
-
.description(
|
|
123
|
-
'Get information of installed ZenStack and related packages.'
|
|
124
|
-
)
|
|
103
|
+
.description('Get information of installed ZenStack and related packages.')
|
|
125
104
|
.argument('[path]', 'project path', '.')
|
|
126
105
|
.action(infoAction);
|
|
127
106
|
|
package/src/utils/exec-utils.ts
CHANGED
|
@@ -3,10 +3,7 @@ import { execSync as _exec, type ExecSyncOptions } from 'child_process';
|
|
|
3
3
|
/**
|
|
4
4
|
* Utility for executing command synchronously and prints outputs on current console
|
|
5
5
|
*/
|
|
6
|
-
export function execSync(
|
|
7
|
-
cmd: string,
|
|
8
|
-
options?: Omit<ExecSyncOptions, 'env'> & { env?: Record<string, string> }
|
|
9
|
-
): void {
|
|
6
|
+
export function execSync(cmd: string, options?: Omit<ExecSyncOptions, 'env'> & { env?: Record<string, string> }): void {
|
|
10
7
|
const { env, ...restOptions } = options ?? {};
|
|
11
8
|
const mergedEnv = env ? { ...process.env, ...env } : undefined;
|
|
12
9
|
_exec(cmd, {
|
|
@@ -22,7 +19,7 @@ export function execSync(
|
|
|
22
19
|
*/
|
|
23
20
|
export function execPackage(
|
|
24
21
|
cmd: string,
|
|
25
|
-
options?: Omit<ExecSyncOptions, 'env'> & { env?: Record<string, string> }
|
|
22
|
+
options?: Omit<ExecSyncOptions, 'env'> & { env?: Record<string, string> },
|
|
26
23
|
): void {
|
|
27
24
|
const packageManager = process?.versions?.['bun'] ? 'bunx' : 'npx';
|
|
28
25
|
execSync(`${packageManager} ${cmd}`, options);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
export function getVersion() {
|
|
3
6
|
try {
|
|
4
|
-
|
|
7
|
+
// isomorphic __dirname
|
|
8
|
+
const _dirname = typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
return JSON.parse(fs.readFileSync(path.join(_dirname, '../package.json'), 'utf8')).version;
|
|
5
10
|
} catch {
|
|
6
|
-
|
|
7
|
-
// dev environment
|
|
8
|
-
return require('../../package.json').version;
|
|
9
|
-
} catch {
|
|
10
|
-
return undefined;
|
|
11
|
-
}
|
|
11
|
+
return undefined;
|
|
12
12
|
}
|
|
13
13
|
}
|
package/test/db.test.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { createProject, runCli } from './utils';
|
|
5
|
+
|
|
6
|
+
const model = `
|
|
7
|
+
model User {
|
|
8
|
+
id String @id @default(cuid())
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
describe('CLI db commands test', () => {
|
|
13
|
+
it('should generate a database with db push', () => {
|
|
14
|
+
const workDir = createProject(model);
|
|
15
|
+
runCli('db push', workDir);
|
|
16
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/dev.db'))).toBe(true);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { createProject, runCli } from './utils';
|
|
5
|
+
|
|
6
|
+
const model = `
|
|
7
|
+
model User {
|
|
8
|
+
id String @id @default(cuid())
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
describe('CLI generate command test', () => {
|
|
13
|
+
it('should generate a TypeScript schema', () => {
|
|
14
|
+
const workDir = createProject(model);
|
|
15
|
+
runCli('generate', workDir);
|
|
16
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.ts'))).toBe(true);
|
|
17
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.prisma'))).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should respect custom output directory', () => {
|
|
21
|
+
const workDir = createProject(model);
|
|
22
|
+
runCli('generate --output ./zen', workDir);
|
|
23
|
+
expect(fs.existsSync(path.join(workDir, 'zen/schema.ts'))).toBe(true);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should respect custom schema location', () => {
|
|
27
|
+
const workDir = createProject(model);
|
|
28
|
+
fs.renameSync(path.join(workDir, 'zenstack/schema.zmodel'), path.join(workDir, 'zenstack/foo.zmodel'));
|
|
29
|
+
runCli('generate --schema ./zenstack/foo.zmodel', workDir);
|
|
30
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.ts'))).toBe(true);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should respect save prisma schema option', () => {
|
|
34
|
+
const workDir = createProject(model);
|
|
35
|
+
runCli('generate --save-prisma-schema', workDir);
|
|
36
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.prisma'))).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should respect save prisma schema custom path option', () => {
|
|
40
|
+
const workDir = createProject(model);
|
|
41
|
+
runCli('generate --save-prisma-schema "../prisma/schema.prisma"', workDir);
|
|
42
|
+
expect(fs.existsSync(path.join(workDir, 'prisma/schema.prisma'))).toBe(true);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should respect package.json config', () => {
|
|
46
|
+
const workDir = createProject(model);
|
|
47
|
+
fs.mkdirSync(path.join(workDir, 'foo'));
|
|
48
|
+
fs.renameSync(path.join(workDir, 'zenstack/schema.zmodel'), path.join(workDir, 'foo/schema.zmodel'));
|
|
49
|
+
fs.rmdirSync(path.join(workDir, 'zenstack'));
|
|
50
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(workDir, 'package.json'), 'utf8'));
|
|
51
|
+
pkgJson.zenstack = {
|
|
52
|
+
schema: './foo/schema.zmodel',
|
|
53
|
+
output: './bar',
|
|
54
|
+
};
|
|
55
|
+
fs.writeFileSync(path.join(workDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
|
|
56
|
+
runCli('generate', workDir);
|
|
57
|
+
expect(fs.existsSync(path.join(workDir, 'bar/schema.ts'))).toBe(true);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import tmp from 'tmp';
|
|
4
|
+
import { describe, expect, it } from 'vitest';
|
|
5
|
+
import { runCli } from './utils';
|
|
6
|
+
|
|
7
|
+
describe('Cli init command tests', () => {
|
|
8
|
+
it('should create a new project', () => {
|
|
9
|
+
const { name: workDir } = tmp.dirSync({ unsafeCleanup: true });
|
|
10
|
+
runCli('init', workDir);
|
|
11
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.zmodel'))).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { describe, expect, it } from 'vitest';
|
|
4
|
+
import { createProject, runCli } from './utils';
|
|
5
|
+
|
|
6
|
+
const model = `
|
|
7
|
+
model User {
|
|
8
|
+
id String @id @default(cuid())
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
describe('CLI migrate commands test', () => {
|
|
13
|
+
it('should generate a database with migrate dev', () => {
|
|
14
|
+
const workDir = createProject(model);
|
|
15
|
+
runCli('migrate dev --name init', workDir);
|
|
16
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/dev.db'))).toBe(true);
|
|
17
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/migrations'))).toBe(true);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should reset the database with migrate reset', () => {
|
|
21
|
+
const workDir = createProject(model);
|
|
22
|
+
runCli('db push', workDir);
|
|
23
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/dev.db'))).toBe(true);
|
|
24
|
+
runCli('migrate reset --force', workDir);
|
|
25
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/dev.db'))).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should reset the database with migrate deploy', () => {
|
|
29
|
+
const workDir = createProject(model);
|
|
30
|
+
runCli('migrate dev --name init', workDir);
|
|
31
|
+
fs.rmSync(path.join(workDir, 'zenstack/dev.db'));
|
|
32
|
+
runCli('migrate deploy', workDir);
|
|
33
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/dev.db'))).toBe(true);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('supports migrate status', () => {
|
|
37
|
+
const workDir = createProject(model);
|
|
38
|
+
runCli('migrate dev --name init', workDir);
|
|
39
|
+
runCli('migrate status', workDir);
|
|
40
|
+
});
|
|
41
|
+
});
|
package/test/utils.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createTestProject } from '@zenstackhq/testtools';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
const ZMODEL_PRELUDE = `datasource db {
|
|
7
|
+
provider = "sqlite"
|
|
8
|
+
url = "file:./dev.db"
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
export function createProject(zmodel: string, addPrelude = true) {
|
|
13
|
+
const workDir = createTestProject();
|
|
14
|
+
fs.mkdirSync(path.join(workDir, 'zenstack'), { recursive: true });
|
|
15
|
+
const schemaPath = path.join(workDir, 'zenstack/schema.zmodel');
|
|
16
|
+
fs.writeFileSync(schemaPath, addPrelude ? `${ZMODEL_PRELUDE}\n\n${zmodel}` : zmodel);
|
|
17
|
+
return workDir;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function runCli(command: string, cwd: string) {
|
|
21
|
+
const cli = path.join(__dirname, '../dist/index.js');
|
|
22
|
+
execSync(`node ${cli} ${command}`, { cwd });
|
|
23
|
+
}
|
package/tsconfig.json
CHANGED
package/.turbo/turbo-lint.log
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
> zenstack@3.0.0-alpha.1 lint /Users/yiming/git/zenstack/zenstack-v3/packages/cli
|
|
4
|
-
> eslint src --ext ts
|
|
5
|
-
|
|
6
|
-
=============
|
|
7
|
-
|
|
8
|
-
WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.
|
|
9
|
-
|
|
10
|
-
You may find that it works just fine, or you may not.
|
|
11
|
-
|
|
12
|
-
SUPPORTED TYPESCRIPT VERSIONS: >=4.7.4 <5.5.0
|
|
13
|
-
|
|
14
|
-
YOUR TYPESCRIPT VERSION: 5.7.3
|
|
15
|
-
|
|
16
|
-
Please only submit bug reports when using the officially supported version.
|
|
17
|
-
|
|
18
|
-
=============
|