@stonecrop/nuxt-grafserv 0.7.8 → 0.7.9
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 +174 -241
- package/dist/module.d.mts +30 -14
- package/dist/module.json +1 -1
- package/dist/module.mjs +56 -11
- package/dist/runtime/handler.js +9 -13
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -48,25 +48,33 @@ yarn add @stonecrop/nuxt-grafserv postgraphile
|
|
|
48
48
|
npm install @stonecrop/nuxt-grafserv postgraphile
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
2.
|
|
51
|
+
2. Create your preset file `server/graphile.preset.ts`:
|
|
52
52
|
|
|
53
53
|
```ts
|
|
54
54
|
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
55
55
|
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
56
56
|
|
|
57
|
+
const preset = {
|
|
58
|
+
extends: [PostGraphileAmberPreset],
|
|
59
|
+
pgServices: [
|
|
60
|
+
makePgService({
|
|
61
|
+
connectionString: process.env.DATABASE_URL || 'postgresql://localhost/mydb',
|
|
62
|
+
schemas: ['public'],
|
|
63
|
+
}),
|
|
64
|
+
],
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default preset
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
3. Configure in `nuxt.config.ts`:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
57
73
|
export default defineNuxtConfig({
|
|
58
74
|
modules: ['@stonecrop/nuxt-grafserv'],
|
|
59
75
|
grafserv: {
|
|
60
76
|
type: 'postgraphile', // Required: specify configuration type
|
|
61
|
-
preset:
|
|
62
|
-
extends: [PostGraphileAmberPreset],
|
|
63
|
-
pgServices: [
|
|
64
|
-
makePgService({
|
|
65
|
-
connectionString: process.env.DATABASE_URL || 'postgresql://localhost/mydb',
|
|
66
|
-
schemas: ['public'],
|
|
67
|
-
}),
|
|
68
|
-
],
|
|
69
|
-
},
|
|
77
|
+
preset: './server/graphile.preset.ts', // Path to preset file
|
|
70
78
|
url: '/graphql',
|
|
71
79
|
graphiql: true,
|
|
72
80
|
}
|
|
@@ -109,35 +117,45 @@ Use `type: 'postgraphile'` for PostGraphile-based GraphQL APIs:
|
|
|
109
117
|
| Option | Type | Required | Description |
|
|
110
118
|
|--------|------|----------|-------------|
|
|
111
119
|
| `type` | `'postgraphile'` | ✅ | Configuration type discriminator |
|
|
112
|
-
| `preset` | `
|
|
120
|
+
| `preset` | `string` | ✅ | Path to PostGraphile preset file (e.g., './server/graphile.preset.ts') |
|
|
113
121
|
| `url` | `string` | ❌ | GraphQL endpoint URL (default: '/graphql/') |
|
|
114
122
|
| `graphiql` | `boolean` | ❌ | Enable GraphiQL IDE (default: true in dev, false in prod) |
|
|
115
123
|
|
|
124
|
+
> **Important:** The preset must be a file path, not an inline object. See "Why File-Based Presets?" section below.
|
|
125
|
+
|
|
116
126
|
**Example:**
|
|
117
127
|
|
|
118
128
|
```ts
|
|
119
|
-
|
|
120
|
-
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
121
|
-
|
|
129
|
+
// nuxt.config.ts
|
|
122
130
|
export default defineNuxtConfig({
|
|
123
131
|
grafserv: {
|
|
124
132
|
type: 'postgraphile',
|
|
125
|
-
preset:
|
|
126
|
-
extends: [PostGraphileAmberPreset],
|
|
127
|
-
pgServices: [
|
|
128
|
-
makePgService({
|
|
129
|
-
connectionString: process.env.DATABASE_URL,
|
|
130
|
-
schemas: ['public'],
|
|
131
|
-
}),
|
|
132
|
-
],
|
|
133
|
-
plugins: [MyCustomPlugin],
|
|
134
|
-
},
|
|
133
|
+
preset: './server/graphile.preset.ts',
|
|
135
134
|
url: '/graphql',
|
|
136
135
|
graphiql: true,
|
|
137
136
|
}
|
|
138
137
|
})
|
|
139
138
|
```
|
|
140
139
|
|
|
140
|
+
```ts
|
|
141
|
+
// server/graphile.preset.ts
|
|
142
|
+
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
143
|
+
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
144
|
+
|
|
145
|
+
const preset = {
|
|
146
|
+
extends: [PostGraphileAmberPreset],
|
|
147
|
+
pgServices: [
|
|
148
|
+
makePgService({
|
|
149
|
+
connectionString: process.env.DATABASE_URL,
|
|
150
|
+
schemas: ['public'],
|
|
151
|
+
}),
|
|
152
|
+
],
|
|
153
|
+
plugins: [MyCustomPlugin],
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export default preset
|
|
157
|
+
```
|
|
158
|
+
|
|
141
159
|
### Schema Configuration
|
|
142
160
|
|
|
143
161
|
Use `type: 'schema'` for custom GraphQL schemas with Grafast resolvers:
|
|
@@ -249,109 +267,47 @@ export default defineNuxtConfig({
|
|
|
249
267
|
|
|
250
268
|
For database-backed GraphQL APIs:
|
|
251
269
|
|
|
252
|
-
1.
|
|
270
|
+
1. Create your preset file `server/graphile.preset.ts`:
|
|
253
271
|
|
|
254
272
|
```ts
|
|
255
273
|
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
256
274
|
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
257
275
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
schemas: ['public'],
|
|
268
|
-
}),
|
|
269
|
-
],
|
|
270
|
-
},
|
|
271
|
-
}
|
|
272
|
-
})
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
2. That's it! PostGraphile automatically generates your GraphQL schema from your PostgreSQL database.
|
|
276
|
-
|
|
277
|
-
## Advanced Usage
|
|
278
|
-
|
|
279
|
-
## Advanced Usage
|
|
280
|
-
|
|
281
|
-
### Grafserv Middleware and Plugins
|
|
276
|
+
const preset = {
|
|
277
|
+
extends: [PostGraphileAmberPreset],
|
|
278
|
+
pgServices: [
|
|
279
|
+
makePgService({
|
|
280
|
+
connectionString: process.env.DATABASE_URL,
|
|
281
|
+
schemas: ['public'],
|
|
282
|
+
}),
|
|
283
|
+
],
|
|
284
|
+
}
|
|
282
285
|
|
|
283
|
-
|
|
286
|
+
export default preset
|
|
287
|
+
```
|
|
284
288
|
|
|
285
|
-
|
|
289
|
+
2. Configure PostGraphile in `nuxt.config.ts`:
|
|
286
290
|
|
|
287
291
|
```ts
|
|
288
|
-
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
289
|
-
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
290
|
-
|
|
291
292
|
export default defineNuxtConfig({
|
|
293
|
+
modules: ['@stonecrop/nuxt-grafserv'],
|
|
292
294
|
grafserv: {
|
|
293
295
|
type: 'postgraphile',
|
|
294
|
-
preset:
|
|
295
|
-
extends: [PostGraphileAmberPreset],
|
|
296
|
-
pgServices: [makePgService({ /* ... */ })],
|
|
297
|
-
plugins: [
|
|
298
|
-
{
|
|
299
|
-
name: 'request-logging',
|
|
300
|
-
version: '1.0.0',
|
|
301
|
-
grafserv: {
|
|
302
|
-
middleware: {
|
|
303
|
-
processGraphQLRequestBody: async (next, event) => {
|
|
304
|
-
const start = Date.now()
|
|
305
|
-
console.log('[GraphQL] Request started')
|
|
306
|
-
const result = await next()
|
|
307
|
-
console.log(`[GraphQL] Completed in ${Date.now() - start}ms`)
|
|
308
|
-
return result
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
]
|
|
314
|
-
}
|
|
296
|
+
preset: './server/graphile.preset.ts',
|
|
315
297
|
}
|
|
316
298
|
})
|
|
317
299
|
```
|
|
318
300
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
```ts
|
|
322
|
-
export default defineNuxtConfig({
|
|
323
|
-
grafserv: {
|
|
324
|
-
type: 'schema',
|
|
325
|
-
schema: 'server/**/*.graphql',
|
|
326
|
-
resolvers: 'server/resolvers.ts',
|
|
327
|
-
// Note: For Schema config, advanced plugin configuration should be done
|
|
328
|
-
// through a preset configuration or custom schema provider
|
|
329
|
-
}
|
|
330
|
-
})
|
|
331
|
-
```
|
|
301
|
+
3. That's it! PostGraphile automatically generates your GraphQL schema from your PostgreSQL database.
|
|
332
302
|
|
|
333
|
-
|
|
303
|
+
## Advanced Usage
|
|
334
304
|
|
|
335
|
-
|
|
336
|
-
// nuxt.config.ts
|
|
337
|
-
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
338
|
-
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
339
|
-
import plugins from './server/plugins'
|
|
305
|
+
### Custom Grafserv Plugins
|
|
340
306
|
|
|
341
|
-
|
|
342
|
-
grafserv: {
|
|
343
|
-
type: 'postgraphile',
|
|
344
|
-
preset: {
|
|
345
|
-
extends: [PostGraphileAmberPreset],
|
|
346
|
-
pgServices: [makePgService({ /* ... */ })],
|
|
347
|
-
plugins
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
})
|
|
351
|
-
```
|
|
307
|
+
Add custom plugins for authentication, logging, or rate limiting through your preset file:
|
|
352
308
|
|
|
353
309
|
```ts
|
|
354
|
-
// server/plugins.ts
|
|
310
|
+
// server/graphile/plugins.ts
|
|
355
311
|
import type { GraphileConfig } from 'graphile-config'
|
|
356
312
|
|
|
357
313
|
const loggingPlugin: GraphileConfig.Plugin = {
|
|
@@ -387,6 +343,23 @@ const authPlugin: GraphileConfig.Plugin = {
|
|
|
387
343
|
export default [loggingPlugin, authPlugin]
|
|
388
344
|
```
|
|
389
345
|
|
|
346
|
+
Import the plugins in your preset:
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
// server/graphile/graphile.preset.ts
|
|
350
|
+
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
351
|
+
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
352
|
+
import plugins from './plugins'
|
|
353
|
+
|
|
354
|
+
const preset = {
|
|
355
|
+
extends: [PostGraphileAmberPreset],
|
|
356
|
+
pgServices: [makePgService({ /* ... */ })],
|
|
357
|
+
plugins
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export default preset
|
|
361
|
+
```
|
|
362
|
+
|
|
390
363
|
#### Available Middleware Hooks
|
|
391
364
|
|
|
392
365
|
- `processRequest` - Process all incoming requests
|
|
@@ -396,149 +369,120 @@ export default [loggingPlugin, authPlugin]
|
|
|
396
369
|
|
|
397
370
|
## PostGraphile Integration
|
|
398
371
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
### Prerequisites
|
|
372
|
+
PostGraphile v5+ automatically generates your GraphQL schema from PostgreSQL.
|
|
402
373
|
|
|
403
|
-
|
|
404
|
-
pnpm add postgraphile
|
|
405
|
-
```
|
|
406
|
-
|
|
407
|
-
### Basic PostGraphile Setup
|
|
374
|
+
### With Community Plugins
|
|
408
375
|
|
|
409
376
|
```typescript
|
|
410
|
-
// nuxt.config.ts
|
|
411
377
|
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
412
378
|
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
379
|
+
import PgSimplifyInflectorPlugin from '@graphile-contrib/pg-simplify-inflector'
|
|
413
380
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
})
|
|
431
|
-
```
|
|
381
|
+
const preset = {
|
|
382
|
+
extends: [PostGraphileAmberPreset],
|
|
383
|
+
plugins: [PgSimplifyInflectorPlugin],
|
|
384
|
+
pgServices: [
|
|
385
|
+
makePgService({
|
|
386
|
+
connectionString: process.env.DATABASE_URL,
|
|
387
|
+
schemas: ['public'],
|
|
388
|
+
}),
|
|
389
|
+
],
|
|
390
|
+
schema: {
|
|
391
|
+
defaultBehavior: 'connection', // Enable Relay-style connections
|
|
392
|
+
},
|
|
393
|
+
grafast: {
|
|
394
|
+
explain: process.env.NODE_ENV === 'development', // Plan diagrams in dev
|
|
395
|
+
},
|
|
396
|
+
}
|
|
432
397
|
|
|
433
|
-
|
|
398
|
+
export default preset
|
|
399
|
+
```
|
|
434
400
|
|
|
435
|
-
|
|
401
|
+
### Advanced Configuration
|
|
436
402
|
|
|
437
403
|
```typescript
|
|
438
|
-
// nuxt.config.ts
|
|
439
404
|
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
440
405
|
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
441
|
-
import PgSimplifyInflectorPlugin from '@graphile-contrib/pg-simplify-inflector'
|
|
442
406
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
407
|
+
const preset = {
|
|
408
|
+
extends: [PostGraphileAmberPreset],
|
|
409
|
+
pgServices: [
|
|
410
|
+
makePgService({
|
|
411
|
+
connectionString: process.env.DATABASE_URL,
|
|
412
|
+
schemas: ['public', 'app_private'],
|
|
413
|
+
superuserConnectionString: process.env.SUPERUSER_DATABASE_URL, // For watch mode
|
|
414
|
+
pubsub: true, // Enable LISTEN/NOTIFY for subscriptions
|
|
415
|
+
}),
|
|
416
|
+
],
|
|
417
|
+
gather: {
|
|
418
|
+
// Smart tags for schema customization
|
|
419
|
+
pgJwtTypes: 'app_public.jwt_token',
|
|
420
|
+
},
|
|
421
|
+
schema: {
|
|
422
|
+
// Behavior overrides
|
|
423
|
+
defaultBehavior: '-insert -update -delete', // Read-only by default
|
|
424
|
+
pgJwtSecret: process.env.JWT_SECRET,
|
|
425
|
+
},
|
|
426
|
+
grafast: {
|
|
427
|
+
explain: true,
|
|
428
|
+
context: (requestContext) => ({
|
|
429
|
+
// Custom context for all resolvers
|
|
430
|
+
userId: requestContext.user?.id,
|
|
431
|
+
}),
|
|
432
|
+
},
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export default preset
|
|
464
436
|
```
|
|
465
437
|
|
|
466
|
-
###
|
|
438
|
+
### Why File-Based Presets?
|
|
467
439
|
|
|
468
|
-
|
|
469
|
-
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
470
|
-
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
440
|
+
PostGraphile presets must be in separate files, not inline in `nuxt.config.ts`.
|
|
471
441
|
|
|
472
|
-
|
|
473
|
-
grafserv: {
|
|
474
|
-
type: 'postgraphile',
|
|
475
|
-
preset: {
|
|
476
|
-
extends: [PostGraphileAmberPreset],
|
|
477
|
-
pgServices: [
|
|
478
|
-
makePgService({
|
|
479
|
-
connectionString: process.env.DATABASE_URL,
|
|
480
|
-
schemas: ['public', 'app_private'],
|
|
481
|
-
superuserConnectionString: process.env.SUPERUSER_DATABASE_URL, // For watch mode
|
|
482
|
-
pubsub: true, // Enable LISTEN/NOTIFY for subscriptions
|
|
483
|
-
}),
|
|
484
|
-
],
|
|
485
|
-
gather: {
|
|
486
|
-
// Smart tags for schema customization
|
|
487
|
-
pgJwtTypes: 'app_public.jwt_token',
|
|
488
|
-
},
|
|
489
|
-
schema: {
|
|
490
|
-
// Behavior overrides
|
|
491
|
-
defaultBehavior: '-insert -update -delete', // Read-only by default
|
|
492
|
-
pgJwtSecret: process.env.JWT_SECRET,
|
|
493
|
-
},
|
|
494
|
-
grafast: {
|
|
495
|
-
explain: true,
|
|
496
|
-
context: (requestContext) => ({
|
|
497
|
-
// Custom context for all resolvers
|
|
498
|
-
userId: requestContext.user?.id,
|
|
499
|
-
}),
|
|
500
|
-
},
|
|
501
|
-
},
|
|
502
|
-
}
|
|
503
|
-
})
|
|
504
|
-
```
|
|
442
|
+
The module uses PostGraphile's [instance-based approach](https://postgraphile.org/postgraphile/next/usage-library):
|
|
505
443
|
|
|
506
|
-
|
|
444
|
+
1. At build time, the preset file is imported and a PostGraphile instance is created
|
|
445
|
+
2. The instance is exposed via Nitro's virtual module system
|
|
446
|
+
3. At runtime, handlers call `pgl.getSchema()` to get the schema
|
|
507
447
|
|
|
508
|
-
|
|
509
|
-
- **Auto-Generated Resolvers**: All queries, mutations, and subscriptions from database
|
|
510
|
-
- **Real-time Subscriptions**: Live queries via PostgreSQL LISTEN/NOTIFY
|
|
511
|
-
- **Row-Level Security**: Leverages PostgreSQL RLS for fine-grained authorization
|
|
512
|
-
- **High Performance**: Grafast execution engine with intelligent query planning
|
|
513
|
-
- **Type Safety**: Full TypeScript support for generated schema
|
|
514
|
-
- **Plugin Ecosystem**: Rich collection of community plugins for extended functionality
|
|
448
|
+
This approach avoids GraphQL module duplication, follows PostGraphile's recommended pattern, supports watch mode, and properly handles database connections.
|
|
515
449
|
|
|
516
|
-
|
|
450
|
+
**Your preset file needs a default export:**
|
|
517
451
|
|
|
518
|
-
|
|
452
|
+
```typescript
|
|
453
|
+
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
519
454
|
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
455
|
+
const preset = {
|
|
456
|
+
extends: [PostGraphileAmberPreset],
|
|
457
|
+
// ...
|
|
458
|
+
}
|
|
524
459
|
|
|
525
|
-
export default
|
|
526
|
-
|
|
527
|
-
const serv = await getGrafservInstance(config.grafserv)
|
|
460
|
+
export default preset
|
|
461
|
+
```
|
|
528
462
|
|
|
529
|
-
|
|
530
|
-
// Note: serv contains the grafserv instance with your schema
|
|
463
|
+
**Import Requirements:**
|
|
531
464
|
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
465
|
+
Relative imports in preset files work with file extensions:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
// server/graphile/graphile.preset.ts
|
|
469
|
+
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
470
|
+
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
471
|
+
import { MyPlugin } from './plugins/my-plugin'
|
|
472
|
+
import { AnotherPlugin } from './plugins/another'
|
|
473
|
+
|
|
474
|
+
const preset = {
|
|
475
|
+
extends: [PostGraphileAmberPreset],
|
|
476
|
+
pgServices: [makePgService({/*...*/})],
|
|
477
|
+
plugins: [MyPlugin, AnotherPlugin],
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export default preset
|
|
537
481
|
```
|
|
538
482
|
|
|
539
|
-
### Schema Building with
|
|
483
|
+
### Schema Building with Grafast
|
|
540
484
|
|
|
541
|
-
|
|
485
|
+
Grafast uses a step-based execution model. Common patterns:
|
|
542
486
|
|
|
543
487
|
```typescript
|
|
544
488
|
import { constant, lambda, access, object, filter, type GrafastSchemaConfig } from 'grafast'
|
|
@@ -621,26 +565,15 @@ export default resolvers
|
|
|
621
565
|
```
|
|
622
566
|
|
|
623
567
|
**Key Concepts:**
|
|
624
|
-
-
|
|
625
|
-
- Arguments are accessed via `fieldArgs.$argumentName`
|
|
626
|
-
-
|
|
627
|
-
-
|
|
628
|
-
-
|
|
629
|
-
-
|
|
630
|
-
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
**Standard Steps Reference:**
|
|
634
|
-
- `constant()` - Create a step from a static value
|
|
635
|
-
- `lambda()` - Transform step values with execution-time callbacks
|
|
636
|
-
- `access()` - Extract properties from object steps
|
|
637
|
-
- `object()` - Compose objects from multiple steps
|
|
638
|
-
- `filter()` - Filter list steps based on conditions
|
|
639
|
-
- `list()` - Create lists from step tuples
|
|
640
|
-
- `first()`/`last()` - Get first/last elements from lists
|
|
641
|
-
- `loadOne()`/`loadMany()` - Batch data loading (DataLoader-style)
|
|
642
|
-
|
|
643
|
-
For the complete list, see [Grafast Standard Steps](https://grafast.org/grafast/standard-steps)
|
|
568
|
+
- Resolvers return **steps** (constant, lambda, access, object, filter), not plain values
|
|
569
|
+
- Arguments are accessed via `fieldArgs.$argumentName`
|
|
570
|
+
- `constant()` - static values
|
|
571
|
+
- `lambda()` - transform step values at execution time
|
|
572
|
+
- `access()` - extract object properties efficiently
|
|
573
|
+
- `object()` - compose objects from steps
|
|
574
|
+
- `filter()` - filter list steps
|
|
575
|
+
|
|
576
|
+
See [Grafast Standard Steps](https://grafast.org/grafast/standard-steps) for the complete reference.
|
|
644
577
|
|
|
645
578
|
## Development
|
|
646
579
|
|
package/dist/module.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { NuxtModule } from '@nuxt/schema';
|
|
2
2
|
import { GraphQLSchema } from 'graphql';
|
|
3
|
-
import { GraphileConfig } from 'graphile-config';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Schema provider function - returns a GraphQL schema
|
|
@@ -10,27 +9,34 @@ type SchemaProvider = () => GraphQLSchema | Promise<GraphQLSchema>;
|
|
|
10
9
|
* PostGraphile configuration using preset
|
|
11
10
|
*
|
|
12
11
|
* This is the recommended approach for PostGraphile integration.
|
|
13
|
-
* The preset is passed to PostGraphile's makeSchema() function
|
|
12
|
+
* The preset file path is resolved and imported at runtime, then passed to PostGraphile's makeSchema() function.
|
|
13
|
+
*
|
|
14
|
+
* Note: Inline preset objects are not supported due to Nitro's build/runtime separation.
|
|
15
|
+
* Complex objects with extends arrays, plugins, and functions cannot be serialized across this boundary.
|
|
14
16
|
*
|
|
15
17
|
* @example
|
|
16
18
|
* ```typescript
|
|
19
|
+
* // 1. Create server/graphile.preset.ts
|
|
17
20
|
* import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
18
21
|
* import { makePgService } from 'postgraphile/adaptors/pg'
|
|
19
22
|
*
|
|
23
|
+
* export default {
|
|
24
|
+
* extends: [PostGraphileAmberPreset],
|
|
25
|
+
* pgServices: [
|
|
26
|
+
* makePgService({
|
|
27
|
+
* connectionString: process.env.DATABASE_URL,
|
|
28
|
+
* schemas: ['public'],
|
|
29
|
+
* }),
|
|
30
|
+
* ],
|
|
31
|
+
* plugins: [MyCustomPlugin],
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* // 2. Reference the preset file in nuxt.config.ts
|
|
20
35
|
* export default defineNuxtConfig({
|
|
21
36
|
* modules: ['@stonecrop/nuxt-grafserv'],
|
|
22
37
|
* grafserv: {
|
|
23
38
|
* type: 'postgraphile',
|
|
24
|
-
* preset:
|
|
25
|
-
* extends: [PostGraphileAmberPreset],
|
|
26
|
-
* pgServices: [
|
|
27
|
-
* makePgService({
|
|
28
|
-
* connectionString: process.env.DATABASE_URL,
|
|
29
|
-
* schemas: ['public'],
|
|
30
|
-
* }),
|
|
31
|
-
* ],
|
|
32
|
-
* plugins: [MyCustomPlugin],
|
|
33
|
-
* },
|
|
39
|
+
* preset: './server/graphile.preset.ts',
|
|
34
40
|
* url: '/graphql',
|
|
35
41
|
* graphiql: true,
|
|
36
42
|
* },
|
|
@@ -40,8 +46,18 @@ type SchemaProvider = () => GraphQLSchema | Promise<GraphQLSchema>;
|
|
|
40
46
|
interface PostGraphileConfig {
|
|
41
47
|
/** Configuration type discriminator */
|
|
42
48
|
type: 'postgraphile';
|
|
43
|
-
/**
|
|
44
|
-
|
|
49
|
+
/**
|
|
50
|
+
* Path to PostGraphile preset file
|
|
51
|
+
*
|
|
52
|
+
* The preset file must export the preset configuration using default export:
|
|
53
|
+
* `export default { extends: [...], pgServices: [...], plugins: [...] }`
|
|
54
|
+
*
|
|
55
|
+
* A PostGraphile instance will be created from this preset at build time.
|
|
56
|
+
*
|
|
57
|
+
* @example './server/graphile.preset.ts'
|
|
58
|
+
* @example './server/graphile.preset.js'
|
|
59
|
+
*/
|
|
60
|
+
preset: string;
|
|
45
61
|
/** GraphQL endpoint URL (default: '/graphql/') */
|
|
46
62
|
url?: string;
|
|
47
63
|
/** Whether to enable GraphiQL IDE (default: true in dev, false in prod) */
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
|
-
import {
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { useLogger, defineNuxtModule, createResolver } from '@nuxt/kit';
|
|
4
5
|
|
|
5
6
|
const logger = useLogger("@stonecrop/nuxt-grafserv");
|
|
6
7
|
function validateConfig(options) {
|
|
@@ -77,19 +78,53 @@ const module$1 = defineNuxtModule({
|
|
|
77
78
|
logger.info(`Grafserv server alias: ${config.alias["#grafserv-server"]}`);
|
|
78
79
|
if (options.type === "postgraphile") {
|
|
79
80
|
logger.info("Using PostGraphile preset configuration");
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
let presetPath = resolveForVirtualModule(options.preset);
|
|
82
|
+
if (!existsSync(presetPath)) {
|
|
83
|
+
const extensions = [".ts", ".js", ".mjs"];
|
|
84
|
+
let found = false;
|
|
85
|
+
for (const ext of extensions) {
|
|
86
|
+
const pathWithExt = presetPath + ext;
|
|
87
|
+
if (existsSync(pathWithExt)) {
|
|
88
|
+
presetPath = pathWithExt;
|
|
89
|
+
found = true;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
85
92
|
}
|
|
86
|
-
|
|
93
|
+
if (!found) {
|
|
94
|
+
throw new Error(
|
|
95
|
+
`[@stonecrop/nuxt-grafserv] Preset file not found: ${presetPath}
|
|
96
|
+
Tried extensions: ${extensions.join(", ")}
|
|
97
|
+
|
|
98
|
+
Create the preset file with your PostGraphile configuration:
|
|
99
|
+
|
|
100
|
+
// ${options.preset}.ts (or .js, .mjs)
|
|
101
|
+
import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
|
|
102
|
+
import { makePgService } from 'postgraphile/adaptors/pg'
|
|
103
|
+
|
|
104
|
+
export default {
|
|
105
|
+
extends: [PostGraphileAmberPreset],
|
|
106
|
+
pgServices: [makePgService({ connectionString: process.env.DATABASE_URL, schemas: ['public'] })],
|
|
107
|
+
plugins: [],
|
|
108
|
+
}
|
|
109
|
+
`
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
logger.info(`Resolved preset path: ${presetPath}`);
|
|
114
|
+
config.virtual = config.virtual || {};
|
|
115
|
+
config.virtual["#internal/grafserv/pgl"] = [
|
|
116
|
+
`import { postgraphile } from 'postgraphile'`,
|
|
117
|
+
`import preset from '${presetPath}'`,
|
|
118
|
+
``,
|
|
119
|
+
`// Create PostGraphile instance with the preset`,
|
|
120
|
+
`// This handles schema building, watch mode, and lifecycle`,
|
|
121
|
+
`export const pgl = postgraphile(preset)`
|
|
122
|
+
].join("\n");
|
|
87
123
|
config.runtimeConfig = config.runtimeConfig || {};
|
|
88
124
|
config.runtimeConfig.grafserv = {
|
|
89
125
|
type: "postgraphile",
|
|
90
126
|
url: options.url || "/graphql/",
|
|
91
|
-
graphiql: options.graphiql
|
|
92
|
-
presetPath: template.dst
|
|
127
|
+
graphiql: options.graphiql
|
|
93
128
|
};
|
|
94
129
|
} else if (options.type === "schema") {
|
|
95
130
|
logger.info("Using schema configuration");
|
|
@@ -128,7 +163,11 @@ const module$1 = defineNuxtModule({
|
|
|
128
163
|
config.externals = config.externals || {};
|
|
129
164
|
config.externals.external = config.externals.external || [];
|
|
130
165
|
config.externals.external.push(
|
|
166
|
+
"graphql",
|
|
131
167
|
"grafast",
|
|
168
|
+
"postgraphile",
|
|
169
|
+
"graphile-config",
|
|
170
|
+
"graphile-build",
|
|
132
171
|
"@graphql-tools/schema",
|
|
133
172
|
"@graphql-tools/load",
|
|
134
173
|
"@graphql-tools/graphql-file-loader"
|
|
@@ -136,6 +175,11 @@ const module$1 = defineNuxtModule({
|
|
|
136
175
|
const grafastPath = require.resolve("grafast");
|
|
137
176
|
config.alias = config.alias || {};
|
|
138
177
|
config.alias["grafast"] = grafastPath;
|
|
178
|
+
config.typescript = config.typescript || {};
|
|
179
|
+
config.typescript.tsConfig = config.typescript.tsConfig || {};
|
|
180
|
+
config.typescript.tsConfig.compilerOptions = config.typescript.tsConfig.compilerOptions || {};
|
|
181
|
+
config.typescript.tsConfig.compilerOptions.allowImportingTsExtensions = true;
|
|
182
|
+
config.typescript.tsConfig.compilerOptions.moduleResolution = "bundler";
|
|
139
183
|
});
|
|
140
184
|
nuxt.hook("nitro:config", (config) => {
|
|
141
185
|
config.handlers = config.handlers || [];
|
|
@@ -170,7 +214,8 @@ const module$1 = defineNuxtModule({
|
|
|
170
214
|
nuxt.hook("builder:watch", async (event, path) => {
|
|
171
215
|
const isSchemaFile = path.endsWith(".graphql");
|
|
172
216
|
const isResolverFile = options.type === "schema" && options.resolvers && path.includes(options.resolvers.replace("./", ""));
|
|
173
|
-
|
|
217
|
+
const isPresetFile = options.type === "postgraphile" && path.includes(options.preset.replace("./", ""));
|
|
218
|
+
if (isSchemaFile || isResolverFile || isPresetFile) {
|
|
174
219
|
if (!cacheClearing) {
|
|
175
220
|
cacheClearing = true;
|
|
176
221
|
try {
|
package/dist/runtime/handler.js
CHANGED
|
@@ -19,25 +19,19 @@ async function getSchema(options) {
|
|
|
19
19
|
}
|
|
20
20
|
let schema;
|
|
21
21
|
if (options.type === "postgraphile") {
|
|
22
|
-
console.debug("[@stonecrop/nuxt-grafserv]
|
|
22
|
+
console.debug("[@stonecrop/nuxt-grafserv] Getting schema from PostGraphile instance");
|
|
23
23
|
try {
|
|
24
|
-
const {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
const presetModule = await import(config.grafserv.presetPath);
|
|
30
|
-
const preset = presetModule.preset;
|
|
31
|
-
const result = await makeSchema(preset);
|
|
32
|
-
schema = result.schema;
|
|
33
|
-
console.debug("[@stonecrop/nuxt-grafserv] PostGraphile schema created successfully");
|
|
24
|
+
const { pgl } = await import("#internal/grafserv/pgl");
|
|
25
|
+
console.debug("[@stonecrop/nuxt-grafserv] Calling pgl.getSchema()");
|
|
26
|
+
schema = await pgl.getSchema();
|
|
27
|
+
console.debug("[@stonecrop/nuxt-grafserv] PostGraphile schema retrieved successfully");
|
|
34
28
|
} catch (error) {
|
|
35
29
|
if (error instanceof Error && "code" in error && error.code === "MODULE_NOT_FOUND") {
|
|
36
30
|
throw new Error(
|
|
37
31
|
'[@stonecrop/nuxt-grafserv] PostGraphile preset provided but "postgraphile" package not found. Install it with: npm install postgraphile'
|
|
38
32
|
);
|
|
39
33
|
}
|
|
40
|
-
console.error("[@stonecrop/nuxt-grafserv] Error
|
|
34
|
+
console.error("[@stonecrop/nuxt-grafserv] Error getting PostGraphile schema:", error);
|
|
41
35
|
throw error;
|
|
42
36
|
}
|
|
43
37
|
} else if (options.type === "schema") {
|
|
@@ -80,7 +74,9 @@ async function getSchema(options) {
|
|
|
80
74
|
}
|
|
81
75
|
}
|
|
82
76
|
} else {
|
|
83
|
-
throw new Error(
|
|
77
|
+
throw new Error(
|
|
78
|
+
`[@stonecrop/nuxt-grafserv] Invalid configuration type: ${options.type}`
|
|
79
|
+
);
|
|
84
80
|
}
|
|
85
81
|
cachedSchema = schema;
|
|
86
82
|
return schema;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stonecrop/nuxt-grafserv",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.9",
|
|
4
4
|
"description": "Pluggable Grafserv GraphQL server as Nuxt Module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"grafast": "^1.0.0-rc.4",
|
|
44
44
|
"grafserv": "^1.0.0-rc.4",
|
|
45
45
|
"graphql": "^16.12.0",
|
|
46
|
-
"@stonecrop/graphql-middleware": "0.7.
|
|
46
|
+
"@stonecrop/graphql-middleware": "0.7.9"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@eslint/js": "^9.39.2",
|