@opensaas/stack-core 0.1.7 → 0.4.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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +352 -0
- package/CLAUDE.md +46 -1
- package/dist/access/engine.d.ts +7 -6
- package/dist/access/engine.d.ts.map +1 -1
- package/dist/access/engine.js +55 -0
- package/dist/access/engine.js.map +1 -1
- package/dist/access/engine.test.d.ts +2 -0
- package/dist/access/engine.test.d.ts.map +1 -0
- package/dist/access/engine.test.js +125 -0
- package/dist/access/engine.test.js.map +1 -0
- package/dist/access/types.d.ts +39 -9
- package/dist/access/types.d.ts.map +1 -1
- package/dist/config/index.d.ts +40 -20
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +34 -15
- package/dist/config/index.js.map +1 -1
- package/dist/config/plugin-engine.d.ts.map +1 -1
- package/dist/config/plugin-engine.js +9 -0
- package/dist/config/plugin-engine.js.map +1 -1
- package/dist/config/types.d.ts +277 -84
- package/dist/config/types.d.ts.map +1 -1
- package/dist/context/index.d.ts +5 -3
- package/dist/context/index.d.ts.map +1 -1
- package/dist/context/index.js +146 -20
- package/dist/context/index.js.map +1 -1
- package/dist/context/nested-operations.d.ts.map +1 -1
- package/dist/context/nested-operations.js +88 -72
- package/dist/context/nested-operations.js.map +1 -1
- package/dist/fields/index.d.ts +65 -9
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +98 -16
- package/dist/fields/index.js.map +1 -1
- package/dist/hooks/index.d.ts +28 -12
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +16 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp/handler.js +1 -0
- package/dist/mcp/handler.js.map +1 -1
- package/dist/validation/schema.d.ts.map +1 -1
- package/dist/validation/schema.js +4 -2
- package/dist/validation/schema.js.map +1 -1
- package/package.json +8 -9
- package/src/access/engine.test.ts +145 -0
- package/src/access/engine.ts +73 -9
- package/src/access/types.ts +38 -8
- package/src/config/index.ts +45 -23
- package/src/config/plugin-engine.ts +13 -3
- package/src/config/types.ts +347 -117
- package/src/context/index.ts +176 -23
- package/src/context/nested-operations.ts +83 -71
- package/src/fields/index.ts +132 -27
- package/src/hooks/index.ts +63 -20
- package/src/index.ts +9 -0
- package/src/mcp/handler.ts +2 -1
- package/src/validation/schema.ts +4 -2
- package/tests/context.test.ts +38 -6
- package/tests/field-types.test.ts +729 -0
- package/tests/password-type-distribution.test.ts +0 -1
- package/tests/password-types.test.ts +0 -1
- package/tests/plugin-engine.test.ts +1102 -0
- package/tests/sudo.test.ts +230 -2
- package/tsconfig.tsbuildinfo +1 -1
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,357 @@
|
|
|
1
1
|
# @opensaas/stack-core
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#190](https://github.com/OpenSaasAU/stack/pull/190) [`527b677`](https://github.com/OpenSaasAU/stack/commit/527b677ab598070185e23d163a9e99bc20f03c49) Thanks [@borisno2](https://github.com/borisno2)! - Fix nested operations to respect sudo mode, preventing access control checks when using context.sudo()
|
|
8
|
+
|
|
9
|
+
When using `context.sudo()`, nested relationship operations (create, connect, update, connectOrCreate) were still enforcing access control checks, causing "Access denied" errors even when sudo mode should bypass all access control.
|
|
10
|
+
|
|
11
|
+
This fix adds `context._isSudo` checks to all four nested operation functions in `packages/core/src/context/nested-operations.ts`:
|
|
12
|
+
- `processNestedCreate()` - Now skips create access control in sudo mode
|
|
13
|
+
- `processNestedConnect()` - Now skips update access control in sudo mode
|
|
14
|
+
- `processNestedUpdate()` - Now skips update access control in sudo mode
|
|
15
|
+
- `processNestedConnectOrCreate()` - Now skips update access control in sudo mode
|
|
16
|
+
|
|
17
|
+
The fix ensures that when `context.sudo()` is used, all nested operations bypass access control checks while still executing hooks and validation.
|
|
18
|
+
|
|
19
|
+
Comprehensive tests have been added to `packages/core/tests/sudo.test.ts` to verify nested operations work correctly in sudo mode.
|
|
20
|
+
|
|
21
|
+
Fixes #134
|
|
22
|
+
|
|
23
|
+
- [#172](https://github.com/OpenSaasAU/stack/pull/172) [`929a2a9`](https://github.com/OpenSaasAU/stack/commit/929a2a9a2dfa80b1d973d259dd87828d644ea58d) Thanks [@list<Lists.User.TypeInfo>({](https://github.com/list<Lists.User.TypeInfo>({), [@list<Lists.User.TypeInfo>({](https://github.com/list<Lists.User.TypeInfo>({)! - Improve TypeScript type inference for field configs and list-level hooks by automatically passing TypeInfo from list level down
|
|
24
|
+
|
|
25
|
+
This change eliminates the need to manually specify type parameters on field builders when using features like virtual fields, and fixes a critical bug where list-level hooks weren't receiving properly typed parameters.
|
|
26
|
+
|
|
27
|
+
## Field Type Inference Improvements
|
|
28
|
+
|
|
29
|
+
Previously, users had to write `virtual<Lists.User.TypeInfo>({...})` to get proper type inference. Now TypeScript automatically infers the correct types from the list-level type parameter.
|
|
30
|
+
|
|
31
|
+
**Example:**
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// Before
|
|
35
|
+
|
|
36
|
+
fields: {
|
|
37
|
+
displayName: virtual<Lists.User.TypeInfo>({
|
|
38
|
+
type: 'string',
|
|
39
|
+
hooks: {
|
|
40
|
+
resolveOutput: ({ item }) => `${item.name} (${item.email})`,
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
// After
|
|
47
|
+
|
|
48
|
+
fields: {
|
|
49
|
+
displayName: virtual({
|
|
50
|
+
type: 'string',
|
|
51
|
+
hooks: {
|
|
52
|
+
resolveOutput: ({ item }) => `${item.name} (${item.email})`,
|
|
53
|
+
},
|
|
54
|
+
}),
|
|
55
|
+
},
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## List-Level Hooks Type Inference Fix
|
|
60
|
+
|
|
61
|
+
Fixed a critical type parameter mismatch where `Hooks<TTypeInfo>` was passing the entire TypeInfo object as the first parameter instead of properly destructuring it into three required parameters:
|
|
62
|
+
1. `TOutput` - The item type (what's stored in DB)
|
|
63
|
+
2. `TCreateInput` - Prisma create input type
|
|
64
|
+
3. `TUpdateInput` - Prisma update input type
|
|
65
|
+
|
|
66
|
+
**Impact:**
|
|
67
|
+
- `resolveInput` now receives proper Prisma input types (e.g., `PostCreateInput`, `PostUpdateInput`)
|
|
68
|
+
- `validateInput` has access to properly typed input data
|
|
69
|
+
- `beforeOperation` and `afterOperation` have correct item types
|
|
70
|
+
- All list-level hook callbacks now get full IntelliSense and type checking
|
|
71
|
+
|
|
72
|
+
**Example:**
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
Post: list<Lists.Post.TypeInfo>({
|
|
76
|
+
fields: { title: text(), content: text() },
|
|
77
|
+
hooks: {
|
|
78
|
+
resolveInput: async ({ operation, resolvedData }) => {
|
|
79
|
+
// ✅ resolvedData is now properly typed as PostCreateInput or PostUpdateInput
|
|
80
|
+
// ✅ Full autocomplete for title, content, etc.
|
|
81
|
+
if (operation === 'create') {
|
|
82
|
+
console.log(resolvedData.title) // TypeScript knows this is string | undefined
|
|
83
|
+
}
|
|
84
|
+
return resolvedData
|
|
85
|
+
},
|
|
86
|
+
beforeOperation: async ({ operation, item }) => {
|
|
87
|
+
// ✅ item is now properly typed as Post with all fields
|
|
88
|
+
if (operation === 'update' && item) {
|
|
89
|
+
console.log(item.title) // TypeScript knows this is string
|
|
90
|
+
console.log(item.createdAt) // TypeScript knows this is Date
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Breaking Changes
|
|
98
|
+
- Field types now accept full `TTypeInfo extends TypeInfo` instead of just `TItem`
|
|
99
|
+
- `FieldsWithItemType` utility replaced with `FieldsWithTypeInfo`
|
|
100
|
+
- All field builders updated to use new type signature
|
|
101
|
+
- List-level hooks now receive properly typed parameters (may reveal existing type errors)
|
|
102
|
+
|
|
103
|
+
## Benefits
|
|
104
|
+
- ✨ Cleaner code without manual type parameter repetition
|
|
105
|
+
- 🎯 Better type inference in both field-level and list-level hooks
|
|
106
|
+
- 🔄 Consistent type flow from list configuration down to individual fields
|
|
107
|
+
- 🛡️ Maintained full type safety with improved DX
|
|
108
|
+
- 💡 Full IntelliSense support in all hook callbacks
|
|
109
|
+
|
|
110
|
+
- [#170](https://github.com/OpenSaasAU/stack/pull/170) [`3c4db9d`](https://github.com/OpenSaasAU/stack/commit/3c4db9d8318fc73d291991d8bdfa4f607c3a50ea) Thanks [@list({](https://github.com/list({)! - Add support for virtual fields with proper TypeScript type generation
|
|
111
|
+
|
|
112
|
+
Virtual fields are computed fields that don't exist in the database but are added to query results at runtime. This feature enables derived or computed values to be included in your API responses with full type safety.
|
|
113
|
+
|
|
114
|
+
**New Features:**
|
|
115
|
+
- Added `virtual()` field type for defining computed fields in your schema
|
|
116
|
+
- Virtual fields are automatically excluded from database schema and input types
|
|
117
|
+
- Virtual fields appear in output types with full TypeScript autocomplete
|
|
118
|
+
- Virtual fields support `resolveOutput` hooks for custom computation logic
|
|
119
|
+
|
|
120
|
+
**Type System Improvements:**
|
|
121
|
+
- Generated Context type now properly extends AccessContext from core
|
|
122
|
+
- Separate Input and Output types (e.g., `UserOutput` includes virtual fields, `UserCreateInput` does not)
|
|
123
|
+
- UI components now accept `AccessContext<any>` for better compatibility with custom context types
|
|
124
|
+
- Type aliases provide convenience (e.g., `User = UserOutput`)
|
|
125
|
+
|
|
126
|
+
**Example Usage:**
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { list, text, virtual } from '@opensaas/stack-core'
|
|
130
|
+
|
|
131
|
+
export default config({
|
|
132
|
+
lists: {
|
|
133
|
+
|
|
134
|
+
fields: {
|
|
135
|
+
name: text(),
|
|
136
|
+
email: text(),
|
|
137
|
+
displayName: virtual({
|
|
138
|
+
type: 'string',
|
|
139
|
+
hooks: {
|
|
140
|
+
resolveOutput: async ({ item }) => {
|
|
141
|
+
return `${item.name} (${item.email})`
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The `displayName` field will automatically appear in query results with full TypeScript support, but won't be part of create/update operations or the database schema.
|
|
152
|
+
|
|
153
|
+
## 0.3.0
|
|
154
|
+
|
|
155
|
+
## 0.2.0
|
|
156
|
+
|
|
157
|
+
### Minor Changes
|
|
158
|
+
|
|
159
|
+
- [#132](https://github.com/OpenSaasAU/stack/pull/132) [`fcf5cb8`](https://github.com/OpenSaasAU/stack/commit/fcf5cb8bbd55d802350b8d97e342dd7f6368163b) Thanks [@borisno2](https://github.com/borisno2)! - Upgrade to Prisma 7 with database adapter support
|
|
160
|
+
|
|
161
|
+
## Breaking Changes
|
|
162
|
+
|
|
163
|
+
### Required `prismaClientConstructor`
|
|
164
|
+
|
|
165
|
+
Prisma 7 requires database adapters. All configs must now include `prismaClientConstructor`:
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
import { PrismaBetterSQLite3 } from '@prisma/adapter-better-sqlite3'
|
|
169
|
+
import Database from 'better-sqlite3'
|
|
170
|
+
|
|
171
|
+
export default config({
|
|
172
|
+
db: {
|
|
173
|
+
provider: 'sqlite',
|
|
174
|
+
prismaClientConstructor: (PrismaClient) => {
|
|
175
|
+
const db = new Database(process.env.DATABASE_URL || './dev.db')
|
|
176
|
+
const adapter = new PrismaBetterSQLite3(db)
|
|
177
|
+
return new PrismaClient({ adapter })
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Removed `url` from `DatabaseConfig`
|
|
184
|
+
|
|
185
|
+
The `url` field has been removed from the `DatabaseConfig` type. Database connection URLs are now passed directly to adapters in `prismaClientConstructor`:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// ❌ Before (Prisma 6)
|
|
189
|
+
db: {
|
|
190
|
+
provider: 'sqlite',
|
|
191
|
+
url: 'file:./dev.db', // url in config
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// ✅ After (Prisma 7)
|
|
195
|
+
db: {
|
|
196
|
+
provider: 'sqlite',
|
|
197
|
+
prismaClientConstructor: (PrismaClient) => {
|
|
198
|
+
const adapter = new PrismaBetterSQLite3({ url: './dev.db' }) // url in adapter
|
|
199
|
+
return new PrismaClient({ adapter })
|
|
200
|
+
},
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Generated Schema Changes
|
|
205
|
+
- Generator provider changed from `prisma-client-js` to `prisma-client`
|
|
206
|
+
- Removed `url` field from datasource block
|
|
207
|
+
- Database URL now passed via adapter in `prismaClientConstructor`
|
|
208
|
+
|
|
209
|
+
### Required Dependencies
|
|
210
|
+
|
|
211
|
+
Install the appropriate adapter for your database:
|
|
212
|
+
- **SQLite**: `@prisma/adapter-better-sqlite3` + `better-sqlite3`
|
|
213
|
+
- **PostgreSQL**: `@prisma/adapter-pg` + `pg`
|
|
214
|
+
- **MySQL**: `@prisma/adapter-mysql` + `mysql2`
|
|
215
|
+
|
|
216
|
+
## Migration Steps
|
|
217
|
+
1. Install Prisma 7 and adapter:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
pnpm add @prisma/client@7 @prisma/adapter-better-sqlite3 better-sqlite3
|
|
221
|
+
pnpm add -D prisma@7
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
2. Update your `opensaas.config.ts` to include `prismaClientConstructor` (see example above)
|
|
225
|
+
3. Regenerate schema and client:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
pnpm generate
|
|
229
|
+
npx prisma generate
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
4. Push schema to database:
|
|
233
|
+
```bash
|
|
234
|
+
pnpm db:push
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
See the updated documentation in CLAUDE.md for more examples including PostgreSQL and custom adapters.
|
|
238
|
+
|
|
239
|
+
- [#121](https://github.com/OpenSaasAU/stack/pull/121) [`3851a3c`](https://github.com/OpenSaasAU/stack/commit/3851a3cf72e78dc6f01a73c6fff97deca6fad043) Thanks [@borisno2](https://github.com/borisno2)! - Add strongly-typed session support via module augmentation
|
|
240
|
+
|
|
241
|
+
This change enables developers to define custom session types with full TypeScript autocomplete and type safety throughout their OpenSaas applications using the module augmentation pattern.
|
|
242
|
+
|
|
243
|
+
**Core Changes:**
|
|
244
|
+
- Converted `Session` from `type` to `interface` to enable module augmentation
|
|
245
|
+
- Updated all session references to properly handle `Session | null`
|
|
246
|
+
- Added comprehensive JSDoc documentation with module augmentation examples
|
|
247
|
+
- Updated `AccessControl`, `AccessContext`, and access control engine to support nullable sessions
|
|
248
|
+
- Added "Session Typing" section to core package documentation
|
|
249
|
+
|
|
250
|
+
**Auth Package:**
|
|
251
|
+
- Added "Session Type Safety" section to documentation
|
|
252
|
+
- Documented how Better Auth users can create session type declarations
|
|
253
|
+
- Provided step-by-step guide for matching sessionFields to TypeScript types
|
|
254
|
+
- Created `getSession()` helper pattern for transforming Better Auth sessions
|
|
255
|
+
|
|
256
|
+
**Developer Experience:**
|
|
257
|
+
|
|
258
|
+
Developers can now augment the `Session` interface to get autocomplete everywhere:
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
// types/session.d.ts
|
|
262
|
+
import '@opensaas/stack-core'
|
|
263
|
+
|
|
264
|
+
declare module '@opensaas/stack-core' {
|
|
265
|
+
interface Session {
|
|
266
|
+
userId?: string
|
|
267
|
+
email?: string
|
|
268
|
+
role?: 'admin' | 'user'
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
This provides autocomplete in:
|
|
274
|
+
- Access control functions
|
|
275
|
+
- Hooks (resolveInput, validateInput, etc.)
|
|
276
|
+
- Context object
|
|
277
|
+
- Server actions
|
|
278
|
+
|
|
279
|
+
**Benefits:**
|
|
280
|
+
- Zero boilerplate - module augmentation provides types everywhere automatically
|
|
281
|
+
- Full type safety for session properties
|
|
282
|
+
- Autocomplete in all contexts that use session
|
|
283
|
+
- Developer controls session shape (no assumptions about structure)
|
|
284
|
+
- Works with any auth provider (Better Auth, custom, etc.)
|
|
285
|
+
- Fully backward compatible - existing code continues to work
|
|
286
|
+
- Follows TypeScript best practices (similar to NextAuth.js pattern)
|
|
287
|
+
|
|
288
|
+
**Example:**
|
|
289
|
+
|
|
290
|
+
```typescript
|
|
291
|
+
// Before: No autocomplete
|
|
292
|
+
const isAdmin: AccessControl = ({ session }) => {
|
|
293
|
+
return session?.role === 'admin' // ❌ 'role' is 'unknown'
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// After: Full autocomplete and type checking
|
|
297
|
+
const isAdmin: AccessControl = ({ session }) => {
|
|
298
|
+
return session?.role === 'admin' // ✅ Autocomplete + type checking
|
|
299
|
+
// ↑ Shows: userId, email, role
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
**Migration:**
|
|
304
|
+
|
|
305
|
+
No migration required - this is a fully backward compatible change. Existing projects continue to work with untyped sessions. Projects can opt-in to typed sessions by creating a `types/session.d.ts` file with module augmentation.
|
|
306
|
+
|
|
307
|
+
### Patch Changes
|
|
308
|
+
|
|
309
|
+
- [#107](https://github.com/OpenSaasAU/stack/pull/107) [`f4f3966`](https://github.com/OpenSaasAU/stack/commit/f4f3966faedba07d2cf412fab826d81e30c63a6c) Thanks [@borisno2](https://github.com/borisno2)! - Add strict typing for plugin runtime services
|
|
310
|
+
|
|
311
|
+
This change implements fully typed plugin runtime services, providing autocomplete and type safety for `context.plugins` throughout the codebase.
|
|
312
|
+
|
|
313
|
+
**Core Changes:**
|
|
314
|
+
- Extended `Plugin` type with optional `runtimeServiceTypes` metadata for type-safe code generation
|
|
315
|
+
- Converted `OpenSaasConfig` and `AccessContext` from `type` to `interface` to enable module augmentation
|
|
316
|
+
- Plugins can now declare their runtime service type information
|
|
317
|
+
|
|
318
|
+
**Auth Plugin:**
|
|
319
|
+
- Added `AuthRuntimeServices` interface defining runtime service types
|
|
320
|
+
- Exported runtime types from package
|
|
321
|
+
- Users now get full autocomplete for `context.plugins.auth.getUser()` and `context.plugins.auth.getCurrentUser()`
|
|
322
|
+
|
|
323
|
+
**RAG Plugin:**
|
|
324
|
+
- Added `RAGRuntimeServices` interface defining runtime service types
|
|
325
|
+
- Exported runtime types from package
|
|
326
|
+
- Users now get full autocomplete for `context.plugins.rag.generateEmbedding()` and `context.plugins.rag.generateEmbeddings()`
|
|
327
|
+
|
|
328
|
+
**CLI Generator:**
|
|
329
|
+
- Enhanced plugin types generator to import and use plugin runtime service types
|
|
330
|
+
- Generated `.opensaas/plugin-types.ts` now includes proper type imports
|
|
331
|
+
- `PluginServices` interface extends `Record<string, Record<string, any> | undefined>` for type compatibility
|
|
332
|
+
- Maintains backwards compatibility with plugins that don't provide type metadata
|
|
333
|
+
|
|
334
|
+
**UI Package:**
|
|
335
|
+
- Updated `AdminUI` props to accept contexts with typed plugin services
|
|
336
|
+
- Ensures compatibility between generated context types and UI components
|
|
337
|
+
|
|
338
|
+
**Benefits:**
|
|
339
|
+
- Full TypeScript autocomplete for all plugin runtime methods
|
|
340
|
+
- Compile-time type checking catches errors early
|
|
341
|
+
- Better IDE experience with hover documentation and jump-to-definition
|
|
342
|
+
- Backwards compatible - third-party plugins without type metadata continue to work
|
|
343
|
+
- Zero type errors in examples
|
|
344
|
+
|
|
345
|
+
**Example:**
|
|
346
|
+
|
|
347
|
+
```typescript
|
|
348
|
+
const context = await getContext()
|
|
349
|
+
|
|
350
|
+
// Fully typed with autocomplete
|
|
351
|
+
context.plugins.auth.getUser('123') // (userId: string) => Promise<unknown>
|
|
352
|
+
context.plugins.rag.generateEmbedding('text') // (text: string, providerName?: string) => Promise<number[]>
|
|
353
|
+
```
|
|
354
|
+
|
|
3
355
|
## 0.1.7
|
|
4
356
|
|
|
5
357
|
### Patch Changes
|
package/CLAUDE.md
CHANGED
|
@@ -35,13 +35,58 @@ Built-in fields:
|
|
|
35
35
|
### Access Control (`src/access/`)
|
|
36
36
|
|
|
37
37
|
- `engine.ts` - Core execution logic (`applyAccessControl()`)
|
|
38
|
-
- `types.ts` - Type definitions (`AccessControl`, `OperationAccessControl`, etc.)
|
|
38
|
+
- `types.ts` - Type definitions (`AccessControl`, `OperationAccessControl`, `Session`, etc.)
|
|
39
39
|
|
|
40
40
|
Access control functions receive `{ session, context, item, operation }` and return:
|
|
41
41
|
|
|
42
42
|
- `boolean` - Allow/deny
|
|
43
43
|
- `Prisma filter object` - Scope access to matching records
|
|
44
44
|
|
|
45
|
+
### Session Typing (`src/access/types.ts`)
|
|
46
|
+
|
|
47
|
+
The `Session` interface can be augmented to provide type safety and autocomplete for session fields.
|
|
48
|
+
|
|
49
|
+
**Default:** Session is a permissive object: `interface Session { [key: string]: unknown }`
|
|
50
|
+
|
|
51
|
+
**Module Augmentation Pattern:**
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
// types/session.d.ts (create this file in your project)
|
|
55
|
+
import '@opensaas/stack-core'
|
|
56
|
+
|
|
57
|
+
declare module '@opensaas/stack-core' {
|
|
58
|
+
interface Session {
|
|
59
|
+
userId: string
|
|
60
|
+
email: string
|
|
61
|
+
role: 'admin' | 'user'
|
|
62
|
+
organizationId?: string
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Benefits:**
|
|
68
|
+
|
|
69
|
+
- Autocomplete in access control functions
|
|
70
|
+
- Type safety when accessing session properties
|
|
71
|
+
- Single source of truth for session shape
|
|
72
|
+
- Works with any auth provider (Better Auth, custom, etc.)
|
|
73
|
+
|
|
74
|
+
**Usage after augmentation:**
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
// Access control - fully typed
|
|
78
|
+
const isAdmin: AccessControl = ({ session }) => {
|
|
79
|
+
return session?.role === 'admin' // ✅ 'role' is typed as 'admin' | 'user'
|
|
80
|
+
// ↑ Autocomplete shows: userId, email, role, organizationId
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// In server actions
|
|
84
|
+
const context = await getContext(session)
|
|
85
|
+
context.session?.email // ✅ Typed as string
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**For Better Auth users:** See `@opensaas/stack-auth` documentation for examples of extracting Better Auth session types.
|
|
89
|
+
|
|
45
90
|
### Hooks (`src/hooks/`)
|
|
46
91
|
|
|
47
92
|
- `index.ts` - Hook execution logic
|
package/dist/access/engine.d.ts
CHANGED
|
@@ -19,13 +19,13 @@ export declare function isPrismaFilter(value: unknown): value is PrismaFilter;
|
|
|
19
19
|
*/
|
|
20
20
|
export declare function getRelatedListConfig(relationshipRef: string, config: OpenSaasConfig): {
|
|
21
21
|
listName: string;
|
|
22
|
-
listConfig: ListConfig
|
|
22
|
+
listConfig: ListConfig<any>;
|
|
23
23
|
} | null;
|
|
24
24
|
/**
|
|
25
25
|
* Execute an access control function
|
|
26
26
|
*/
|
|
27
27
|
export declare function checkAccess<T = Record<string, unknown>>(accessControl: AccessControl<T> | undefined, args: {
|
|
28
|
-
session: Session;
|
|
28
|
+
session: Session | null;
|
|
29
29
|
item?: T;
|
|
30
30
|
context: AccessContext;
|
|
31
31
|
}): Promise<boolean | PrismaFilter<T>>;
|
|
@@ -37,7 +37,7 @@ export declare function mergeFilters(userFilter: PrismaFilter | undefined, acces
|
|
|
37
37
|
* Check field-level access for a specific operation
|
|
38
38
|
*/
|
|
39
39
|
export declare function checkFieldAccess(fieldAccess: FieldAccess | undefined, operation: 'read' | 'create' | 'update', args: {
|
|
40
|
-
session: Session;
|
|
40
|
+
session: Session | null;
|
|
41
41
|
item?: Record<string, unknown>;
|
|
42
42
|
context: AccessContext & {
|
|
43
43
|
_isSudo?: boolean;
|
|
@@ -48,7 +48,7 @@ export declare function checkFieldAccess(fieldAccess: FieldAccess | undefined, o
|
|
|
48
48
|
* This allows us to filter relationships at the database level instead of in memory
|
|
49
49
|
*/
|
|
50
50
|
export declare function buildIncludeWithAccessControl(fieldConfigs: Record<string, FieldConfig>, args: {
|
|
51
|
-
session: Session;
|
|
51
|
+
session: Session | null;
|
|
52
52
|
context: AccessContext;
|
|
53
53
|
}, config: OpenSaasConfig, depth?: number): Promise<Record<string, boolean | {
|
|
54
54
|
where?: PrismaFilter;
|
|
@@ -59,7 +59,7 @@ export declare function buildIncludeWithAccessControl(fieldConfigs: Record<strin
|
|
|
59
59
|
* Recursively applies access control to nested relationships
|
|
60
60
|
*/
|
|
61
61
|
export declare function filterReadableFields<T extends Record<string, unknown>>(item: T, fieldConfigs: Record<string, FieldConfig>, args: {
|
|
62
|
-
session: Session;
|
|
62
|
+
session: Session | null;
|
|
63
63
|
context: AccessContext & {
|
|
64
64
|
_isSudo?: boolean;
|
|
65
65
|
};
|
|
@@ -69,8 +69,9 @@ export declare function filterReadableFields<T extends Record<string, unknown>>(
|
|
|
69
69
|
*/
|
|
70
70
|
export declare function filterWritableFields<T extends Record<string, unknown>>(data: T, fieldConfigs: Record<string, {
|
|
71
71
|
access?: FieldAccess;
|
|
72
|
+
type?: string;
|
|
72
73
|
}>, operation: 'create' | 'update', args: {
|
|
73
|
-
session: Session;
|
|
74
|
+
session: Session | null;
|
|
74
75
|
item?: Record<string, unknown>;
|
|
75
76
|
context: AccessContext & {
|
|
76
77
|
_isSudo?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/access/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAejF;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/access/engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAC7C,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAejF;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,OAAO,CAE1D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,YAAY,CAEpE;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,cAAc,GAErB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,CAAA;CAAE,GAAG,IAAI,CAe1D;AAED;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS,EAC3C,IAAI,EAAE;IACJ,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,IAAI,CAAC,EAAE,CAAC,CAAA;IACR,OAAO,EAAE,aAAa,CAAA;CACvB,GACA,OAAO,CAAC,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAUpC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,UAAU,EAAE,YAAY,GAAG,SAAS,EACpC,YAAY,EAAE,OAAO,GAAG,YAAY,GACnC,YAAY,GAAG,IAAI,CAoBrB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,WAAW,GAAG,SAAS,EACpC,SAAS,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,EACvC,IAAI,EAAE;IACJ,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,OAAO,EAAE,aAAa,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC/C,GACA,OAAO,CAAC,OAAO,CAAC,CAmClB;AA8BD;;;GAGG;AACH,wBAAsB,6BAA6B,CACjD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACzC,IAAI,EAAE;IACJ,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,aAAa,CAAA;CACvB,EACD,MAAM,EAAE,cAAc,EACtB,KAAK,GAAE,MAAU;YAOuB,YAAY;cAAY,MAAM,CAAC,MAAM,2BAAe;gBAkD7F;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,IAAI,EAAE,CAAC,EACP,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,EACzC,IAAI,EAAE;IACJ,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,aAAa,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC/C,EACD,MAAM,CAAC,EAAE,cAAc,EACvB,KAAK,GAAE,MAAU,EACjB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAiIrB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC1E,IAAI,EAAE,CAAC,EACP,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACrE,SAAS,EAAE,QAAQ,GAAG,QAAQ,EAC9B,IAAI,EAAE;IACJ,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,OAAO,EAAE,aAAa,GAAG;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAC/C,GACA,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CA+CrB"}
|
package/dist/access/engine.js
CHANGED
|
@@ -176,6 +176,7 @@ export async function buildIncludeWithAccessControl(fieldConfigs, args, config,
|
|
|
176
176
|
export async function filterReadableFields(item, fieldConfigs, args, config, depth = 0, listKey) {
|
|
177
177
|
const filtered = {};
|
|
178
178
|
const MAX_DEPTH = 5; // Prevent infinite recursion
|
|
179
|
+
// Process existing fields from the database result
|
|
179
180
|
for (const [fieldName, value] of Object.entries(item)) {
|
|
180
181
|
const fieldConfig = fieldConfigs[fieldName];
|
|
181
182
|
// Always include id, createdAt, updatedAt
|
|
@@ -239,6 +240,38 @@ export async function filterReadableFields(item, fieldConfigs, args, config, dep
|
|
|
239
240
|
}
|
|
240
241
|
}
|
|
241
242
|
}
|
|
243
|
+
// Process virtual fields - compute values from other fields
|
|
244
|
+
// Virtual fields don't exist in the database result, so we need to compute them separately
|
|
245
|
+
for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
|
|
246
|
+
// Skip if already processed (from database result)
|
|
247
|
+
if (fieldName in filtered) {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
// Only process virtual fields
|
|
251
|
+
if (!fieldConfig.virtual) {
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
// Check field access
|
|
255
|
+
const canRead = await checkFieldAccess(fieldConfig.access, 'read', {
|
|
256
|
+
...args,
|
|
257
|
+
item,
|
|
258
|
+
});
|
|
259
|
+
if (!canRead) {
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
// Virtual fields must have resolveOutput hook to compute their value
|
|
263
|
+
if (fieldConfig.hooks?.resolveOutput && listKey) {
|
|
264
|
+
const hook = fieldConfig.hooks.resolveOutput;
|
|
265
|
+
filtered[fieldName] = hook({
|
|
266
|
+
value: undefined, // Virtual fields don't have a database value
|
|
267
|
+
operation: 'query',
|
|
268
|
+
fieldName,
|
|
269
|
+
listKey,
|
|
270
|
+
item: filtered, // Pass filtered item so virtual field can access other fields
|
|
271
|
+
context: args.context,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
242
275
|
return filtered;
|
|
243
276
|
}
|
|
244
277
|
/**
|
|
@@ -246,12 +279,34 @@ export async function filterReadableFields(item, fieldConfigs, args, config, dep
|
|
|
246
279
|
*/
|
|
247
280
|
export async function filterWritableFields(data, fieldConfigs, operation, args) {
|
|
248
281
|
const filtered = {};
|
|
282
|
+
// Build a set of foreign key field names to exclude
|
|
283
|
+
// Foreign keys should not be in the data when using Prisma's relation syntax
|
|
284
|
+
const foreignKeyFields = new Set();
|
|
285
|
+
for (const [fieldName, fieldConfig] of Object.entries(fieldConfigs)) {
|
|
286
|
+
if (fieldConfig.type === 'relationship') {
|
|
287
|
+
// For non-many relationships, Prisma creates a foreign key field named `${fieldName}Id`
|
|
288
|
+
const relConfig = fieldConfig;
|
|
289
|
+
if (!relConfig.many) {
|
|
290
|
+
foreignKeyFields.add(`${fieldName}Id`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
249
294
|
for (const [fieldName, value] of Object.entries(data)) {
|
|
250
295
|
const fieldConfig = fieldConfigs[fieldName];
|
|
251
296
|
// Skip system fields
|
|
252
297
|
if (['id', 'createdAt', 'updatedAt'].includes(fieldName)) {
|
|
253
298
|
continue;
|
|
254
299
|
}
|
|
300
|
+
// Skip virtual fields - they don't store in database
|
|
301
|
+
// Virtual fields with resolveInput hooks handle side effects separately
|
|
302
|
+
if (fieldConfig && 'virtual' in fieldConfig && fieldConfig.virtual) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
// Skip foreign key fields (e.g., authorId) when their corresponding relationship field exists
|
|
306
|
+
// This prevents conflicts when using Prisma's relation syntax (e.g., author: { connect: { id } })
|
|
307
|
+
if (foreignKeyFields.has(fieldName)) {
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
255
310
|
// Check field access (checkFieldAccess already handles sudo mode)
|
|
256
311
|
const canWrite = await checkFieldAccess(fieldConfig?.access, operation, {
|
|
257
312
|
...args,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/access/engine.ts"],"names":[],"mappings":"AAiBA;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAA;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,eAAuB,EACvB,MAAsB;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/access/engine.ts"],"names":[],"mappings":"AAiBA;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAc;IACtC,OAAO,OAAO,KAAK,KAAK,SAAS,CAAA;AACnC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAClC,eAAuB,EACvB,MAAsB;IAGtB,yCAAyC;IACzC,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACzB,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAEzC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,aAA2C,EAC3C,IAIC;IAED,0CAA0C;IAC1C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,sCAAsC;IACtC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;IAExC,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,UAAoC,EACpC,YAAoC;IAEpC,mCAAmC;IACnC,IAAI,YAAY,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,8CAA8C;IAC9C,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;QAC1B,OAAO,UAAU,IAAI,EAAE,CAAA;IACzB,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,2BAA2B;IAC3B,OAAO;QACL,GAAG,EAAE,CAAC,YAAY,EAAE,UAAU,CAAC;KAChC,CAAA;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAoC,EACpC,SAAuC,EACvC,IAIC;IAED,iCAAiC;IACjC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACzB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,IAAI,CAAA,CAAC,8BAA8B;IAC5C,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;IAC5C,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,IAAI,CAAA,CAAC,yCAAyC;IACvD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,IAAI,CAAC,CAAA;IAExC,kCAAkC;IAClC,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;QACrB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,kCAAkC;IAClC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,0DAA0D;IAC1D,0EAA0E;IAC1E,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACzC,CAAC;IAED,mDAAmD;IACnD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,SAAS,aAAa,CAAC,IAA6B,EAAE,MAA+B;IACnF,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;YACxD,kDAAkD;YAClD,IAAI,QAAQ,IAAI,SAAS,EAAE,CAAC;gBAC1B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,MAAM,EAAE,CAAC;oBACnC,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;gBAC9B,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,GAAG,EAAE,CAAC;oBAChC,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;YACD,qCAAqC;QACvC,CAAC;aAAM,CAAC;YACN,wBAAwB;YACxB,IAAI,IAAI,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAA;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,6BAA6B,CACjD,YAAyC,EACzC,IAGC,EACD,MAAsB,EACtB,QAAgB,CAAC;IAEjB,MAAM,SAAS,GAAG,CAAC,CAAA;IACnB,IAAI,KAAK,IAAI,SAAS,EAAE,CAAC;QACvB,OAAO,SAAS,CAAA;IAClB,CAAC;IAID,MAAM,OAAO,GAAiC,EAAE,CAAA;IAChD,IAAI,gBAAgB,GAAG,KAAK,CAAA;IAE5B,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,IAAI,WAAW,EAAE,IAAI,KAAK,cAAc,IAAI,KAAK,IAAI,WAAW,IAAI,WAAW,CAAC,GAAG,EAAE,CAAC;YACpF,gBAAgB,GAAG,IAAI,CAAA;YACvB,MAAM,aAAa,GAAG,oBAAoB,CAAC,WAAW,CAAC,GAAa,EAAE,MAAM,CAAC,CAAA;YAE7E,IAAI,aAAa,EAAE,CAAC;gBAClB,0CAA0C;gBAC1C,MAAM,WAAW,GAAG,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAA;gBACrE,MAAM,YAAY,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE;oBAClD,OAAO,EAAE,IAAI,CAAC,OAAO;oBACrB,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC,CAAA;gBAEF,4DAA4D;gBAC5D,IAAI,YAAY,KAAK,KAAK,EAAE,CAAC;oBAC3B,SAAQ;gBACV,CAAC;gBAED,0BAA0B;gBAC1B,MAAM,YAAY,GAA4B,EAAE,CAAA;gBAEhD,yDAAyD;gBACzD,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;oBACrC,YAAY,CAAC,KAAK,GAAG,YAAY,CAAA;gBACnC,CAAC;gBAED,oCAAoC;gBACpC,MAAM,aAAa,GAAG,MAAM,6BAA6B,CACvD,aAAa,CAAC,UAAU,CAAC,MAAM,EAC/B,IAAI,EACJ,MAAM,EACN,KAAK,GAAG,CAAC,CACV,CAAA;gBAED,IAAI,aAAa,IAAI,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC3D,YAAY,CAAC,OAAO,GAAG,aAAa,CAAA;gBACtC,CAAC;gBAED,wBAAwB;gBACxB,OAAO,CAAC,SAAS,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAA;YACjF,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC/C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAO,EACP,YAAyC,EACzC,IAGC,EACD,MAAuB,EACvB,QAAgB,CAAC,EACjB,OAAgB;IAEhB,MAAM,QAAQ,GAA4B,EAAE,CAAA;IAC5C,MAAM,SAAS,GAAG,CAAC,CAAA,CAAC,6BAA6B;IAEjD,mDAAmD;IACnD,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,WAAW,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QAE3C,0CAA0C;QAC1C,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACzD,QAAQ,CAAC,SAAS,CAAC,GAAG,KAAK,CAAA;YAC3B,SAAQ;QACV,CAAC;QAED,kEAAkE;QAClE,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE;YAClE,GAAG,IAAI;YACP,IAAI;SACL,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,SAAQ;QACV,CAAC;QAED,8EAA8E;QAC9E,iGAAiG;QACjG,iEAAiE;QACjE,IACE,MAAM;YACN,WAAW,EAAE,IAAI,KAAK,cAAc;YACpC,KAAK,IAAI,WAAW;YACpB,WAAW,CAAC,GAAG;YACf,KAAK,KAAK,IAAI;YACd,KAAK,KAAK,SAAS;YACnB,KAAK,GAAG,SAAS,EACjB,CAAC;YACD,MAAM,aAAa,GAAG,oBAAoB,CAAC,WAAW,CAAC,GAAa,EAAE,MAAM,CAAC,CAAA;YAE7E,IAAI,aAAa,EAAE,CAAC;gBAClB,2EAA2E;gBAC3E,kEAAkE;gBAClE,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;oBACzB,QAAQ,CAAC,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CACrC,KAAK,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CACxB,oBAAoB,CAClB,WAAW,EACX,aAAa,CAAC,UAAU,CAAC,MAAM,EAC/B,IAAI,EACJ,MAAM,EACN,KAAK,GAAG,CAAC,EACT,aAAa,CAAC,QAAQ,CACvB,CACF,CACF,CAAA;gBACH,CAAC;gBACD,iEAAiE;gBACjE,kEAAkE;qBAC7D,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;oBACnC,QAAQ,CAAC,SAAS,CAAC,GAAG,MAAM,oBAAoB,CAC9C,KAAgC,EAChC,aAAa,CAAC,UAAU,CAAC,MAAM,EAC/B,IAAI,EACJ,MAAM,EACN,KAAK,GAAG,CAAC,EACT,aAAa,CAAC,QAAQ,CACvB,CAAA;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,oDAAoD;gBACpD,QAAQ,CAAC,SAAS,CAAC,GAAG,KAAK,CAAA;YAC7B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,qFAAqF;YACrF,IAAI,WAAW,EAAE,KAAK,EAAE,aAAa,IAAI,OAAO,EAAE,CAAC;gBACjD,6CAA6C;gBAC7C,yEAAyE;gBACzE,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,aAAoD,CAAA;gBACnF,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;oBACzB,KAAK;oBACL,SAAS,EAAE,OAAO;oBAClB,SAAS;oBACT,OAAO;oBACP,IAAI;oBACJ,OAAO,EAAE,IAAI,CAAC,OAAO;iBACtB,CAAC,CAAA;YACJ,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,SAAS,CAAC,GAAG,KAAK,CAAA;YAC7B,CAAC;QACH,CAAC;IACH,CAAC;IAED,4DAA4D;IAC5D,2FAA2F;IAC3F,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,mDAAmD;QACnD,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC1B,SAAQ;QACV,CAAC;QAED,8BAA8B;QAC9B,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,SAAQ;QACV,CAAC;QAED,qBAAqB;QACrB,MAAM,OAAO,GAAG,MAAM,gBAAgB,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE;YACjE,GAAG,IAAI;YACP,IAAI;SACL,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,SAAQ;QACV,CAAC;QAED,qEAAqE;QACrE,IAAI,WAAW,CAAC,KAAK,EAAE,aAAa,IAAI,OAAO,EAAE,CAAC;YAChD,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,CAAC,aAAoD,CAAA;YACnF,QAAQ,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;gBACzB,KAAK,EAAE,SAAS,EAAE,6CAA6C;gBAC/D,SAAS,EAAE,OAAO;gBAClB,SAAS;gBACT,OAAO;gBACP,IAAI,EAAE,QAAQ,EAAE,8DAA8D;gBAC9E,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,QAAsB,CAAA;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAO,EACP,YAAqE,EACrE,SAA8B,EAC9B,IAIC;IAED,MAAM,QAAQ,GAA4B,EAAE,CAAA;IAE5C,oDAAoD;IACpD,6EAA6E;IAC7E,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAA;IAC1C,KAAK,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACpE,IAAI,WAAW,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACxC,wFAAwF;YACxF,MAAM,SAAS,GAAG,WAAiC,CAAA;YACnD,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;gBACpB,gBAAgB,CAAC,GAAG,CAAC,GAAG,SAAS,IAAI,CAAC,CAAA;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACtD,MAAM,WAAW,GAAG,YAAY,CAAC,SAAS,CAAC,CAAA;QAE3C,qBAAqB;QACrB,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YACzD,SAAQ;QACV,CAAC;QAED,qDAAqD;QACrD,wEAAwE;QACxE,IAAI,WAAW,IAAI,SAAS,IAAI,WAAW,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACnE,SAAQ;QACV,CAAC;QAED,8FAA8F;QAC9F,kGAAkG;QAClG,IAAI,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YACpC,SAAQ;QACV,CAAC;QAED,kEAAkE;QAClE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE;YACtE,GAAG,IAAI;SACR,CAAC,CAAA;QAEF,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,SAAS,CAAC,GAAG,KAAK,CAAA;QAC7B,CAAC;IACH,CAAC;IAED,OAAO,QAAsB,CAAA;AAC/B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.test.d.ts","sourceRoot":"","sources":["../../src/access/engine.test.ts"],"names":[],"mappings":""}
|