@opensaas/stack-auth 0.30.0 → 0.31.0

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.
@@ -1,4 +1,4 @@
1
1
 
2
- > @opensaas/stack-auth@0.30.0 build /home/runner/work/stack/stack/packages/auth
2
+ > @opensaas/stack-auth@0.31.0 build /home/runner/work/stack/stack/packages/auth
3
3
  > tsc
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @opensaas/stack-auth
2
2
 
3
+ ## 0.31.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#772](https://github.com/OpenSaasAU/stack/pull/772) [`be5772b`](https://github.com/OpenSaasAU/stack/commit/be5772be231d5be6a77d80c4f7eff5adc15da2fa) Thanks [@borisno2](https://github.com/borisno2)! - Add a regression test locking the generated Session/Account user FK shape (no `@@index([userId])`, `onDelete: Cascade`) so future drift from better-auth parity is caught.
8
+
3
9
  ## 0.30.0
4
10
 
5
11
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opensaas/stack-auth",
3
- "version": "0.30.0",
3
+ "version": "0.31.0",
4
4
  "description": "Better-auth integration for OpenSaas Stack",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -65,7 +65,8 @@
65
65
  "react": "^19.2.4",
66
66
  "typescript": "npm:@typescript/typescript6@^6.0.2",
67
67
  "vitest": "^4.1.10",
68
- "@opensaas/stack-core": "0.30.0"
68
+ "@opensaas/stack-cli": "0.31.0",
69
+ "@opensaas/stack-core": "0.31.0"
69
70
  },
70
71
  "scripts": {
71
72
  "build": "tsc",
@@ -0,0 +1,81 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { config, list } from '@opensaas/stack-core'
3
+ import { text, relationship } from '@opensaas/stack-core/fields'
4
+ import type { OpenSaasConfig } from '@opensaas/stack-core'
5
+ import type { Plugin } from '@opensaas/stack-core/extend'
6
+ import { generatePrismaSchema } from '@opensaas/stack-cli/generator/prisma'
7
+ import { authPlugin } from '../src/config/plugin.js'
8
+
9
+ /**
10
+ * Resolve a config through plugin `init` (via `config()`) and each plugin's
11
+ * `beforeGenerate` hook — the same sequence the CLI generate pipeline runs —
12
+ * then hand the result to the Prisma generator. Unlike the config-level
13
+ * assertions in `derive-auth-lists.test.ts` and `plugin-schema-placement.test.ts`,
14
+ * this exercises the *assembled generated schema text* so the auth FK shape is
15
+ * locked end-to-end (issue #753).
16
+ */
17
+ async function generateSchema(userConfig: OpenSaasConfig): Promise<string> {
18
+ let current = await config(userConfig)
19
+ const plugins: Plugin[] = current.plugins ?? []
20
+ for (const plugin of plugins) {
21
+ if (plugin.beforeGenerate) {
22
+ current = await plugin.beforeGenerate(current)
23
+ }
24
+ }
25
+ return generatePrismaSchema(current)
26
+ }
27
+
28
+ /** Slice out a single `model X { ... }` block from generated schema text. */
29
+ function modelBlock(schema: string, modelName: string): string {
30
+ const start = schema.indexOf(`model ${modelName} {`)
31
+ if (start === -1) throw new Error(`model ${modelName} not found in generated schema`)
32
+ const end = schema.indexOf('\n}', start)
33
+ return schema.slice(start, end === -1 ? undefined : end + 2)
34
+ }
35
+
36
+ describe('generated auth schema — Session/Account user FK mirrors better-auth (issue #679/#753)', () => {
37
+ it('emits onDelete: Cascade and omits @@index on Session.user and Account.user', async () => {
38
+ const schema = await generateSchema({
39
+ db: { provider: 'sqlite' },
40
+ plugins: [authPlugin({ emailAndPassword: { enabled: true } })],
41
+ lists: {},
42
+ })
43
+
44
+ for (const model of ['Session', 'Account']) {
45
+ const block = modelBlock(schema, model)
46
+
47
+ // (a) The user relation carries the cascade referential action. Match on
48
+ // the whitespace-stable attribute substring rather than the padded line,
49
+ // since raw generator output and prisma-formatted output differ only in
50
+ // column alignment.
51
+ expect(block).toContain('@relation(onDelete: Cascade, fields: [userId], references: [id])')
52
+
53
+ // (b) No separate FK index is emitted — parity with better-auth, which
54
+ // ships no @@index([userId]). This is deliberate (ADR-0007), not a
55
+ // regression; catching a re-introduced index here flags drift.
56
+ expect(block).not.toContain('@@index([userId])')
57
+ expect(block).not.toContain('@@index([user])')
58
+ }
59
+ })
60
+
61
+ it('still emits the default @@index for a non-auth relationship FK', async () => {
62
+ // Contrast case: the generic FK-index path is untouched. Only the auth
63
+ // user relations opt out (via isIndexed: false); an ordinary app
64
+ // relationship keeps the default Keystone-parity @@index.
65
+ const schema = await generateSchema({
66
+ db: { provider: 'sqlite' },
67
+ plugins: [authPlugin({ emailAndPassword: { enabled: true } })],
68
+ lists: {
69
+ Widget: list({
70
+ fields: {
71
+ title: text({ validation: { isRequired: true } }),
72
+ owner: relationship({ ref: 'User' }),
73
+ },
74
+ }),
75
+ },
76
+ })
77
+
78
+ const widget = modelBlock(schema, 'Widget')
79
+ expect(widget).toContain('@@index([ownerId])')
80
+ })
81
+ })