Skip to content

Commit

Permalink
Merge from dev
Browse files Browse the repository at this point in the history
  • Loading branch information
ymc9 committed Mar 13, 2024
1 parent b63589a commit df4edcc
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 89 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<a href="https://twitter.com/zenstackhq">
<img src="https://img.shields.io/twitter/url?style=social&url=https%3A%2F%2Fgithub.com%2Fzenstackhq%2Fzenstack">
</a>
<a href="https://go.zenstack.dev/chat">
<a href="https://discord.gg/Ykhr738dUe">
<img src="https://img.shields.io/discord/1035538056146595961">
</a>
<a href="https://github.com/zenstackhq/zenstack/blob/main/LICENSE">
Expand Down Expand Up @@ -142,7 +142,7 @@ The following diagram gives a high-level architecture overview of ZenStack.

- [Home](https://zenstack.dev)
- [Documentation](https://zenstack.dev/docs)
- [Community chat](https://go.zenstack.dev/chat)
- [Community chat](https://discord.gg/Ykhr738dUe)
- [Twitter](https://twitter.com/zenstackhq)
- [Blog](https://zenstack.dev/blog)

Expand All @@ -162,7 +162,7 @@ The following diagram gives a high-level architecture overview of ZenStack.
- [SWR](https://github.com/vercel/swr) and [TanStack Query](https://github.com/TanStack/query) hooks generator
- OpenAPI specification generator
- [tRPC](https://trpc.io) router generator
- 🙋🏻 [Request for a plugin](https://go.zenstack.dev/chat)
- 🙋🏻 [Request for a plugin](https://discord.gg/Ykhr738dUe)

### Framework adapters

Expand All @@ -171,15 +171,15 @@ The following diagram gives a high-level architecture overview of ZenStack.
- [SvelteKit](https://zenstack.dev/docs/reference/server-adapters/sveltekit)
- [Fastify](https://zenstack.dev/docs/reference/server-adapters/fastify)
- [ExpressJS](https://zenstack.dev/docs/reference/server-adapters/express)
- 🙋🏻 [Request for an adapter](https://go.zenstack.dev/chat)
- 🙋🏻 [Request for an adapter](https://discord.gg/Ykhr738dUe)

### Prisma schema extensions

- [Custom attributes and functions](https://zenstack.dev/docs/reference/zmodel-language#custom-attributes-and-functions)
- [Multi-file schema and model inheritance](https://zenstack.dev/docs/guides/multiple-schema)
- Strong-typed JSON field (coming soon)
- Polymorphism (future)
- 🙋🏻 [Request for an extension](https://go.zenstack.dev/chat)
- 🙋🏻 [Request for an extension](https://discord.gg/Ykhr738dUe)

## Examples

Expand Down
4 changes: 2 additions & 2 deletions packages/schema/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ This VS Code extension provides code editing helpers for authoring ZenStack's sc

- [Home](https://zenstack.dev)
- [Documentation](https://zenstack.dev/docs)
- [Community chat](https://go.zenstack.dev/chat)
- [Community chat](https://discord.gg/Ykhr738dUe)
- [Twitter](https://twitter.com/zenstackhq)
- [Blog](https://dev.to/zenstack)

## Community

Join our [discord server](https://go.zenstack.dev/chat) for chat and updates!
Join our [discord server](https://discord.gg/Ykhr738dUe) for chat and updates!

## License

Expand Down
148 changes: 66 additions & 82 deletions packages/schema/tests/schema/validation/datamodel-validation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@ describe('Data Model Validation Tests', () => {

it('duplicated fields', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
id String @id
x Int
x String
}
`);
`)

expect(result).toMatchObject(errorLike('Duplicated declaration name "x"'));
});
Expand Down Expand Up @@ -128,14 +128,14 @@ describe('Data Model Validation Tests', () => {

it('should error when there are no unique fields', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int
@@allow('all', x > 0)
}
`);
`)
expect(result).toMatchObject(errorLike(err));
});
})

it('should should use @unique when there is no @id', async () => {
const result = await safelyLoadModel(`
Expand All @@ -147,24 +147,24 @@ describe('Data Model Validation Tests', () => {
}
`);
expect(result).toMatchObject({ status: 'fulfilled' });
});
})

// @@unique used as id
it('should suceed when @@unique used as id', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int
@@unique([x])
@@allow('all', x > 0)
}
`);
expect(result).toMatchObject({ status: 'fulfilled' });
});
})

it('should succeed when @id is an enum type', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
enum E {
A
B
Expand All @@ -174,11 +174,11 @@ describe('Data Model Validation Tests', () => {
}
`);
expect(result).toMatchObject({ status: 'fulfilled' });
});
})

it('should succeed when @@id is an enum type', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
enum E {
A
B
Expand All @@ -190,145 +190,143 @@ describe('Data Model Validation Tests', () => {
}
`);
expect(result).toMatchObject({ status: 'fulfilled' });
});
})

it('should error when there are no id fields, even when denying access', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int
@@deny('all', x <= 0)
}
`);

`)
expect(result).toMatchObject(errorLike(err));
});
})

it('should error when there are not id fields, without access restrictions', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int @gt(0)
}
`);

`)
expect(result).toMatchObject(errorLike(err));
});
})

it('should error when there is more than one field marked as @id', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int @id
y Int @id
}
`);
expect(result).toMatchObject(errorLike(`Model can include at most one field with @id attribute`));
});
`)
expect(result).toMatchObject(errorLike(`Model can include at most one field with @id attribute`))
})

it('should error when both @id and @@id are used', async () => {
it('should error when both @id and @@id are used', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int @id
y Int
@@id([x, y])
}
`);
expect(result).toMatchObject(
errorLike(`Model cannot have both field-level @id and model-level @@id attributes`)
);
});
`)
expect(result).toMatchObject(errorLike(`Model cannot have both field-level @id and model-level @@id attributes`))
})

it('should error when @id used on optional field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int? @id
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must not be optional`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must not be optional`))
})

it('should error when @@id used on optional field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int?
@@id([x])
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must not be optional`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must not be optional`))
})

it('should error when @id used on list field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int[] @id
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`))
})

it('should error when @@id used on list field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Int[]
@@id([x])
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`))
})

it('should error when @id used on a Json field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Json @id
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`))
})

it('should error when @@id used on a Json field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model M {
x Json
@@id([x])
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`))
})

it('should error when @id used on a reference field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model Id {
id String @id
}
model M {
myId Id @id
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`))
})

it('should error when @@id used on a reference field', async () => {
const result = await safelyLoadModel(`
${prelude}
${ prelude }
model Id {
id String @id
}
model M {
myId Id
@@id([myId])
}
`);
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`));
});
`)
expect(result).toMatchObject(errorLike(`Field with @id attribute must be of scalar or enum type`))
})
});

