Skip to content
This repository was archived by the owner on Mar 1, 2026. It is now read-only.

Commit 25d11e0

Browse files
committed
fix(zmodel): require implicitly used "public" schema to be declared in "schemas" config
1 parent 081e434 commit 25d11e0

2 files changed

Lines changed: 54 additions & 9 deletions

File tree

packages/language/src/validators/datasource-validator.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { ValidationAcceptor } from 'langium';
22
import { SUPPORTED_PROVIDERS } from '../constants';
3-
import { DataSource, isConfigArrayExpr, isInvocationExpr, isLiteralExpr } from '../generated/ast';
3+
import { DataSource, isConfigArrayExpr, isDataModel, isEnum, isInvocationExpr, isLiteralExpr } from '../generated/ast';
44
import { getStringLiteral } from '../utils';
55
import { validateDuplicatedDeclarations, type AstValidator } from './common';
66

@@ -70,14 +70,28 @@ export default class DataSourceValidator implements AstValidator<DataSource> {
7070
accept('error', '"schemas" must be an array of string literals', {
7171
node: schemasField,
7272
});
73-
} else if (
74-
// validate `defaultSchema` is included in `schemas`
75-
defaultSchemaValue &&
76-
!schemasValue.items.some((e) => getStringLiteral(e) === defaultSchemaValue)
77-
) {
78-
accept('error', `"${defaultSchemaValue}" must be included in the "schemas" array`, {
79-
node: schemasField,
80-
});
73+
} else {
74+
const schemasArray = schemasValue.items.map((e) => getStringLiteral(e)!);
75+
76+
if (defaultSchemaValue) {
77+
// validate `defaultSchema` is included in `schemas`
78+
if (!schemasArray.includes(defaultSchemaValue)) {
79+
accept('error', `"${defaultSchemaValue}" must be included in the "schemas" array`, {
80+
node: schemasField,
81+
});
82+
}
83+
} else {
84+
// if no explicit default schema is specified, and there are models or enums without '@@schema',
85+
// "public" is implicitly used, so it must be included in the "schemas" array
86+
const hasImplicitPublicSchema = ds.$container.declarations.some(
87+
(d) => (isDataModel(d) || isEnum(d)) && !d.attributes.some((a) => a.decl.$refText === 'schema'),
88+
);
89+
if (hasImplicitPublicSchema && !schemasArray.includes('public')) {
90+
accept('error', `"public" must be included in the "schemas" array`, {
91+
node: schemasField,
92+
});
93+
}
94+
}
8195
}
8296
}
8397
}

tests/e2e/orm/client-api/pg-custom-schema.test.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,37 @@ model Foo {
247247
).rejects.toThrow('"mySchema" must be included in the "schemas" array');
248248
});
249249

250+
it('requires implicit public schema to be included in schemas', async () => {
251+
await expect(
252+
createTestClient(
253+
`
254+
datasource db {
255+
provider = 'postgresql'
256+
schemas = ['mySchema']
257+
url = '$DB_URL'
258+
}
259+
260+
enum Role {
261+
ADMIN
262+
USER
263+
}
264+
265+
model Foo {
266+
id Int @id
267+
name String
268+
role Role
269+
@@schema('mySchema')
270+
}
271+
272+
model Bar {
273+
id Int @id
274+
name String
275+
}
276+
`,
277+
),
278+
).rejects.toThrow('"public" must be included in the "schemas" array');
279+
});
280+
250281
it('allows specifying schema only on a few models', async () => {
251282
let fooQueriesVerified = false;
252283
let barQueriesVerified = false;

0 commit comments

Comments
 (0)