@zenstackhq/cli 3.0.0-beta.2 → 3.0.0-beta.21
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 +8 -8
- package/dist/index.cjs +33 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +33 -19
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/scripts/post-build.ts +20 -0
- package/src/actions/generate.ts +18 -9
- package/src/actions/init.ts +1 -1
- package/src/actions/migrate.ts +6 -3
- package/src/actions/templates.ts +1 -1
- package/src/constants.ts +3 -0
- package/src/index.ts +2 -0
- package/src/plugins/prisma.ts +2 -2
- package/src/plugins/typescript.ts +9 -1
- package/test/generate.test.ts +14 -0
- package/test/plugins/prisma-plugin.test.ts +21 -0
- package/test/ts-schema-gen.test.ts +83 -1
- package/tsup.config.ts +0 -17
package/src/actions/init.ts
CHANGED
|
@@ -13,7 +13,7 @@ import { STARTER_ZMODEL } from './templates';
|
|
|
13
13
|
export async function run(projectPath: string) {
|
|
14
14
|
const packages = [
|
|
15
15
|
{ name: '@zenstackhq/cli@next', dev: true },
|
|
16
|
-
{ name: '@zenstackhq/
|
|
16
|
+
{ name: '@zenstackhq/orm@next', dev: false },
|
|
17
17
|
];
|
|
18
18
|
let pm = await detect();
|
|
19
19
|
if (!pm) {
|
package/src/actions/migrate.ts
CHANGED
|
@@ -82,9 +82,12 @@ async function runDev(prismaSchemaFile: string, options: DevOptions) {
|
|
|
82
82
|
|
|
83
83
|
async function runReset(prismaSchemaFile: string, options: ResetOptions) {
|
|
84
84
|
try {
|
|
85
|
-
const cmd = [
|
|
86
|
-
'',
|
|
87
|
-
|
|
85
|
+
const cmd = [
|
|
86
|
+
'prisma migrate reset',
|
|
87
|
+
` --schema "${prismaSchemaFile}"`,
|
|
88
|
+
' --skip-generate',
|
|
89
|
+
options.force ? ' --force' : '',
|
|
90
|
+
].join('');
|
|
88
91
|
|
|
89
92
|
await execPackage(cmd);
|
|
90
93
|
} catch (err) {
|
package/src/actions/templates.ts
CHANGED
|
@@ -26,7 +26,7 @@ model Post {
|
|
|
26
26
|
}
|
|
27
27
|
`;
|
|
28
28
|
|
|
29
|
-
export const STARTER_MAIN_TS = `import { ZenStackClient } from '@zenstackhq/
|
|
29
|
+
export const STARTER_MAIN_TS = `import { ZenStackClient } from '@zenstackhq/orm';
|
|
30
30
|
import SQLite from 'better-sqlite3';
|
|
31
31
|
import { SqliteDialect } from 'kysely';
|
|
32
32
|
import { schema } from './zenstack/schema';
|
package/src/constants.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -59,6 +59,8 @@ function createProgram() {
|
|
|
59
59
|
.addOption(schemaOption)
|
|
60
60
|
.addOption(noVersionCheckOption)
|
|
61
61
|
.addOption(new Option('-o, --output <path>', 'default output directory for code generation'))
|
|
62
|
+
.addOption(new Option('--lite', 'also generate a lite version of schema without attributes').default(false))
|
|
63
|
+
.addOption(new Option('--lite-only', 'only generate lite version of schema without attributes').default(false))
|
|
62
64
|
.addOption(new Option('--silent', 'suppress all output except errors').default(false))
|
|
63
65
|
.action(generateAction);
|
|
64
66
|
|
package/src/plugins/prisma.ts
CHANGED
|
@@ -5,10 +5,10 @@ import path from 'node:path';
|
|
|
5
5
|
const plugin: CliPlugin = {
|
|
6
6
|
name: 'Prisma Schema Generator',
|
|
7
7
|
statusText: 'Generating Prisma schema',
|
|
8
|
-
async generate({ model,
|
|
8
|
+
async generate({ model, defaultOutputPath, pluginOptions }) {
|
|
9
9
|
let outFile = path.join(defaultOutputPath, 'schema.prisma');
|
|
10
10
|
if (typeof pluginOptions['output'] === 'string') {
|
|
11
|
-
outFile = path.resolve(
|
|
11
|
+
outFile = path.resolve(defaultOutputPath, pluginOptions['output']);
|
|
12
12
|
if (!fs.existsSync(path.dirname(outFile))) {
|
|
13
13
|
fs.mkdirSync(path.dirname(outFile), { recursive: true });
|
|
14
14
|
}
|
|
@@ -7,6 +7,7 @@ const plugin: CliPlugin = {
|
|
|
7
7
|
name: 'TypeScript Schema Generator',
|
|
8
8
|
statusText: 'Generating TypeScript schema',
|
|
9
9
|
async generate({ model, defaultOutputPath, pluginOptions }) {
|
|
10
|
+
// output path
|
|
10
11
|
let outDir = defaultOutputPath;
|
|
11
12
|
if (typeof pluginOptions['output'] === 'string') {
|
|
12
13
|
outDir = path.resolve(defaultOutputPath, pluginOptions['output']);
|
|
@@ -14,7 +15,14 @@ const plugin: CliPlugin = {
|
|
|
14
15
|
fs.mkdirSync(outDir, { recursive: true });
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
+
|
|
19
|
+
// lite mode
|
|
20
|
+
const lite = pluginOptions['lite'] === true;
|
|
21
|
+
|
|
22
|
+
// liteOnly mode
|
|
23
|
+
const liteOnly = pluginOptions['liteOnly'] === true;
|
|
24
|
+
|
|
25
|
+
await new TsSchemaGenerator().generate(model, { outDir, lite, liteOnly });
|
|
18
26
|
},
|
|
19
27
|
};
|
|
20
28
|
|
package/test/generate.test.ts
CHANGED
|
@@ -44,4 +44,18 @@ describe('CLI generate command test', () => {
|
|
|
44
44
|
runCli('generate', workDir);
|
|
45
45
|
expect(fs.existsSync(path.join(workDir, 'bar/schema.ts'))).toBe(true);
|
|
46
46
|
});
|
|
47
|
+
|
|
48
|
+
it('should respect lite option', () => {
|
|
49
|
+
const workDir = createProject(model);
|
|
50
|
+
runCli('generate --lite', workDir);
|
|
51
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.ts'))).toBe(true);
|
|
52
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema-lite.ts'))).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('should respect liteOnly option', () => {
|
|
56
|
+
const workDir = createProject(model);
|
|
57
|
+
runCli('generate --lite-only', workDir);
|
|
58
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema.ts'))).toBe(false);
|
|
59
|
+
expect(fs.existsSync(path.join(workDir, 'zenstack/schema-lite.ts'))).toBe(true);
|
|
60
|
+
});
|
|
47
61
|
});
|
|
@@ -57,4 +57,25 @@ model User {
|
|
|
57
57
|
runCli('generate', workDir);
|
|
58
58
|
expect(fs.existsSync(path.join(workDir, 'prisma/schema.prisma'))).toBe(true);
|
|
59
59
|
});
|
|
60
|
+
|
|
61
|
+
it('can generate a Prisma schema with custom output relative to zenstack.output', () => {
|
|
62
|
+
const workDir = createProject(`
|
|
63
|
+
plugin prisma {
|
|
64
|
+
provider = '@core/prisma'
|
|
65
|
+
output = './schema.prisma'
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
model User {
|
|
69
|
+
id String @id @default(cuid())
|
|
70
|
+
}
|
|
71
|
+
`);
|
|
72
|
+
|
|
73
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(workDir, 'package.json'), 'utf8'));
|
|
74
|
+
pkgJson.zenstack = {
|
|
75
|
+
output: './relative',
|
|
76
|
+
};
|
|
77
|
+
fs.writeFileSync(path.join(workDir, 'package.json'), JSON.stringify(pkgJson, null, 2));
|
|
78
|
+
runCli('generate', workDir);
|
|
79
|
+
expect(fs.existsSync(path.join(workDir, 'relative/schema.prisma'))).toBe(true);
|
|
80
|
+
});
|
|
60
81
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ExpressionUtils } from '@zenstackhq/
|
|
1
|
+
import { ExpressionUtils } from '@zenstackhq/orm/schema';
|
|
2
2
|
import { createTestProject, generateTsSchema, generateTsSchemaInPlace } from '@zenstackhq/testtools';
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import path from 'node:path';
|
|
@@ -360,4 +360,86 @@ model User extends Base {
|
|
|
360
360
|
expect(schema.enums).toMatchObject({ Role: expect.any(Object) });
|
|
361
361
|
expect(schema.models).toMatchObject({ User: expect.any(Object) });
|
|
362
362
|
});
|
|
363
|
+
|
|
364
|
+
it('generates correct default literal function arguments', async () => {
|
|
365
|
+
const { schema } = await generateTsSchema(`
|
|
366
|
+
model User {
|
|
367
|
+
id String @id @default(uuid(7))
|
|
368
|
+
}
|
|
369
|
+
`);
|
|
370
|
+
|
|
371
|
+
expect(schema.models).toMatchObject({
|
|
372
|
+
User: {
|
|
373
|
+
name: 'User',
|
|
374
|
+
fields: {
|
|
375
|
+
id: {
|
|
376
|
+
name: 'id',
|
|
377
|
+
type: 'String',
|
|
378
|
+
id: true,
|
|
379
|
+
attributes: [
|
|
380
|
+
{
|
|
381
|
+
name: '@id',
|
|
382
|
+
},
|
|
383
|
+
{
|
|
384
|
+
name: '@default',
|
|
385
|
+
args: [
|
|
386
|
+
{
|
|
387
|
+
name: 'value',
|
|
388
|
+
value: {
|
|
389
|
+
kind: 'call',
|
|
390
|
+
function: 'uuid',
|
|
391
|
+
args: [
|
|
392
|
+
{
|
|
393
|
+
kind: 'literal',
|
|
394
|
+
value: 7,
|
|
395
|
+
},
|
|
396
|
+
],
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
],
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
default: {
|
|
403
|
+
kind: 'call',
|
|
404
|
+
function: 'uuid',
|
|
405
|
+
args: [
|
|
406
|
+
{
|
|
407
|
+
kind: 'literal',
|
|
408
|
+
value: 7,
|
|
409
|
+
},
|
|
410
|
+
],
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
idFields: ['id'],
|
|
415
|
+
uniqueFields: {
|
|
416
|
+
id: {
|
|
417
|
+
type: 'String',
|
|
418
|
+
},
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
it('supports lite schema generation', async () => {
|
|
425
|
+
const { schemaLite } = await generateTsSchema(
|
|
426
|
+
`
|
|
427
|
+
model User {
|
|
428
|
+
id String @id @default(uuid())
|
|
429
|
+
name String
|
|
430
|
+
email String @unique
|
|
431
|
+
|
|
432
|
+
@@map('users')
|
|
433
|
+
}
|
|
434
|
+
`,
|
|
435
|
+
undefined,
|
|
436
|
+
undefined,
|
|
437
|
+
undefined,
|
|
438
|
+
true,
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
expect(schemaLite!.models.User.attributes).toBeUndefined();
|
|
442
|
+
expect(schemaLite!.models.User.fields.id.attributes).toBeUndefined();
|
|
443
|
+
expect(schemaLite!.models.User.fields.email.attributes).toBeUndefined();
|
|
444
|
+
});
|
|
363
445
|
});
|
package/tsup.config.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
1
|
import { defineConfig } from 'tsup';
|
|
4
2
|
|
|
5
3
|
export default defineConfig({
|
|
@@ -12,19 +10,4 @@ export default defineConfig({
|
|
|
12
10
|
clean: true,
|
|
13
11
|
dts: true,
|
|
14
12
|
format: ['esm', 'cjs'],
|
|
15
|
-
onSuccess: async () => {
|
|
16
|
-
if (!process.env['TELEMETRY_TRACKING_TOKEN']) {
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
const filesToProcess = ['dist/index.js', 'dist/index.cjs'];
|
|
20
|
-
for (const file of filesToProcess) {
|
|
21
|
-
console.log(`Processing ${file} for telemetry token...`);
|
|
22
|
-
const content = fs.readFileSync(path.join(__dirname, file), 'utf-8');
|
|
23
|
-
const updatedContent = content.replace(
|
|
24
|
-
'<TELEMETRY_TRACKING_TOKEN>',
|
|
25
|
-
process.env['TELEMETRY_TRACKING_TOKEN'],
|
|
26
|
-
);
|
|
27
|
-
fs.writeFileSync(file, updatedContent, 'utf-8');
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
13
|
});
|