diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c5365a5d..b780f2f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -115,7 +115,7 @@ importers: version: 8.34.1(eslint@9.29.0(jiti@2.6.1))(typescript@5.9.3) vitest: specifier: ^4.0.14 - version: 4.0.14(@types/node@20.19.24)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) + version: 4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) yaml: specifier: ^2.8.0 version: 2.8.0 @@ -804,43 +804,6 @@ importers: specifier: 'catalog:' version: 6.19.0(magicast@0.3.5)(typescript@5.9.3) - tests/bun: - dependencies: - '@zenstackhq/cli': - specifier: workspace:* - version: link:../../packages/cli - '@zenstackhq/common-helpers': - specifier: workspace:* - version: link:../../packages/common-helpers - '@zenstackhq/orm': - specifier: workspace:* - version: link:../../packages/orm - '@zenstackhq/plugin-policy': - specifier: workspace:* - version: link:../../packages/plugins/policy - '@zenstackhq/testtools': - specifier: workspace:* - version: link:../../packages/testtools - kysely: - specifier: 'catalog:' - version: 0.28.8 - kysely-bun-sqlite: - specifier: ^0.4.0 - version: 0.4.0(kysely@0.28.8) - pg: - specifier: 'catalog:' - version: 8.16.3 - devDependencies: - '@types/pg': - specifier: ^8.15.6 - version: 8.15.6 - '@zenstackhq/typescript-config': - specifier: workspace:* - version: link:../../packages/config/typescript-config - bun-types: - specifier: ^1.3.3 - version: 1.3.3 - tests/e2e: dependencies: '@paralleldrive/cuid2': @@ -921,6 +884,77 @@ importers: specifier: workspace:* version: link:../../packages/config/vitest-config + tests/runtimes/bun: + dependencies: + '@zenstackhq/cli': + specifier: workspace:* + version: link:../../../packages/cli + '@zenstackhq/common-helpers': + specifier: workspace:* + version: link:../../../packages/common-helpers + '@zenstackhq/orm': + specifier: workspace:* + version: link:../../../packages/orm + '@zenstackhq/plugin-policy': + specifier: workspace:* + version: link:../../../packages/plugins/policy + '@zenstackhq/testtools': + specifier: workspace:* + version: link:../../../packages/testtools + kysely: + specifier: 'catalog:' + version: 0.28.8 + kysely-bun-sqlite: + specifier: ^0.4.0 + version: 0.4.0(kysely@0.28.8) + pg: + specifier: 'catalog:' + version: 8.16.3 + devDependencies: + '@types/pg': + specifier: ^8.15.6 + version: 8.15.6 + '@zenstackhq/typescript-config': + specifier: workspace:* + version: link:../../../packages/config/typescript-config + bun-types: + specifier: ^1.3.3 + version: 1.3.3 + + tests/runtimes/edge-runtime: + dependencies: + '@edge-runtime/vm': + specifier: ^5.0.0 + version: 5.0.0 + '@zenstackhq/cli': + specifier: workspace:* + version: link:../../../packages/cli + '@zenstackhq/common-helpers': + specifier: workspace:* + version: link:../../../packages/common-helpers + '@zenstackhq/orm': + specifier: workspace:* + version: link:../../../packages/orm + '@zenstackhq/plugin-policy': + specifier: workspace:* + version: link:../../../packages/plugins/policy + '@zenstackhq/testtools': + specifier: workspace:* + version: link:../../../packages/testtools + pg: + specifier: 'catalog:' + version: 8.16.3 + devDependencies: + '@types/pg': + specifier: ^8.15.6 + version: 8.15.6 + '@zenstackhq/typescript-config': + specifier: workspace:* + version: link:../../../packages/config/typescript-config + '@zenstackhq/vitest-config': + specifier: workspace:* + version: link:../../../packages/config/vitest-config + packages: '@acemir/cssom@0.9.23': @@ -1139,6 +1173,14 @@ packages: '@dxup/unimport@0.1.0': resolution: {integrity: sha512-6Q/Po8qGmlrShdG/R9+rpIhme9N/PGJumpvmwr1UAxGpt9DfOCt9kF8+yJkxhtPdJFL37KgUILZBRAkSU8cJZg==} + '@edge-runtime/primitives@6.0.0': + resolution: {integrity: sha512-FqoxaBT+prPBHBwE1WXS1ocnu/VLTQyZ6NMUBAdbP7N2hsFTTxMC/jMu2D/8GAlMQfxeuppcPuCUk/HO3fpIvA==} + engines: {node: '>=18'} + + '@edge-runtime/vm@5.0.0': + resolution: {integrity: sha512-NKBGBSIKUG584qrS1tyxVpX/AKJKQw5HgjYEnPLC0QsTw79JrGn+qUr8CXFb955Iy7GUdiiUv1rJ6JBGvaKb6w==} + engines: {node: '>=18'} + '@emnapi/core@1.6.0': resolution: {integrity: sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg==} @@ -7946,6 +7988,12 @@ snapshots: '@dxup/unimport@0.1.0': {} + '@edge-runtime/primitives@6.0.0': {} + + '@edge-runtime/vm@5.0.0': + dependencies: + '@edge-runtime/primitives': 6.0.0 + '@emnapi/core@1.6.0': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -14843,7 +14891,7 @@ snapshots: optionalDependencies: vite: 7.1.12(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.1) - vitest@4.0.14(@types/node@20.19.24)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): + vitest@4.0.14(@edge-runtime/vm@5.0.0)(@types/node@20.19.24)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.1.0)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0): dependencies: '@vitest/expect': 4.0.14 '@vitest/mocker': 4.0.14(vite@7.1.12(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0)) @@ -14866,6 +14914,7 @@ snapshots: vite: 7.1.12(@types/node@20.19.24)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.3)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: + '@edge-runtime/vm': 5.0.0 '@types/node': 20.19.24 happy-dom: 20.0.10 jsdom: 27.1.0 diff --git a/tests/bun/e2e.test.ts b/tests/runtimes/bun/bun-e2e.test.ts similarity index 92% rename from tests/bun/e2e.test.ts rename to tests/runtimes/bun/bun-e2e.test.ts index bfc60494..901daadd 100644 --- a/tests/bun/e2e.test.ts +++ b/tests/runtimes/bun/bun-e2e.test.ts @@ -4,7 +4,7 @@ import { PostgresDialect } from '@zenstackhq/orm/dialects/postgres'; import { PolicyPlugin } from '@zenstackhq/plugin-policy'; import { TEST_PG_URL } from '@zenstackhq/testtools'; import { Database } from 'bun:sqlite'; -import { describe, expect, it } from 'bun:test'; +import { afterEach, describe, expect, it } from 'bun:test'; import type { Dialect } from 'kysely'; import { BunSqliteDialect } from 'kysely-bun-sqlite'; import { Client, Pool } from 'pg'; @@ -13,8 +13,14 @@ import { schema } from './schemas/schema'; describe('Bun e2e tests', () => { const provider = (process.env['TEST_DB_PROVIDER'] ?? 'sqlite') as 'sqlite' | 'postgresql'; + let _db: any; + + afterEach(async () => { + await _db?.$disconnect(); + }); + it('works with simple CRUD', async () => { - const db = await createClient(provider, 'bun-e2e-crud'); + const db = (_db = await createClient(provider, 'bun-e2e-crud')); const user = await db.user.create({ data: { @@ -44,7 +50,7 @@ describe('Bun e2e tests', () => { }); it('enforces policies', async () => { - const db = await createClient(provider, 'bun-e2e-policies'); + const db = (_db = await createClient(provider, 'bun-e2e-policies')); const authDb = db.$use(new PolicyPlugin()); // create a user @@ -58,13 +64,11 @@ describe('Bun e2e tests', () => { { id: 'p1', title: 'First Post', - content: 'Hello World', published: true, }, { id: 'p2', title: 'Second Post', - content: 'Draft Post', published: false, }, ], diff --git a/tests/bun/package.json b/tests/runtimes/bun/package.json similarity index 100% rename from tests/bun/package.json rename to tests/runtimes/bun/package.json diff --git a/tests/bun/schemas/input.ts b/tests/runtimes/bun/schemas/input.ts similarity index 100% rename from tests/bun/schemas/input.ts rename to tests/runtimes/bun/schemas/input.ts diff --git a/tests/bun/schemas/models.ts b/tests/runtimes/bun/schemas/models.ts similarity index 59% rename from tests/bun/schemas/models.ts rename to tests/runtimes/bun/schemas/models.ts index b91301c9..72654e58 100644 --- a/tests/bun/schemas/models.ts +++ b/tests/runtimes/bun/schemas/models.ts @@ -5,10 +5,7 @@ /* eslint-disable */ -import { schema as $schema, type SchemaType as $Schema } from "./schema"; -import { type ModelResult as $ModelResult, type TypeDefResult as $TypeDefResult } from "@zenstackhq/orm"; +import { type SchemaType as $Schema } from "./schema"; +import { type ModelResult as $ModelResult } from "@zenstackhq/orm"; export type User = $ModelResult<$Schema, "User">; export type Post = $ModelResult<$Schema, "Post">; -export type CommonFields = $TypeDefResult<$Schema, "CommonFields">; -export const Role = $schema.enums.Role.values; -export type Role = (typeof Role)[keyof typeof Role]; diff --git a/tests/bun/schemas/schema.ts b/tests/runtimes/bun/schemas/schema.ts similarity index 64% rename from tests/bun/schemas/schema.ts rename to tests/runtimes/bun/schemas/schema.ts index 627922bc..b7d3bfcd 100644 --- a/tests/bun/schemas/schema.ts +++ b/tests/runtimes/bun/schemas/schema.ts @@ -21,18 +21,6 @@ const _schema = { attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], default: ExpressionUtils.call("cuid") }, - createdAt: { - name: "createdAt", - type: "DateTime", - attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }], - default: ExpressionUtils.call("now") - }, - updatedAt: { - name: "updatedAt", - type: "DateTime", - updatedAt: true, - attributes: [{ name: "@updatedAt" }] - }, email: { name: "email", type: "String", @@ -44,22 +32,11 @@ const _schema = { type: "String", optional: true }, - role: { - name: "role", - type: "Role", - attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.literal("USER") }] }], - default: "USER" - }, posts: { name: "posts", type: "Post", array: true, relation: { opposite: "author" } - }, - meta: { - name: "meta", - type: "Json", - optional: true } }, attributes: [ @@ -82,27 +59,10 @@ const _schema = { attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], default: ExpressionUtils.call("cuid") }, - createdAt: { - name: "createdAt", - type: "DateTime", - attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }], - default: ExpressionUtils.call("now") - }, - updatedAt: { - name: "updatedAt", - type: "DateTime", - updatedAt: true, - attributes: [{ name: "@updatedAt" }] - }, title: { name: "title", type: "String" }, - content: { - name: "content", - type: "String", - optional: true - }, published: { name: "published", type: "Boolean", @@ -134,39 +94,6 @@ const _schema = { } } }, - typeDefs: { - CommonFields: { - name: "CommonFields", - fields: { - id: { - name: "id", - type: "String", - attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], - default: ExpressionUtils.call("cuid") - }, - createdAt: { - name: "createdAt", - type: "DateTime", - attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.call("now") }] }], - default: ExpressionUtils.call("now") - }, - updatedAt: { - name: "updatedAt", - type: "DateTime", - updatedAt: true, - attributes: [{ name: "@updatedAt" }] - } - } - } - }, - enums: { - Role: { - values: { - ADMIN: "ADMIN", - USER: "USER" - } - } - }, authType: "User", plugins: {} } as const satisfies SchemaDef; diff --git a/tests/bun/schemas/schema.zmodel b/tests/runtimes/bun/schemas/schema.zmodel similarity index 54% rename from tests/bun/schemas/schema.zmodel rename to tests/runtimes/bun/schemas/schema.zmodel index 05f14bf4..ee491c08 100644 --- a/tests/bun/schemas/schema.zmodel +++ b/tests/runtimes/bun/schemas/schema.zmodel @@ -1,39 +1,25 @@ datasource db { provider = "sqlite" - url = "file:./dev.db" } plugin policy { provider = "../../../packages/plugins/policy" } -enum Role { - ADMIN - USER -} - -type CommonFields { - id String @id @default(cuid()) - createdAt DateTime @default(now()) - updatedAt DateTime @updatedAt -} - -model User with CommonFields { - email String @unique - name String? - password String @ignore - role Role @default(USER) - posts Post[] - meta Json? +model User { + id String @id @default(cuid()) + email String @unique + name String? + posts Post[] // Access policies @@allow('all', auth().id == id) @@allow('read', auth() != null) } -model Post with CommonFields { +model Post { + id String @id @default(cuid()) title String - content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id], onUpdate: Cascade, onDelete: Cascade) authorId String @@ -43,4 +29,3 @@ model Post with CommonFields { @@allow('all', auth().id == authorId) @@allow('read', published) } - diff --git a/tests/bun/scripts/generate.ts b/tests/runtimes/bun/scripts/generate.ts similarity index 100% rename from tests/bun/scripts/generate.ts rename to tests/runtimes/bun/scripts/generate.ts diff --git a/tests/bun/tsconfig.json b/tests/runtimes/bun/tsconfig.json similarity index 100% rename from tests/bun/tsconfig.json rename to tests/runtimes/bun/tsconfig.json diff --git a/tests/runtimes/edge-runtime/.DS_Store b/tests/runtimes/edge-runtime/.DS_Store new file mode 100644 index 00000000..d6f7ebb2 Binary files /dev/null and b/tests/runtimes/edge-runtime/.DS_Store differ diff --git a/tests/runtimes/edge-runtime/edge-runtime-e2e.test.ts b/tests/runtimes/edge-runtime/edge-runtime-e2e.test.ts new file mode 100644 index 00000000..ca3b57e2 --- /dev/null +++ b/tests/runtimes/edge-runtime/edge-runtime-e2e.test.ts @@ -0,0 +1,101 @@ +import { ZenStackClient } from '@zenstackhq/orm'; +import { PostgresDialect } from '@zenstackhq/orm/dialects/postgres'; +import { PolicyPlugin } from '@zenstackhq/plugin-policy'; +import { TEST_PG_URL } from '@zenstackhq/testtools'; +import { Client, Pool } from 'pg'; +import { afterEach, describe, expect, it } from 'vitest'; +import { schema } from './schemas/schema'; + +describe('Edge-runtime e2e tests', () => { + let _db: any; + + afterEach(async () => { + await _db?.$disconnect(); + }); + + it('works with simple CRUD', async () => { + const db = (_db = await createClient('edge-runtime-e2e-crud')); + + const user = await db.user.create({ + data: { + id: '1', + email: 'u1@example.com', + name: 'Test User', + }, + }); + expect(user).toMatchObject({ + id: '1', + email: 'u1@example.com', + name: 'Test User', + }); + + let found = await db.user.findUnique({ + where: { id: '1' }, + }); + expect(found).toMatchObject(user); + + await db.user.update({ where: { id: '1' }, data: { name: 'Updated Name' } }); + found = await db.user.findFirst(); + expect(found).toMatchObject({ name: 'Updated Name' }); + + await db.user.delete({ where: { id: '1' } }); + const count = await db.user.count(); + expect(count).toBe(0); + }); + + it('enforces policies', async () => { + const db = (_db = await createClient('edge-runtime-e2e-policies')); + const authDb = db.$use(new PolicyPlugin()); + + // create a user + await db.user.create({ + data: { + id: '1', + email: 'u1@example.com', + name: 'Test User', + posts: { + create: [ + { + id: 'p1', + title: 'First Post', + published: true, + }, + { + id: 'p2', + title: 'Second Post', + published: false, + }, + ], + }, + }, + }); + + const anonCount = await authDb.post.count(); + expect(anonCount).toBe(0); + + const user1DbCount = await authDb.$setAuth({ id: '1' }).post.count(); + expect(user1DbCount).toBe(2); + + const user2DbCount = await authDb.$setAuth({ id: '2' }).post.count(); + expect(user2DbCount).toBe(1); + }); +}); + +async function createClient(dbName: string) { + const pgClient = new Client({ + connectionString: TEST_PG_URL, + }); + await pgClient.connect(); + await pgClient.query(`DROP DATABASE IF EXISTS "${dbName}"`); + await pgClient.query(`CREATE DATABASE "${dbName}"`); + await pgClient.end(); + const dialect = new PostgresDialect({ + pool: new Pool({ + connectionString: `${TEST_PG_URL}/${dbName}`, + }), + }); + + const db = new ZenStackClient(schema, { dialect }); + await db.$pushSchema(); + return db; +} diff --git a/tests/runtimes/edge-runtime/package.json b/tests/runtimes/edge-runtime/package.json new file mode 100644 index 00000000..324a21ca --- /dev/null +++ b/tests/runtimes/edge-runtime/package.json @@ -0,0 +1,26 @@ +{ + "name": "edge-runtime-e2e", + "version": "3.0.0-beta.27", + "private": true, + "type": "module", + "scripts": { + "build": "pnpm test:generate && pnpm test:typecheck", + "test:generate": "tsx scripts/generate.ts", + "test:typecheck": "tsc --noEmit", + "test": "vitest run" + }, + "dependencies": { + "@edge-runtime/vm": "^5.0.0", + "@zenstackhq/cli": "workspace:*", + "@zenstackhq/common-helpers": "workspace:*", + "@zenstackhq/orm": "workspace:*", + "@zenstackhq/plugin-policy": "workspace:*", + "@zenstackhq/testtools": "workspace:*", + "pg": "catalog:" + }, + "devDependencies": { + "@types/pg": "^8.15.6", + "@zenstackhq/typescript-config": "workspace:*", + "@zenstackhq/vitest-config": "workspace:*" + } +} diff --git a/tests/runtimes/edge-runtime/schemas/input.ts b/tests/runtimes/edge-runtime/schemas/input.ts new file mode 100644 index 00000000..fb776314 --- /dev/null +++ b/tests/runtimes/edge-runtime/schemas/input.ts @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaType as $Schema } from "./schema"; +import type { FindManyArgs as $FindManyArgs, FindUniqueArgs as $FindUniqueArgs, FindFirstArgs as $FindFirstArgs, CreateArgs as $CreateArgs, CreateManyArgs as $CreateManyArgs, CreateManyAndReturnArgs as $CreateManyAndReturnArgs, UpdateArgs as $UpdateArgs, UpdateManyArgs as $UpdateManyArgs, UpdateManyAndReturnArgs as $UpdateManyAndReturnArgs, UpsertArgs as $UpsertArgs, DeleteArgs as $DeleteArgs, DeleteManyArgs as $DeleteManyArgs, CountArgs as $CountArgs, AggregateArgs as $AggregateArgs, GroupByArgs as $GroupByArgs, WhereInput as $WhereInput, SelectInput as $SelectInput, IncludeInput as $IncludeInput, OmitInput as $OmitInput, ClientOptions as $ClientOptions } from "@zenstackhq/orm"; +import type { SimplifiedModelResult as $SimplifiedModelResult, SelectIncludeOmit as $SelectIncludeOmit } from "@zenstackhq/orm"; +export type UserFindManyArgs = $FindManyArgs<$Schema, "User">; +export type UserFindUniqueArgs = $FindUniqueArgs<$Schema, "User">; +export type UserFindFirstArgs = $FindFirstArgs<$Schema, "User">; +export type UserCreateArgs = $CreateArgs<$Schema, "User">; +export type UserCreateManyArgs = $CreateManyArgs<$Schema, "User">; +export type UserCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "User">; +export type UserUpdateArgs = $UpdateArgs<$Schema, "User">; +export type UserUpdateManyArgs = $UpdateManyArgs<$Schema, "User">; +export type UserUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "User">; +export type UserUpsertArgs = $UpsertArgs<$Schema, "User">; +export type UserDeleteArgs = $DeleteArgs<$Schema, "User">; +export type UserDeleteManyArgs = $DeleteManyArgs<$Schema, "User">; +export type UserCountArgs = $CountArgs<$Schema, "User">; +export type UserAggregateArgs = $AggregateArgs<$Schema, "User">; +export type UserGroupByArgs = $GroupByArgs<$Schema, "User">; +export type UserWhereInput = $WhereInput<$Schema, "User">; +export type UserSelect = $SelectInput<$Schema, "User">; +export type UserInclude = $IncludeInput<$Schema, "User">; +export type UserOmit = $OmitInput<$Schema, "User">; +export type UserGetPayload, Options extends $ClientOptions<$Schema> = $ClientOptions<$Schema>> = $SimplifiedModelResult<$Schema, "User", Options, Args>; +export type PostFindManyArgs = $FindManyArgs<$Schema, "Post">; +export type PostFindUniqueArgs = $FindUniqueArgs<$Schema, "Post">; +export type PostFindFirstArgs = $FindFirstArgs<$Schema, "Post">; +export type PostCreateArgs = $CreateArgs<$Schema, "Post">; +export type PostCreateManyArgs = $CreateManyArgs<$Schema, "Post">; +export type PostCreateManyAndReturnArgs = $CreateManyAndReturnArgs<$Schema, "Post">; +export type PostUpdateArgs = $UpdateArgs<$Schema, "Post">; +export type PostUpdateManyArgs = $UpdateManyArgs<$Schema, "Post">; +export type PostUpdateManyAndReturnArgs = $UpdateManyAndReturnArgs<$Schema, "Post">; +export type PostUpsertArgs = $UpsertArgs<$Schema, "Post">; +export type PostDeleteArgs = $DeleteArgs<$Schema, "Post">; +export type PostDeleteManyArgs = $DeleteManyArgs<$Schema, "Post">; +export type PostCountArgs = $CountArgs<$Schema, "Post">; +export type PostAggregateArgs = $AggregateArgs<$Schema, "Post">; +export type PostGroupByArgs = $GroupByArgs<$Schema, "Post">; +export type PostWhereInput = $WhereInput<$Schema, "Post">; +export type PostSelect = $SelectInput<$Schema, "Post">; +export type PostInclude = $IncludeInput<$Schema, "Post">; +export type PostOmit = $OmitInput<$Schema, "Post">; +export type PostGetPayload, Options extends $ClientOptions<$Schema> = $ClientOptions<$Schema>> = $SimplifiedModelResult<$Schema, "Post", Options, Args>; diff --git a/tests/runtimes/edge-runtime/schemas/models.ts b/tests/runtimes/edge-runtime/schemas/models.ts new file mode 100644 index 00000000..72654e58 --- /dev/null +++ b/tests/runtimes/edge-runtime/schemas/models.ts @@ -0,0 +1,11 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaType as $Schema } from "./schema"; +import { type ModelResult as $ModelResult } from "@zenstackhq/orm"; +export type User = $ModelResult<$Schema, "User">; +export type Post = $ModelResult<$Schema, "Post">; diff --git a/tests/runtimes/edge-runtime/schemas/schema.ts b/tests/runtimes/edge-runtime/schemas/schema.ts new file mode 100644 index 00000000..7f4436f8 --- /dev/null +++ b/tests/runtimes/edge-runtime/schemas/schema.ts @@ -0,0 +1,104 @@ +////////////////////////////////////////////////////////////////////////////////////////////// +// DO NOT MODIFY THIS FILE // +// This file is automatically generated by ZenStack CLI and should not be manually updated. // +////////////////////////////////////////////////////////////////////////////////////////////// + +/* eslint-disable */ + +import { type SchemaDef, ExpressionUtils } from "@zenstackhq/orm/schema"; +const _schema = { + provider: { + type: "postgresql" + }, + models: { + User: { + name: "User", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + email: { + name: "email", + type: "String", + unique: true, + attributes: [{ name: "@unique" }] + }, + name: { + name: "name", + type: "String", + optional: true + }, + posts: { + name: "posts", + type: "Post", + array: true, + relation: { opposite: "author" } + } + }, + attributes: [ + { name: "@@allow", args: [{ name: "operation", value: ExpressionUtils.literal("all") }, { name: "condition", value: ExpressionUtils.binary(ExpressionUtils.member(ExpressionUtils.call("auth"), ["id"]), "==", ExpressionUtils.field("id")) }] }, + { name: "@@allow", args: [{ name: "operation", value: ExpressionUtils.literal("read") }, { name: "condition", value: ExpressionUtils.binary(ExpressionUtils.call("auth"), "!=", ExpressionUtils._null()) }] } + ], + idFields: ["id"], + uniqueFields: { + id: { type: "String" }, + email: { type: "String" } + } + }, + Post: { + name: "Post", + fields: { + id: { + name: "id", + type: "String", + id: true, + attributes: [{ name: "@id" }, { name: "@default", args: [{ name: "value", value: ExpressionUtils.call("cuid") }] }], + default: ExpressionUtils.call("cuid") + }, + title: { + name: "title", + type: "String" + }, + published: { + name: "published", + type: "Boolean", + attributes: [{ name: "@default", args: [{ name: "value", value: ExpressionUtils.literal(false) }] }], + default: false + }, + author: { + name: "author", + type: "User", + attributes: [{ name: "@relation", args: [{ name: "fields", value: ExpressionUtils.array([ExpressionUtils.field("authorId")]) }, { name: "references", value: ExpressionUtils.array([ExpressionUtils.field("id")]) }, { name: "onUpdate", value: ExpressionUtils.literal("Cascade") }, { name: "onDelete", value: ExpressionUtils.literal("Cascade") }] }], + relation: { opposite: "posts", fields: ["authorId"], references: ["id"], onUpdate: "Cascade", onDelete: "Cascade" } + }, + authorId: { + name: "authorId", + type: "String", + foreignKeyFor: [ + "author" + ] + } + }, + attributes: [ + { name: "@@deny", args: [{ name: "operation", value: ExpressionUtils.literal("all") }, { name: "condition", value: ExpressionUtils.binary(ExpressionUtils.call("auth"), "==", ExpressionUtils._null()) }] }, + { name: "@@allow", args: [{ name: "operation", value: ExpressionUtils.literal("all") }, { name: "condition", value: ExpressionUtils.binary(ExpressionUtils.member(ExpressionUtils.call("auth"), ["id"]), "==", ExpressionUtils.field("authorId")) }] }, + { name: "@@allow", args: [{ name: "operation", value: ExpressionUtils.literal("read") }, { name: "condition", value: ExpressionUtils.field("published") }] } + ], + idFields: ["id"], + uniqueFields: { + id: { type: "String" } + } + } + }, + authType: "User", + plugins: {} +} as const satisfies SchemaDef; +type Schema = typeof _schema & { + __brand?: "schema"; +}; +export const schema: Schema = _schema; +export type SchemaType = Schema; diff --git a/tests/runtimes/edge-runtime/schemas/schema.zmodel b/tests/runtimes/edge-runtime/schemas/schema.zmodel new file mode 100644 index 00000000..7872ce26 --- /dev/null +++ b/tests/runtimes/edge-runtime/schemas/schema.zmodel @@ -0,0 +1,31 @@ +datasource db { + provider = "postgresql" +} + +plugin policy { + provider = "../../../packages/plugins/policy" +} + +model User { + id String @id @default(cuid()) + email String @unique + name String? + posts Post[] + + // Access policies + @@allow('all', auth().id == id) + @@allow('read', auth() != null) +} + +model Post { + id String @id @default(cuid()) + title String + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id], onUpdate: Cascade, onDelete: Cascade) + authorId String + + // Access policies + @@deny('all', auth() == null) + @@allow('all', auth().id == authorId) + @@allow('read', published) +} diff --git a/tests/runtimes/edge-runtime/scripts/generate.ts b/tests/runtimes/edge-runtime/scripts/generate.ts new file mode 100644 index 00000000..cd68f93b --- /dev/null +++ b/tests/runtimes/edge-runtime/scripts/generate.ts @@ -0,0 +1,20 @@ +import { glob } from 'glob'; +import { execSync } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const dir = path.dirname(fileURLToPath(import.meta.url)); + +async function main() { + const zmodelFiles = [...glob.sync(path.resolve(dir, '../schemas/*.zmodel'))]; + for (const file of zmodelFiles) { + console.log(`Generating TS schema for: ${file}`); + await generate(file); + } +} + +async function generate(schemaPath: string) { + execSync('npx zen generate', { cwd: path.dirname(schemaPath) }); +} + +main(); diff --git a/tests/runtimes/edge-runtime/tsconfig.json b/tests/runtimes/edge-runtime/tsconfig.json new file mode 100644 index 00000000..b17ade81 --- /dev/null +++ b/tests/runtimes/edge-runtime/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "@zenstackhq/typescript-config/base.json", + "compilerOptions": { + "noEmit": true + } +} diff --git a/tests/runtimes/edge-runtime/vitest.config.ts b/tests/runtimes/edge-runtime/vitest.config.ts new file mode 100644 index 00000000..e9e63f31 --- /dev/null +++ b/tests/runtimes/edge-runtime/vitest.config.ts @@ -0,0 +1,11 @@ +import base from '@zenstackhq/vitest-config/base'; +import { defineConfig, mergeConfig } from 'vitest/config'; + +export default mergeConfig( + base, + defineConfig({ + test: { + environment: 'edge-runtime', + }, + }), +); diff --git a/vitest.config.ts b/vitest.config.ts index f7268cb1..e4c2666a 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -2,6 +2,6 @@ import { defineConfig } from 'vitest/config'; export default defineConfig({ test: { - projects: ['packages/*', 'tests/*'], + projects: ['packages/**', 'tests/**'], }, });