it('relation', async () => {
Expand Down Expand Up @@ -392,9 +390,7 @@ describe('Data Model Validation Tests', () => {
id String @id
}
`)
).toMatchObject(
errorLike(`The relation field "b" on model "A" is missing an opposite relation field on model "B"`)
);
).toMatchObject(errorLike(`The relation field "b" on model "A" is missing an opposite relation field on model "B"`));

// one-to-one ambiguous
expect(
Expand Down Expand Up @@ -496,11 +492,7 @@ describe('Data Model Validation Tests', () => {
aId String
}
`)
).toMatchObject(
errorLike(
`Field "aId" is part of a one-to-one relation and must be marked as @unique or be part of a model-level @@unique attribute`
)
);
).toMatchObject(errorLike(`Field "aId" is part of a one-to-one relation and must be marked as @unique or be part of a model-level @@unique attribute`));

// missing @relation
expect(
Expand All @@ -516,11 +508,7 @@ describe('Data Model Validation Tests', () => {
a A
}
`)
).toMatchObject(
errorLike(
`Field for one side of relation must carry @relation attribute with both "fields" and "references" fields`
)
);
).toMatchObject(errorLike(`Field for one side of relation must carry @relation attribute with both "fields" and "references" fields`));

// wrong relation owner field type
expect(
Expand Down Expand Up @@ -684,9 +672,7 @@ describe('Data Model Validation Tests', () => {
}
`);

expect(errors).toMatchObject(
errorLike(`Model A cannot be extended because it's neither abstract nor marked as "@@delegate"`)
);
expect(errors).toMatchObject(errorLike(`Model A cannot be extended because it's not abstract`));

// relation incomplete from multiple level inheritance
expect(
Expand All @@ -710,8 +696,6 @@ describe('Data Model Validation Tests', () => {
a String
}
`)
).toMatchObject(
errorLike(`The relation field "user" on model "A" is missing an opposite relation field on model "User"`)
);
).toMatchObject(errorLike(`The relation field "user" on model "A" is missing an opposite relation field on model "User"`));
});
});

0 comments on commit df4edcc

Please sign in to comment.