@stonecrop/nuxt-grafserv 0.7.4 → 0.7.5
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/README.md +308 -63
- package/dist/module.d.mts +1 -34
- package/dist/module.json +2 -2
- package/dist/module.mjs +44 -34
- package/dist/runtime/graphql.d.ts +6 -0
- package/dist/runtime/graphql.js +9 -0
- package/dist/runtime/handler.d.ts +9 -1
- package/dist/runtime/handler.js +26 -70
- package/dist/runtime/ruru-static.d.ts +6 -0
- package/dist/runtime/ruru-static.js +9 -0
- package/dist/runtime/ruru.d.ts +6 -0
- package/dist/runtime/ruru.js +9 -0
- package/dist/types.d.mts +2 -6
- package/package.json +16 -15
package/README.md
CHANGED
|
@@ -3,21 +3,31 @@
|
|
|
3
3
|
[![npm version][npm-version-src]][npm-version-href]
|
|
4
4
|
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
|
5
5
|
[![License][license-src]][license-href]
|
|
6
|
-
[![Nuxt][nuxt-src]][nuxt-href]
|
|
7
6
|
|
|
8
7
|
Pluggable Grafserv GraphQL server as a Nuxt Module. Uses the Grafast execution engine for high-performance GraphQL.
|
|
9
8
|
|
|
10
|
-
- [✨ Release Notes](/CHANGELOG.md)
|
|
11
|
-
|
|
12
9
|
## Features
|
|
13
10
|
|
|
14
11
|
- 🚀 Grafserv Server Integration
|
|
15
|
-
- ⚡️ Grafast Execution Engine (faster than graphql-js)
|
|
12
|
+
- ⚡️ Grafast Execution Engine (faster than [`graphql-js`](https://github.com/graphql/graphql-js))
|
|
16
13
|
- 🔄 Schema Stitching Support
|
|
17
|
-
-
|
|
14
|
+
- 🔍 Graphile Preset System for Advanced Configuration
|
|
18
15
|
- 📝 TypeScript Support
|
|
19
|
-
- 🔍 GraphiQL Interface
|
|
16
|
+
- 🔍 GraphiQL/Ruru Interface
|
|
20
17
|
- ⚡️ Hot Module Reloading
|
|
18
|
+
- 🎯 Separate Route Handlers for GraphQL/UI and Static Assets
|
|
19
|
+
|
|
20
|
+
## Architecture
|
|
21
|
+
|
|
22
|
+
This module uses modern Grafserv patterns with three key components:
|
|
23
|
+
|
|
24
|
+
1. **Preset-Based Configuration**: Leverages Graphile's preset system for extensibility and plugin support
|
|
25
|
+
2. **Separate Route Handlers**: Two dedicated handlers for GraphQL operations/UI and static assets
|
|
26
|
+
3. **Objects Structure**: Uses Grafast's modern `objects/interfaces/enums` schema building pattern for better type safety
|
|
27
|
+
|
|
28
|
+
The module automatically registers these handlers:
|
|
29
|
+
- `{url}` - Unified GraphQL operations and Ruru UI endpoint
|
|
30
|
+
- `/ruru-static/**` - Static assets for the Ruru IDE
|
|
21
31
|
|
|
22
32
|
## Quick Setup
|
|
23
33
|
|
|
@@ -40,48 +50,54 @@ npm install @stonecrop/nuxt-grafserv
|
|
|
40
50
|
export default defineNuxtConfig({
|
|
41
51
|
modules: ['@stonecrop/nuxt-grafserv'],
|
|
42
52
|
grafserv: {
|
|
43
|
-
schema: '
|
|
44
|
-
resolvers: '
|
|
45
|
-
url: '/graphql/',
|
|
53
|
+
schema: 'server/**/*.graphql',
|
|
54
|
+
resolvers: 'server/resolvers.ts',
|
|
55
|
+
url: '/graphql/', // Serves both GraphQL API and Ruru UI
|
|
46
56
|
}
|
|
47
57
|
})
|
|
48
58
|
```
|
|
49
59
|
|
|
50
60
|
## Configuration
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
### All Available Options
|
|
63
|
+
|
|
64
|
+
| Option | Type | Default | Description |
|
|
65
|
+
|--------|------|---------|-------------|
|
|
66
|
+
| `schema` | `string \| string[] \| SchemaProvider` | `'server/**/*.graphql'` | Path(s) to GraphQL schema files or schema provider function |
|
|
67
|
+
| `resolvers` | `string` | `'server/resolvers.ts'` | Path to resolvers file |
|
|
68
|
+
| `url` | `string` | `'/graphql/'` | GraphQL endpoint URL (also serves Ruru UI) |
|
|
69
|
+
| `graphiql` | `boolean` | `true` in dev, `false` in prod | Enable GraphiQL IDE |
|
|
70
|
+
| `preset` | `GraphileConfig.Preset` | `undefined` | Custom Graphile preset for advanced configuration |
|
|
71
|
+
|
|
72
|
+
### Full Configuration Example
|
|
53
73
|
|
|
54
74
|
```ts
|
|
55
75
|
export default defineNuxtConfig({
|
|
56
76
|
modules: ['@stonecrop/nuxt-grafserv'],
|
|
57
77
|
grafserv: {
|
|
58
|
-
//
|
|
59
|
-
schema: '
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// GraphQL endpoint URL (default: /graphql/)
|
|
65
|
-
url: '/graphql/',
|
|
66
|
-
|
|
67
|
-
// Enable GraphiQL IDE (default: true in dev, false in prod)
|
|
78
|
+
// Schema configuration
|
|
79
|
+
schema: 'server/**/*.graphql',
|
|
80
|
+
resolvers: 'server/resolvers.ts',
|
|
81
|
+
|
|
82
|
+
// Endpoints
|
|
83
|
+
url: '/graphql/', // Serves both GraphQL API and Ruru UI
|
|
68
84
|
graphiql: true,
|
|
69
|
-
|
|
70
|
-
//
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
|
|
86
|
+
// Graphile preset with grafserv options
|
|
87
|
+
preset: {
|
|
88
|
+
grafserv: {
|
|
89
|
+
websockets: false,
|
|
90
|
+
graphqlOverGET: true, // Enable GET requests for queries
|
|
91
|
+
maxRequestLength: 100000,
|
|
92
|
+
allowedRequestContentTypes: [
|
|
93
|
+
'application/json',
|
|
94
|
+
'application/graphql+json'
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
grafast: {
|
|
98
|
+
explain: true, // Enable plan diagrams
|
|
77
99
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
// Grafserv-specific options
|
|
81
|
-
grafserv: {
|
|
82
|
-
websockets: false,
|
|
83
|
-
introspection: true
|
|
84
|
-
}
|
|
100
|
+
},
|
|
85
101
|
}
|
|
86
102
|
})
|
|
87
103
|
```
|
|
@@ -104,41 +120,277 @@ type Mutation {
|
|
|
104
120
|
2. Create your resolvers (`server/resolvers.ts`):
|
|
105
121
|
|
|
106
122
|
```typescript
|
|
107
|
-
|
|
123
|
+
import { constant, lambda, access, object, filter, type GrafastSchemaConfig } from 'grafast'
|
|
124
|
+
|
|
125
|
+
const resolvers: GrafastSchemaConfig['objects'] = {
|
|
108
126
|
Query: {
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
plans: {
|
|
128
|
+
hello: () => constant('world'),
|
|
129
|
+
ping: () => constant(true)
|
|
130
|
+
}
|
|
111
131
|
},
|
|
112
132
|
Mutation: {
|
|
113
|
-
|
|
133
|
+
plans: {
|
|
134
|
+
echo: (_source, fieldArgs) => {
|
|
135
|
+
const { $message } = fieldArgs
|
|
136
|
+
return $message
|
|
137
|
+
}
|
|
138
|
+
}
|
|
114
139
|
}
|
|
115
140
|
}
|
|
141
|
+
|
|
142
|
+
export default resolvers
|
|
116
143
|
```
|
|
117
144
|
|
|
118
|
-
##
|
|
145
|
+
## Advanced Usage
|
|
146
|
+
|
|
147
|
+
### Middleware via Grafserv Plugins
|
|
119
148
|
|
|
120
|
-
|
|
149
|
+
For middleware functionality (authentication, logging, etc.), use Grafserv plugins. The CLI installer creates a `server/plugins.ts` file with examples.
|
|
150
|
+
|
|
151
|
+
#### Inline Plugin Configuration
|
|
121
152
|
|
|
122
153
|
```ts
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
154
|
+
export default defineNuxtConfig({
|
|
155
|
+
grafserv: {
|
|
156
|
+
preset: {
|
|
157
|
+
plugins: [
|
|
158
|
+
{
|
|
159
|
+
name: 'request-logging',
|
|
160
|
+
version: '1.0.0',
|
|
161
|
+
grafserv: {
|
|
162
|
+
middleware: {
|
|
163
|
+
processGraphQLRequestBody: async (next, event) => {
|
|
164
|
+
const start = Date.now()
|
|
165
|
+
console.log('[GraphQL] Request started')
|
|
166
|
+
|
|
167
|
+
const result = await next()
|
|
168
|
+
|
|
169
|
+
console.log(`[GraphQL] Completed in ${Date.now() - start}ms`)
|
|
170
|
+
return result
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
]
|
|
137
176
|
}
|
|
138
|
-
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Using External Plugin File
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
// nuxt.config.ts
|
|
185
|
+
import plugins from './server/plugins'
|
|
186
|
+
|
|
187
|
+
export default defineNuxtConfig({
|
|
188
|
+
grafserv: {
|
|
189
|
+
schema: 'server/schema.graphql',
|
|
190
|
+
resolvers: 'server/resolvers.ts',
|
|
191
|
+
preset: {
|
|
192
|
+
plugins
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
})
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
// server/plugins.ts
|
|
200
|
+
import type { GraphileConfig } from 'graphile-config'
|
|
201
|
+
|
|
202
|
+
const loggingPlugin: GraphileConfig.Plugin = {
|
|
203
|
+
name: 'request-logging',
|
|
204
|
+
version: '1.0.0',
|
|
205
|
+
grafserv: {
|
|
206
|
+
middleware: {
|
|
207
|
+
processGraphQLRequestBody: async (next, event) => {
|
|
208
|
+
console.log('Processing:', event.request.url)
|
|
209
|
+
return next()
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const authPlugin: GraphileConfig.Plugin = {
|
|
216
|
+
name: 'authentication',
|
|
217
|
+
version: '1.0.0',
|
|
218
|
+
grafserv: {
|
|
219
|
+
middleware: {
|
|
220
|
+
processGraphQLRequestBody: async (next, event) => {
|
|
221
|
+
const token = event.request.headers.get('authorization')
|
|
222
|
+
// TODO: Validate token and add user to context
|
|
223
|
+
return next()
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
139
227
|
}
|
|
228
|
+
|
|
229
|
+
export default [loggingPlugin, authPlugin]
|
|
140
230
|
```
|
|
141
231
|
|
|
232
|
+
#### Available Middleware Hooks
|
|
233
|
+
|
|
234
|
+
- `processRequest` - Process all incoming requests
|
|
235
|
+
- `processGraphQLRequestBody` - Process GraphQL request bodies
|
|
236
|
+
- `ruruHTML` - Customize Ruru IDE HTML generation
|
|
237
|
+
- `onSubscribe` - Handle GraphQL subscriptions
|
|
238
|
+
|
|
239
|
+
## Advanced Usage
|
|
240
|
+
|
|
241
|
+
### Custom Graphile Preset
|
|
242
|
+
|
|
243
|
+
Leverage the full power of the Graphile ecosystem with custom presets:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
247
|
+
|
|
248
|
+
export default defineNuxtConfig({
|
|
249
|
+
grafserv: {
|
|
250
|
+
preset: {
|
|
251
|
+
extends: [PostGraphileAmberPreset],
|
|
252
|
+
grafast: {
|
|
253
|
+
explain: true, // Enable plan diagrams for debugging
|
|
254
|
+
context: {
|
|
255
|
+
// Custom context available in all resolvers
|
|
256
|
+
apiVersion: '1.0'
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
grafserv: {
|
|
260
|
+
graphqlOverGET: true,
|
|
261
|
+
maxRequestLength: 200000
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
})
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Accessing Grafserv Instance
|
|
269
|
+
|
|
270
|
+
For advanced use cases, you can access the grafserv instance directly:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
// server/api/custom.ts
|
|
274
|
+
import { getGrafservInstance } from '@stonecrop/nuxt-grafserv/runtime/handler'
|
|
275
|
+
import { useRuntimeConfig } from '#imports'
|
|
276
|
+
|
|
277
|
+
export default defineEventHandler(async (event) => {
|
|
278
|
+
const config = useRuntimeConfig()
|
|
279
|
+
const serv = await getGrafservInstance(config.grafserv)
|
|
280
|
+
|
|
281
|
+
// Access grafserv methods or configuration
|
|
282
|
+
const preset = serv.getPreset()
|
|
283
|
+
|
|
284
|
+
return { preset }
|
|
285
|
+
})
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Schema Building with Objects Structure
|
|
289
|
+
|
|
290
|
+
The module uses Grafast's modern objects structure for better type safety and performance. Leverage Grafast's standard steps for common operations:
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
import { constant, lambda, access, object, filter, type GrafastSchemaConfig } from 'grafast'
|
|
294
|
+
|
|
295
|
+
const resolvers: GrafastSchemaConfig['objects'] = {
|
|
296
|
+
Query: {
|
|
297
|
+
plans: {
|
|
298
|
+
// Static values use constant()
|
|
299
|
+
hello: () => constant('world'),
|
|
300
|
+
|
|
301
|
+
// Arguments accessed via fieldArgs with $ prefix
|
|
302
|
+
user: (_source, fieldArgs) => {
|
|
303
|
+
const { $id } = fieldArgs
|
|
304
|
+
return lambda($id, (id) => getUserById(id))
|
|
305
|
+
},
|
|
306
|
+
|
|
307
|
+
// Use filter() for list filtering
|
|
308
|
+
userOrders: (_source, fieldArgs) => {
|
|
309
|
+
const { $userId } = fieldArgs
|
|
310
|
+
const $allOrders = constant(getAllOrders())
|
|
311
|
+
return filter($allOrders, $order =>
|
|
312
|
+
lambda([access($order, 'userId'), $userId],
|
|
313
|
+
([orderUserId, userId]) => orderUserId === userId
|
|
314
|
+
)
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
|
|
320
|
+
Mutation: {
|
|
321
|
+
plans: {
|
|
322
|
+
// Use object() to compose objects from steps
|
|
323
|
+
createUser: (_source, fieldArgs) => {
|
|
324
|
+
const { $name, $email } = fieldArgs
|
|
325
|
+
const $id = constant(generateId())
|
|
326
|
+
const $now = constant(new Date().toISOString())
|
|
327
|
+
|
|
328
|
+
const $user = object({
|
|
329
|
+
id: $id,
|
|
330
|
+
name: $name,
|
|
331
|
+
email: $email,
|
|
332
|
+
role: constant('user'),
|
|
333
|
+
createdAt: $now,
|
|
334
|
+
updatedAt: $now
|
|
335
|
+
})
|
|
336
|
+
|
|
337
|
+
return lambda($user, user => {
|
|
338
|
+
saveUser(user)
|
|
339
|
+
return user
|
|
340
|
+
})
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
|
|
345
|
+
// Field resolvers for types
|
|
346
|
+
User: {
|
|
347
|
+
plans: {
|
|
348
|
+
fullName: ($user) => {
|
|
349
|
+
return lambda($user, (user) => {
|
|
350
|
+
const typed = user as { firstName: string; lastName: string }
|
|
351
|
+
return `${typed.firstName} ${typed.lastName}`
|
|
352
|
+
})
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
// Related type resolvers
|
|
358
|
+
Order: {
|
|
359
|
+
plans: {
|
|
360
|
+
// Use access() to extract properties before lookups
|
|
361
|
+
user: ($order) => {
|
|
362
|
+
const $userId = access($order, 'userId')
|
|
363
|
+
return lambda($userId, userId => getUserById(userId as string) ?? null)
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export default resolvers
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
**Key Concepts:**
|
|
373
|
+
- All resolvers return **steps** (constant, lambda, access, object, filter, etc.), not plain values
|
|
374
|
+
- Arguments are accessed via `fieldArgs.$argumentName` (note the `$` prefix)
|
|
375
|
+
- Use `constant()` for static values
|
|
376
|
+
- Use `lambda()` to transform step values at execution time
|
|
377
|
+
- Use `access()` to extract object properties (more efficient than lambda for simple property access)
|
|
378
|
+
- Use `object()` to compose objects from multiple steps
|
|
379
|
+
- Use `filter()` for list filtering operations
|
|
380
|
+
- Source objects (`$source`, `$user`, `$order`, etc.) are also steps that need `lambda()` or `access()` to work with their properties
|
|
381
|
+
|
|
382
|
+
**Standard Steps Reference:**
|
|
383
|
+
- `constant()` - Create a step from a static value
|
|
384
|
+
- `lambda()` - Transform step values with execution-time callbacks
|
|
385
|
+
- `access()` - Extract properties from object steps
|
|
386
|
+
- `object()` - Compose objects from multiple steps
|
|
387
|
+
- `filter()` - Filter list steps based on conditions
|
|
388
|
+
- `list()` - Create lists from step tuples
|
|
389
|
+
- `first()`/`last()` - Get first/last elements from lists
|
|
390
|
+
- `loadOne()`/`loadMany()` - Batch data loading (DataLoader-style)
|
|
391
|
+
|
|
392
|
+
For the complete list, see [Grafast Standard Steps](https://grafast.org/grafast/standard-steps)
|
|
393
|
+
|
|
142
394
|
## Development
|
|
143
395
|
|
|
144
396
|
```bash
|
|
@@ -162,10 +414,6 @@ pnpm run test
|
|
|
162
414
|
pnpm run test:watch
|
|
163
415
|
```
|
|
164
416
|
|
|
165
|
-
## License
|
|
166
|
-
|
|
167
|
-
[MIT License](./LICENSE)
|
|
168
|
-
|
|
169
417
|
<!-- Badges -->
|
|
170
418
|
[npm-version-src]: https://img.shields.io/npm/v/@stonecrop/nuxt-grafserv/latest.svg?style=flat&colorA=020420&colorB=00DC82
|
|
171
419
|
[npm-version-href]: https://npmjs.com/package/@stonecrop/nuxt-grafserv
|
|
@@ -175,6 +423,3 @@ pnpm run test:watch
|
|
|
175
423
|
|
|
176
424
|
[license-src]: https://img.shields.io/npm/l/@stonecrop/nuxt-grafserv.svg?style=flat&colorA=020420&colorB=00DC82
|
|
177
425
|
[license-href]: https://npmjs.com/package/@stonecrop/nuxt-grafserv
|
|
178
|
-
|
|
179
|
-
[nuxt-src]: https://img.shields.io/badge/Nuxt-020420?logo=nuxt.js
|
|
180
|
-
[nuxt-href]: https://nuxt.com
|
package/dist/module.d.mts
CHANGED
|
@@ -2,18 +2,6 @@ import { NuxtModule } from '@nuxt/schema';
|
|
|
2
2
|
import { GraphQLSchema } from 'graphql';
|
|
3
3
|
import { GraphileConfig } from 'graphile-config';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Context provided to GraphQL resolvers
|
|
7
|
-
*/
|
|
8
|
-
type GrafastContext = {
|
|
9
|
-
req: Request;
|
|
10
|
-
params: Record<string, string>;
|
|
11
|
-
[key: string]: unknown;
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* Middleware function type for request processing
|
|
15
|
-
*/
|
|
16
|
-
type MiddlewareFunction = (context: GrafastContext, next: () => Promise<GrafastContext>) => Promise<GrafastContext>;
|
|
17
5
|
/**
|
|
18
6
|
* Schema provider function - returns a GraphQL schema
|
|
19
7
|
*/
|
|
@@ -30,32 +18,11 @@ interface ModuleOptions {
|
|
|
30
18
|
url?: string;
|
|
31
19
|
/** Whether to enable GraphiQL IDE (default: true in dev, false in prod) */
|
|
32
20
|
graphiql?: boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Path to middleware file that exports an array of middleware functions.
|
|
35
|
-
* This is the recommended approach as it preserves imports/dependencies.
|
|
36
|
-
* Example: './server/middleware.ts'
|
|
37
|
-
*/
|
|
38
|
-
middlewarePath?: string;
|
|
39
|
-
/**
|
|
40
|
-
* Middleware functions to process requests (inline).
|
|
41
|
-
* Note: Inline middleware cannot reference external modules.
|
|
42
|
-
* For middleware with dependencies, use middlewarePath instead.
|
|
43
|
-
* @deprecated Use middlewarePath for middleware with external dependencies
|
|
44
|
-
*/
|
|
45
|
-
middleware?: MiddlewareFunction[];
|
|
46
21
|
/** Custom Graphile preset to extend (for advanced grafast configuration) */
|
|
47
22
|
preset?: GraphileConfig.Preset;
|
|
48
|
-
/** Additional Graphile plugins */
|
|
49
|
-
plugins?: GraphileConfig.Plugin[];
|
|
50
|
-
/** Grafserv options */
|
|
51
|
-
grafserv?: {
|
|
52
|
-
/** Whether to enable the GraphQL websocket endpoint */
|
|
53
|
-
websockets?: boolean;
|
|
54
|
-
/** Whether to enable introspection (default: true in dev) */
|
|
55
|
-
introspection?: boolean;
|
|
56
|
-
};
|
|
57
23
|
}
|
|
58
24
|
|
|
59
25
|
declare const module$1: NuxtModule<ModuleOptions>;
|
|
60
26
|
|
|
61
27
|
export { module$1 as default };
|
|
28
|
+
export type { ModuleOptions, SchemaProvider };
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,63 +1,74 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
+
import { createRequire } from 'node:module';
|
|
2
3
|
import { useLogger, defineNuxtModule, createResolver } from '@nuxt/kit';
|
|
3
4
|
|
|
4
|
-
const logger = useLogger("nuxt-grafserv");
|
|
5
|
+
const logger = useLogger("@stonecrop/nuxt-grafserv");
|
|
5
6
|
const module$1 = defineNuxtModule({
|
|
6
7
|
meta: {
|
|
7
|
-
name: "nuxt-grafserv",
|
|
8
|
+
name: "@stonecrop/nuxt-grafserv",
|
|
8
9
|
configKey: "grafserv"
|
|
9
10
|
},
|
|
10
11
|
defaults: (_nuxt) => ({
|
|
11
|
-
schema: "
|
|
12
|
-
resolvers: "
|
|
12
|
+
schema: "server/**/*.graphql",
|
|
13
|
+
resolvers: "server/resolvers.ts",
|
|
13
14
|
url: "/graphql/",
|
|
14
15
|
graphiql: void 0,
|
|
15
16
|
// Will default based on dev mode
|
|
16
|
-
middleware: [],
|
|
17
17
|
plugins: [],
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
preset: {
|
|
19
|
+
grafserv: {
|
|
20
|
+
websockets: false
|
|
21
|
+
}
|
|
22
22
|
}
|
|
23
23
|
}),
|
|
24
24
|
setup(options, nuxt) {
|
|
25
25
|
const { resolve } = createResolver(import.meta.url);
|
|
26
|
+
const require = createRequire(import.meta.url);
|
|
26
27
|
nuxt.hook("nitro:config", (config) => {
|
|
27
|
-
|
|
28
|
+
config.alias = config.alias || {};
|
|
29
|
+
config.alias["#grafserv-server"] = join(nuxt.options.rootDir, "server");
|
|
30
|
+
const resolveForSchema = (path) => {
|
|
31
|
+
if (path.startsWith("/")) {
|
|
32
|
+
return path;
|
|
33
|
+
}
|
|
34
|
+
return join(nuxt.options.rootDir, path);
|
|
35
|
+
};
|
|
36
|
+
const resolveForVirtualModule = (path) => {
|
|
37
|
+
if (path.startsWith("/")) {
|
|
38
|
+
return path;
|
|
39
|
+
}
|
|
40
|
+
return join(nuxt.options.rootDir, path);
|
|
41
|
+
};
|
|
42
|
+
logger.info(`Nitro srcDir: ${config.srcDir}`);
|
|
43
|
+
logger.info(`Nuxt srcDir: ${nuxt.options.srcDir}`);
|
|
44
|
+
logger.info(`Nuxt rootDir: ${nuxt.options.rootDir}`);
|
|
45
|
+
logger.info(`Grafserv server alias: ${config.alias["#grafserv-server"]}`);
|
|
46
|
+
const resolverPath = options.resolvers ? resolveForVirtualModule(options.resolvers) : void 0;
|
|
47
|
+
logger.info(`Resolved resolver path: ${resolverPath}`);
|
|
28
48
|
config.runtimeConfig = config.runtimeConfig || {};
|
|
29
49
|
config.runtimeConfig.grafserv = {
|
|
30
50
|
...options,
|
|
31
|
-
//
|
|
32
|
-
|
|
51
|
+
// Pass resolved resolver path for direct import
|
|
52
|
+
resolversPath: resolverPath,
|
|
53
|
+
// Resolve schema paths from project root
|
|
54
|
+
schema: typeof options.schema === "string" ? resolveForSchema(options.schema) : Array.isArray(options.schema) ? options.schema.map((s) => resolveForSchema(s)) : options.schema
|
|
33
55
|
// function passed through
|
|
34
56
|
};
|
|
35
57
|
config.virtual = config.virtual || {};
|
|
36
58
|
if (resolverPath) {
|
|
37
59
|
config.virtual["#internal/grafserv/resolvers"] = `export { default } from '${resolverPath}'`;
|
|
38
60
|
}
|
|
39
|
-
let middlewareCode;
|
|
40
|
-
if (options.middlewarePath) {
|
|
41
|
-
const middlewarePath = join(nuxt.options.srcDir, options.middlewarePath);
|
|
42
|
-
middlewareCode = `export { default } from '${middlewarePath}'`;
|
|
43
|
-
} else if (options.middleware?.length) {
|
|
44
|
-
logger.warn("Inline middleware is deprecated. Use middlewarePath for middleware with external dependencies.");
|
|
45
|
-
middlewareCode = `export default [${options.middleware.map((fn) => fn.toString()).join(",")}]`;
|
|
46
|
-
} else {
|
|
47
|
-
middlewareCode = "export default []";
|
|
48
|
-
}
|
|
49
|
-
config.virtual["#internal/grafserv/middleware"] = middlewareCode;
|
|
50
61
|
config.externals = config.externals || {};
|
|
51
|
-
config.externals.
|
|
52
|
-
config.externals.
|
|
62
|
+
config.externals.external = config.externals.external || [];
|
|
63
|
+
config.externals.external.push(
|
|
53
64
|
"grafast",
|
|
54
|
-
"grafserv",
|
|
55
|
-
"grafserv/h3/v1",
|
|
56
|
-
"graphile-config",
|
|
57
65
|
"@graphql-tools/schema",
|
|
58
66
|
"@graphql-tools/load",
|
|
59
67
|
"@graphql-tools/graphql-file-loader"
|
|
60
68
|
);
|
|
69
|
+
const grafastPath = require.resolve("grafast");
|
|
70
|
+
config.alias = config.alias || {};
|
|
71
|
+
config.alias["grafast"] = grafastPath;
|
|
61
72
|
});
|
|
62
73
|
nuxt.hook("nitro:config", (config) => {
|
|
63
74
|
config.handlers = config.handlers || [];
|
|
@@ -66,18 +77,18 @@ const module$1 = defineNuxtModule({
|
|
|
66
77
|
handler: resolve("./runtime/handler")
|
|
67
78
|
});
|
|
68
79
|
config.handlers.push({
|
|
69
|
-
route: "/
|
|
70
|
-
handler: resolve("./runtime/
|
|
80
|
+
route: "/ruru-static/**",
|
|
81
|
+
handler: resolve("./runtime/ruru-static")
|
|
71
82
|
});
|
|
72
83
|
config.handlers.push({
|
|
73
|
-
route: "/
|
|
74
|
-
handler: resolve("./runtime/
|
|
84
|
+
route: "/graphql/cache",
|
|
85
|
+
handler: resolve("./runtime/cache")
|
|
75
86
|
});
|
|
76
87
|
});
|
|
77
88
|
if (options.url) {
|
|
78
89
|
nuxt.hook("devtools:customTabs", (tabs) => {
|
|
79
90
|
tabs.push({
|
|
80
|
-
name: "nuxt-grafserv",
|
|
91
|
+
name: "@stonecrop/nuxt-grafserv",
|
|
81
92
|
title: "GraphQL (Grafserv)",
|
|
82
93
|
icon: "simple-icons:graphql",
|
|
83
94
|
view: {
|
|
@@ -93,7 +104,6 @@ const module$1 = defineNuxtModule({
|
|
|
93
104
|
const isSchemaFile = path.endsWith(".graphql");
|
|
94
105
|
const isResolverFile = options.resolvers && path.includes(options.resolvers.replace("./", ""));
|
|
95
106
|
if (isSchemaFile || isResolverFile) {
|
|
96
|
-
logger.info(`${path} changed`);
|
|
97
107
|
if (!cacheClearing) {
|
|
98
108
|
cacheClearing = true;
|
|
99
109
|
try {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GraphQL operations handler
|
|
3
|
+
* Handles POST requests with GraphQL queries, mutations, and subscriptions
|
|
4
|
+
*/
|
|
5
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Buffer<ArrayBufferLike> | import("grafserv").JSONValue | undefined>>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
3
|
+
import { getGrafservInstance } from "./handler.js";
|
|
4
|
+
export default defineEventHandler(async (event) => {
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const options = config.grafserv;
|
|
7
|
+
const serv = await getGrafservInstance(options);
|
|
8
|
+
return serv.handleGraphQLEvent(event);
|
|
9
|
+
});
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
import { grafserv } from 'grafserv/h3/v1';
|
|
2
|
+
import type { ModuleOptions } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Get or create the grafserv instance
|
|
5
|
+
* Exported for use by separate handler files
|
|
6
|
+
*/
|
|
7
|
+
export declare function getGrafservInstance(options: ModuleOptions): Promise<ReturnType<typeof grafserv>>;
|
|
1
8
|
/**
|
|
2
9
|
* Clear the cached instances (useful for development hot reload)
|
|
3
10
|
*/
|
|
4
11
|
export declare function clearGrafservCache(): Promise<void>;
|
|
5
12
|
/**
|
|
6
|
-
* Main H3 event handler for GraphQL requests
|
|
13
|
+
* Main H3 event handler for GraphQL requests and Ruru UI
|
|
14
|
+
* Routes between GraphQL operations and GraphiQL UI based on request type
|
|
7
15
|
*/
|
|
8
16
|
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Buffer<ArrayBufferLike> | import("grafserv").JSONValue | undefined>>;
|
|
9
17
|
export default _default;
|
package/dist/runtime/handler.js
CHANGED
|
@@ -1,22 +1,9 @@
|
|
|
1
|
-
import { grafserv } from "grafserv/h3/v1";
|
|
2
|
-
import { makeGrafastSchema } from "grafast";
|
|
3
1
|
import { GraphQLFileLoader } from "@graphql-tools/graphql-file-loader";
|
|
4
2
|
import { loadTypedefs } from "@graphql-tools/load";
|
|
3
|
+
import { grafserv } from "grafserv/h3/v1";
|
|
4
|
+
import { makeGrafastSchema } from "grafast";
|
|
5
5
|
import { defineEventHandler } from "h3";
|
|
6
6
|
import { useRuntimeConfig } from "nitropack/runtime";
|
|
7
|
-
let middlewareFunctions = null;
|
|
8
|
-
async function getMiddleware() {
|
|
9
|
-
if (middlewareFunctions !== null) {
|
|
10
|
-
return middlewareFunctions;
|
|
11
|
-
}
|
|
12
|
-
try {
|
|
13
|
-
const mod = await import("#internal/grafserv/middleware");
|
|
14
|
-
middlewareFunctions = mod.default || [];
|
|
15
|
-
} catch {
|
|
16
|
-
middlewareFunctions = [];
|
|
17
|
-
}
|
|
18
|
-
return middlewareFunctions;
|
|
19
|
-
}
|
|
20
7
|
let grafservInstance = null;
|
|
21
8
|
let cachedSchema = null;
|
|
22
9
|
async function loadTypeDefsFromFiles(schemaPath) {
|
|
@@ -35,49 +22,48 @@ async function getSchema(options) {
|
|
|
35
22
|
schema = await options.schema();
|
|
36
23
|
} else if (options.schema) {
|
|
37
24
|
const typeDefDocs = await loadTypeDefsFromFiles(options.schema);
|
|
38
|
-
|
|
25
|
+
const objects = {};
|
|
39
26
|
if (options.resolvers) {
|
|
40
27
|
try {
|
|
41
28
|
const resolverModule = await import("#internal/grafserv/resolvers");
|
|
42
29
|
const resolvers = resolverModule.default || resolverModule;
|
|
43
|
-
console.
|
|
30
|
+
console.debug("[@stonecrop/nuxt-grafserv] Resolvers loaded:", Object.keys(resolvers));
|
|
44
31
|
for (const typeName of Object.keys(resolvers)) {
|
|
45
|
-
plans[typeName] = {};
|
|
46
32
|
const typeResolvers = resolvers[typeName];
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
} else {
|
|
52
|
-
plans[typeName][fieldName] = resolver;
|
|
53
|
-
}
|
|
33
|
+
if (typeResolvers && typeof typeResolvers === "object" && "plans" in typeResolvers) {
|
|
34
|
+
objects[typeName] = typeResolvers;
|
|
35
|
+
} else {
|
|
36
|
+
objects[typeName] = { plans: typeResolvers };
|
|
54
37
|
}
|
|
55
38
|
}
|
|
56
39
|
} catch (e) {
|
|
40
|
+
console.error("[@stonecrop/nuxt-grafserv] Error loading resolvers:", e);
|
|
57
41
|
console.warn("[@stonecrop/nuxt-grafserv] Could not load resolvers:", e);
|
|
58
42
|
}
|
|
59
43
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
44
|
+
try {
|
|
45
|
+
schema = makeGrafastSchema({
|
|
46
|
+
typeDefs: typeDefDocs,
|
|
47
|
+
objects
|
|
48
|
+
});
|
|
49
|
+
console.debug("[@stonecrop/nuxt-grafserv] Grafast schema created successfully");
|
|
50
|
+
} catch (error) {
|
|
51
|
+
console.error("[@stonecrop/nuxt-grafserv] Error creating Grafast schema:", error);
|
|
52
|
+
throw error;
|
|
53
|
+
}
|
|
64
54
|
} else {
|
|
65
55
|
throw new Error("[@stonecrop/nuxt-grafserv] No schema provided. Configure schema path or provider function.");
|
|
66
56
|
}
|
|
67
57
|
cachedSchema = schema;
|
|
68
58
|
return schema;
|
|
69
59
|
}
|
|
70
|
-
async function getGrafservInstance(options) {
|
|
60
|
+
export async function getGrafservInstance(options) {
|
|
71
61
|
if (grafservInstance) {
|
|
62
|
+
console.log("[@stonecrop/nuxt-grafserv] Returning cached grafserv instance");
|
|
72
63
|
return grafservInstance;
|
|
73
64
|
}
|
|
74
65
|
const schema = await getSchema(options);
|
|
75
|
-
|
|
76
|
-
grafservInstance = grafserv({
|
|
77
|
-
schema,
|
|
78
|
-
graphiql: options.graphiql ?? isDev,
|
|
79
|
-
websockets: options.grafserv?.websockets ?? false
|
|
80
|
-
});
|
|
66
|
+
grafservInstance = grafserv({ schema, preset: options.preset });
|
|
81
67
|
console.log("[@stonecrop/nuxt-grafserv] Grafserv instance created");
|
|
82
68
|
return grafservInstance;
|
|
83
69
|
}
|
|
@@ -86,46 +72,16 @@ export async function clearGrafservCache() {
|
|
|
86
72
|
cachedSchema = null;
|
|
87
73
|
console.log("[@stonecrop/nuxt-grafserv] Cache cleared");
|
|
88
74
|
}
|
|
89
|
-
async function applyMiddleware(context, middleware) {
|
|
90
|
-
if (!middleware || middleware.length === 0) {
|
|
91
|
-
return context;
|
|
92
|
-
}
|
|
93
|
-
const applyNext = async (index) => {
|
|
94
|
-
if (index >= middleware.length) {
|
|
95
|
-
return context;
|
|
96
|
-
}
|
|
97
|
-
return middleware[index](context, () => applyNext(index + 1));
|
|
98
|
-
};
|
|
99
|
-
return applyNext(0);
|
|
100
|
-
}
|
|
101
75
|
export default defineEventHandler(async (event) => {
|
|
102
76
|
const config = useRuntimeConfig();
|
|
103
77
|
const options = config.grafserv;
|
|
104
78
|
try {
|
|
105
|
-
if (event.node.req.url?.includes("/__grafserv_cache_clear") && process.env.NODE_ENV === "development") {
|
|
106
|
-
await clearGrafservCache();
|
|
107
|
-
return { success: true, message: "Cache cleared" };
|
|
108
|
-
}
|
|
109
|
-
const { req } = event.node;
|
|
110
|
-
const context = {
|
|
111
|
-
req: new Request(new URL(req.url || "/", `http://${req.headers.host || "localhost"}`), {
|
|
112
|
-
method: req.method,
|
|
113
|
-
headers: req.headers
|
|
114
|
-
}),
|
|
115
|
-
params: event.context.params || {}
|
|
116
|
-
};
|
|
117
|
-
const middleware = await getMiddleware();
|
|
118
|
-
await applyMiddleware(context, middleware);
|
|
119
79
|
const serv = await getGrafservInstance(options);
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return serv.handleGraphiqlStaticEvent(event);
|
|
124
|
-
}
|
|
125
|
-
if (method === "GET" && url.match(/\/graphql\/?(\?.*)?$/)) {
|
|
126
|
-
return serv.handleGraphiqlEvent(event);
|
|
80
|
+
const graphqlResult = await serv.handleGraphQLEvent(event);
|
|
81
|
+
if (graphqlResult !== null) {
|
|
82
|
+
return graphqlResult;
|
|
127
83
|
}
|
|
128
|
-
return serv.
|
|
84
|
+
return serv.handleGraphiqlEvent(event);
|
|
129
85
|
} catch (error) {
|
|
130
86
|
console.error("[@stonecrop/nuxt-grafserv] Error in GraphQL handler:", error);
|
|
131
87
|
throw error;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ruru/GraphiQL static assets handler
|
|
3
|
+
* Serves CSS, JavaScript, and other static files for the GraphQL IDE
|
|
4
|
+
*/
|
|
5
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Buffer<ArrayBufferLike> | import("grafserv").JSONValue | undefined>>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
3
|
+
import { getGrafservInstance } from "./handler.js";
|
|
4
|
+
export default defineEventHandler(async (event) => {
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const options = config.grafserv;
|
|
7
|
+
const serv = await getGrafservInstance(options);
|
|
8
|
+
return serv.handleGraphiqlStaticEvent(event);
|
|
9
|
+
});
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ruru/GraphiQL UI handler
|
|
3
|
+
* Serves the GraphQL IDE interface for exploring and testing the API
|
|
4
|
+
*/
|
|
5
|
+
declare const _default: import("h3").EventHandler<import("h3").EventHandlerRequest, Promise<Buffer<ArrayBufferLike> | import("grafserv").JSONValue | undefined>>;
|
|
6
|
+
export default _default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
import { useRuntimeConfig } from "nitropack/runtime";
|
|
3
|
+
import { getGrafservInstance } from "./handler.js";
|
|
4
|
+
export default defineEventHandler(async (event) => {
|
|
5
|
+
const config = useRuntimeConfig();
|
|
6
|
+
const options = config.grafserv;
|
|
7
|
+
const serv = await getGrafservInstance(options);
|
|
8
|
+
return serv.handleGraphiqlEvent(event);
|
|
9
|
+
});
|
package/dist/types.d.mts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import type { NuxtModule } from '@nuxt/schema'
|
|
2
|
-
|
|
3
|
-
import type { default as Module } from './module.mjs'
|
|
4
|
-
|
|
5
|
-
export type ModuleOptions = typeof Module extends NuxtModule<infer O> ? Partial<O> : Record<string, any>
|
|
6
|
-
|
|
7
1
|
export { default } from './module.mjs'
|
|
2
|
+
|
|
3
|
+
export { type ModuleOptions, type SchemaProvider } from './module.mjs'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/nuxt-grafserv",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Pluggable Grafserv GraphQL server as Nuxt Module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -19,16 +19,16 @@
|
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
21
|
"import": "./dist/module.mjs",
|
|
22
|
-
"types": "./dist/
|
|
22
|
+
"types": "./dist/module.d.mts"
|
|
23
23
|
},
|
|
24
24
|
"./runtime/*": "./dist/runtime/*"
|
|
25
25
|
},
|
|
26
26
|
"main": "./dist/module.mjs",
|
|
27
|
-
"types": "./dist/
|
|
27
|
+
"types": "./dist/module.d.mts",
|
|
28
28
|
"typesVersions": {
|
|
29
29
|
"*": {
|
|
30
30
|
".": [
|
|
31
|
-
"./dist/
|
|
31
|
+
"./dist/module.d.mts"
|
|
32
32
|
]
|
|
33
33
|
}
|
|
34
34
|
},
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
"@graphql-tools/load": "^8.1.8",
|
|
41
41
|
"@graphql-tools/stitch": "^10.1.8",
|
|
42
42
|
"@graphql-tools/wrap": "^11.1.4",
|
|
43
|
-
"grafast": "^1.0.0-rc.
|
|
44
|
-
"grafserv": "^1.0.0-rc.
|
|
45
|
-
"graphile-config": "^1.0.0-rc.
|
|
43
|
+
"grafast": "^1.0.0-rc.4",
|
|
44
|
+
"grafserv": "^1.0.0-rc.4",
|
|
45
|
+
"graphile-config": "^1.0.0-rc.3",
|
|
46
46
|
"graphql": "^16.12.0",
|
|
47
|
-
"@stonecrop/graphql-middleware": "0.7.
|
|
47
|
+
"@stonecrop/graphql-middleware": "0.7.5"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@casl/ability": "^6.
|
|
50
|
+
"@casl/ability": "^6.8.0",
|
|
51
51
|
"@eslint/js": "^9.39.2",
|
|
52
52
|
"@nuxt/devtools": "^3.1.1",
|
|
53
53
|
"@nuxt/eslint-config": "^1.12.1",
|
|
@@ -57,8 +57,8 @@
|
|
|
57
57
|
"@nuxt/test-utils": "^3.23.0",
|
|
58
58
|
"@vitest/coverage-istanbul": "^4.0.17",
|
|
59
59
|
"@types/node": "^22.19.5",
|
|
60
|
-
"h3": "^1.15.
|
|
61
|
-
"nitropack": "^2.13.
|
|
60
|
+
"h3": "^1.15.5",
|
|
61
|
+
"nitropack": "^2.13.1",
|
|
62
62
|
"changelogen": "^0.6.2",
|
|
63
63
|
"eslint": "^9.39.2",
|
|
64
64
|
"jsdom": "^27.4.0",
|
|
@@ -67,12 +67,12 @@
|
|
|
67
67
|
"vite": "^7.3.1",
|
|
68
68
|
"vitest": "^4.0.17",
|
|
69
69
|
"vue-tsc": "^3.2.2",
|
|
70
|
-
"@stonecrop/casl-middleware": "0.7.
|
|
71
|
-
"@stonecrop/rockfoil": "0.7.
|
|
70
|
+
"@stonecrop/casl-middleware": "0.7.5",
|
|
71
|
+
"@stonecrop/rockfoil": "0.7.5"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@stonecrop/casl-middleware": "0.7.
|
|
75
|
-
"@stonecrop/rockfoil": "0.7.
|
|
74
|
+
"@stonecrop/casl-middleware": "0.7.5",
|
|
75
|
+
"@stonecrop/rockfoil": "0.7.5"
|
|
76
76
|
},
|
|
77
77
|
"peerDependenciesMeta": {
|
|
78
78
|
"@stonecrop/casl-middleware": {
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"lint": "eslint .",
|
|
94
94
|
"test": "vitest run",
|
|
95
95
|
"test:ci": "vitest run --run",
|
|
96
|
+
"test:coverage": "vitest run --coverage",
|
|
96
97
|
"test:watch": "vitest watch",
|
|
97
98
|
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
|
|
98
99
|
}
|