Skip to content

Commit 56e4744

Browse files
authored
chore: merge from dev (#1017)
1 parent 7b453f7 commit 56e4744

32 files changed

+732
-307
lines changed

.github/workflows/build-test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,4 @@ jobs:
9090
run: pnpm install --frozen-lockfile
9191

9292
- name: Test
93-
run: pnpm run test-ci
93+
run: pnpm run test-scaffold && pnpm run test-ci

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ dist
77
.npmcache
88
coverage
99
.build
10+
.test

CONTRIBUTING.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ I want to think you first for considering contributing to ZenStack 🙏🏻. It'
3535
pnpm build
3636
```
3737

38+
1. Scaffold the project used for testing
39+
40+
```bash
41+
pnpm test-scaffold
42+
```
43+
44+
You only need to run this command once.
45+
3846
1. Run tests
3947

4048
```bash

jest.config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@
33
* https://jestjs.io/docs/configuration
44
*/
55

6+
import path from 'path';
7+
68
export default {
79
// Automatically clear mock calls, instances, contexts and results before every test
810
clearMocks: true,
911

12+
globalSetup: path.join(__dirname, './test-setup.ts'),
13+
1014
// Indicates whether the coverage information should be collected while executing the test
1115
collectCoverage: true,
1216

1317
// The directory where Jest should output its coverage files
14-
coverageDirectory: 'tests/coverage',
18+
coverageDirectory: path.join(__dirname, '.test/coverage'),
1519

1620
// An array of regexp pattern strings used to skip coverage collection
1721
coveragePathIgnorePatterns: ['/node_modules/', '/tests/'],

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
"scripts": {
66
"build": "pnpm -r build",
77
"lint": "pnpm -r lint",
8-
"test": "ZENSTACK_TEST=1 pnpm -r run test --silent --forceExit",
9-
"test-ci": "ZENSTACK_TEST=1 pnpm -r run test --silent --forceExit",
8+
"test": "ZENSTACK_TEST=1 pnpm -r --parallel run test --silent --forceExit",
9+
"test-ci": "ZENSTACK_TEST=1 pnpm -r --parallel run test --silent --forceExit",
10+
"test-scaffold": "tsx script/test-scaffold.ts",
1011
"publish-all": "pnpm --filter \"./packages/**\" -r publish --access public",
1112
"publish-preview": "pnpm --filter \"./packages/**\" -r publish --force --registry https://preview.registry.zenstack.dev/",
1213
"unpublish-preview": "pnpm --recursive --shell-mode exec -- npm unpublish -f --registry https://preview.registry.zenstack.dev/ \"\\$PNPM_PACKAGE_NAME\"",
@@ -33,6 +34,7 @@
3334
"ts-jest": "^29.1.1",
3435
"ts-node": "^10.9.1",
3536
"tsup": "^8.0.1",
37+
"tsx": "^4.7.1",
3638
"typescript": "^5.3.2"
3739
}
3840
}

packages/ide/jetbrains/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
# Changelog
22

33
## [Unreleased]
4+
### Added
5+
- Added support to complex usage of `@@index` attribute like `@@index([content(ops: raw("gin_trgm_ops"))], type: Gin)`.
6+
### Fixed
7+
- Fixed several ZModel validation issues related to model inheritance.
48

9+
## 1.7.0
510
### Added
611
- Auto-completion is now supported inside attributes.

packages/plugins/tanstack-query/src/runtime/vue.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export function useModelQuery<TQueryFnData, TData, TError>(
6161
model: string,
6262
url: string,
6363
args?: unknown,
64-
options?: UseQueryOptions<TQueryFnData, TError, TData>,
64+
options?: Omit<UseQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
6565
fetch?: FetchFn,
6666
optimisticUpdate = false
6767
) {
@@ -87,7 +87,7 @@ export function useInfiniteModelQuery<TQueryFnData, TData, TError>(
8787
model: string,
8888
url: string,
8989
args?: unknown,
90-
options?: UseInfiniteQueryOptions<TQueryFnData, TError, TData>,
90+
options?: Omit<UseInfiniteQueryOptions<TQueryFnData, TError, TData>, 'queryKey'>,
9191
fetch?: FetchFn
9292
) {
9393
return useInfiniteQuery<TQueryFnData, TError, TData>({

packages/schema/src/cli/actions/repl.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
/* eslint-disable @typescript-eslint/no-var-requires */
33
import colors from 'colors';
44
import path from 'path';
5-
import prettyRepl from 'pretty-repl';
65
import { inspect } from 'util';
76

87
// inspired by: https://github.com/Kinjalrk2k/prisma-console
@@ -11,6 +10,13 @@ import { inspect } from 'util';
1110
* CLI action for starting a REPL session
1211
*/
1312
export async function repl(projectPath: string, options: { prismaClient?: string; debug?: boolean; table?: boolean }) {
13+
if (!process?.stdout?.isTTY && process?.versions?.bun) {
14+
console.error('REPL on Bun is only available in a TTY terminal at this time. Please use npm/npx to run the command in this context instead of bun/bunx.');
15+
return;
16+
}
17+
18+
const prettyRepl = await import('pretty-repl')
19+
1420
console.log('Welcome to ZenStack REPL. See help with the ".help" command.');
1521
console.log('Global variables:');
1622
console.log(` ${colors.blue('db')} to access enhanced PrismaClient`);

packages/schema/src/language-server/validator/datamodel-validator.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
isDataModel,
66
isStringLiteral,
77
ReferenceExpr,
8+
isEnum,
89
} from '@zenstackhq/language/ast';
910
import { getLiteral, getModelIdFields, getModelUniqueFields, isDelegateModel } from '@zenstackhq/sdk';
1011
import { AstNode, DiagnosticInfo, getDocument, ValidationAcceptor } from 'langium';
@@ -61,8 +62,13 @@ export default class DataModelValidator implements AstValidator<DataModel> {
6162
if (idField.type.optional) {
6263
accept('error', 'Field with @id attribute must not be optional', { node: idField });
6364
}
64-
if (idField.type.array || !idField.type.type || !SCALAR_TYPES.includes(idField.type.type)) {
65-
accept('error', 'Field with @id attribute must be of scalar type', { node: idField });
65+
66+
const isArray = idField.type.array;
67+
const isScalar = SCALAR_TYPES.includes(idField.type.type as typeof SCALAR_TYPES[number])
68+
const isValidType = isScalar || isEnum(idField.type.reference?.ref)
69+
70+
if (isArray || !isValidType) {
71+
accept('error', 'Field with @id attribute must be of scalar or enum type', { node: idField });
6672
}
6773
});
6874
}

packages/schema/src/language-server/validator/schema-validator.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,9 @@ export default class SchemaValidator implements AstValidator<Model> {
5252
private validateImports(model: Model, accept: ValidationAcceptor) {
5353
model.imports.forEach((imp) => {
5454
const importedModel = resolveImport(this.documents, imp);
55+
const importPath = imp.path.endsWith('.zmodel') ? imp.path : `${imp.path}.zmodel`;
5556
if (!importedModel) {
56-
accept('error', `Cannot find model file ${imp.path}.zmodel`, { node: imp });
57+
accept('error', `Cannot find model file ${importPath}`, { node: imp });
5758
}
5859
});
5960
}

packages/schema/src/plugins/prisma/schema-generator.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import { upperCaseFirst } from 'upper-case-first';
5656
import { name } from '.';
5757
import { getStringLiteral } from '../../language-server/validator/utils';
5858
import telemetry from '../../telemetry';
59-
import { execSync } from '../../utils/exec-utils';
59+
import { execPackage } from '../../utils/exec-utils';
6060
import { findPackageJson } from '../../utils/pkg-utils';
6161
import {
6262
AttributeArgValue,
@@ -142,7 +142,7 @@ export class PrismaSchemaGenerator {
142142
if (options.format === true) {
143143
try {
144144
// run 'prisma format'
145-
await execSync(`npx prisma format --schema ${outFile}`, { stdio: 'ignore' });
145+
await execPackage(`prisma format --schema ${outFile}`, { stdio: 'ignore' });
146146
} catch {
147147
warnings.push(`Failed to format Prisma schema file`);
148148
}
@@ -151,18 +151,18 @@ export class PrismaSchemaGenerator {
151151
const generateClient = options.generateClient !== false;
152152

153153
if (generateClient) {
154-
let generateCmd = `npx prisma generate --schema "${outFile}"`;
154+
let generateCmd = `prisma generate --schema "${outFile}"`;
155155
if (typeof options.generateArgs === 'string') {
156156
generateCmd += ` ${options.generateArgs}`;
157157
}
158158
try {
159159
// run 'prisma generate'
160-
await execSync(generateCmd, { stdio: 'ignore' });
160+
await execPackage(generateCmd, { stdio: 'ignore' });
161161
} catch {
162162
await this.trackPrismaSchemaError(outFile);
163163
try {
164164
// run 'prisma generate' again with output to the console
165-
await execSync(generateCmd);
165+
await execPackage(generateCmd);
166166
} catch {
167167
// noop
168168
}

packages/schema/src/res/stdlib.zmodel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ attribute @updatedAt() @@@targetField([DateTimeField]) @@@prisma
390390
/**
391391
* Add full text index (MySQL only).
392392
*/
393-
attribute @@fulltext(_ fields: FieldReference[]) @@@prisma
393+
attribute @@fulltext(_ fields: FieldReference[], map: String?) @@@prisma
394394

395395

396396
// String type modifiers
@@ -479,7 +479,7 @@ attribute @db.Bytes() @@@targetField([BytesField]) @@@prisma
479479
attribute @db.ByteA() @@@targetField([BytesField]) @@@prisma
480480
attribute @db.LongBlob() @@@targetField([BytesField]) @@@prisma
481481
attribute @db.Binary() @@@targetField([BytesField]) @@@prisma
482-
attribute @db.VarBinary() @@@targetField([BytesField]) @@@prisma
482+
attribute @db.VarBinary(_ x: Int?) @@@targetField([BytesField]) @@@prisma
483483
attribute @db.TinyBlob() @@@targetField([BytesField]) @@@prisma
484484
attribute @db.Blob() @@@targetField([BytesField]) @@@prisma
485485
attribute @db.MediumBlob() @@@targetField([BytesField]) @@@prisma

packages/schema/src/utils/exec-utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ export function execSync(cmd: string, options?: Omit<ExecSyncOptions, 'env'> & {
88
const mergedEnv = env ? { ...process.env, ...env } : undefined;
99
_exec(cmd, { encoding: 'utf-8', stdio: options?.stdio ?? 'inherit', env: mergedEnv, ...restOptions });
1010
}
11+
12+
/**
13+
* Utility for running package commands through npx/bunx
14+
*/
15+
export function execPackage(cmd: string, options?: Omit<ExecSyncOptions, 'env'> & { env?: Record<string, string> }): void {
16+
const packageManager = process?.versions?.bun ? 'bunx' : 'npx';
17+
execSync(`${packageManager} ${cmd}`, options)
18+
}

packages/schema/tests/schema/stdlib.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ describe('Stdlib Tests', () => {
2424
}`
2525
);
2626
}
27-
throw new SchemaLoadingError(validationErrors.map((e) => e.message));
27+
throw new SchemaLoadingError(validationErrors);
2828
}
2929
});
3030
});

packages/schema/tests/schema/validation/attribute-validation.test.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,25 @@ describe('Attribute tests', () => {
226226
}
227227
`);
228228

229+
await loadModel(`
230+
${ prelude }
231+
model A {
232+
id String @id
233+
x String
234+
y String
235+
z String
236+
@@fulltext([x, y, z])
237+
}
238+
239+
model B {
240+
id String @id
241+
x String
242+
y String
243+
z String
244+
@@fulltext([x, y, z], map: "n")
245+
}
246+
`);
247+
229248
await loadModel(`
230249
${prelude}
231250
model A {
@@ -352,6 +371,7 @@ describe('Attribute tests', () => {
352371
_longBlob Bytes @db.LongBlob
353372
_binary Bytes @db.Binary
354373
_varBinary Bytes @db.VarBinary
374+
_varBinarySized Bytes @db.VarBinary(100)
355375
_tinyBlob Bytes @db.TinyBlob
356376
_blob Bytes @db.Blob
357377
_mediumBlob Bytes @db.MediumBlob

0 commit comments

Comments
 (0)