@stonecrop/nuxt-grafserv 0.7.5 → 0.7.6

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 CHANGED
@@ -63,8 +63,8 @@ export default defineNuxtConfig({
63
63
 
64
64
  | Option | Type | Default | Description |
65
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 |
66
+ | `schema` | `string \| string[] \| SchemaProvider \| PostGraphileInstance` | `'server/**/*.graphql'` | Path(s) to GraphQL schema files, schema provider function, or PostGraphile instance |
67
+ | `resolvers` | `string` | `undefined` | Path to resolvers file (optional - not needed for PostGraphile) |
68
68
  | `url` | `string` | `'/graphql/'` | GraphQL endpoint URL (also serves Ruru UI) |
69
69
  | `graphiql` | `boolean` | `true` in dev, `false` in prod | Enable GraphiQL IDE |
70
70
  | `preset` | `GraphileConfig.Preset` | `undefined` | Custom Graphile preset for advanced configuration |
@@ -238,6 +238,134 @@ export default [loggingPlugin, authPlugin]
238
238
 
239
239
  ## Advanced Usage
240
240
 
241
+ ### PostGraphile Integration
242
+
243
+ This module has first-class support for PostGraphile, enabling instant GraphQL APIs from PostgreSQL databases. PostGraphile generates the complete schema and resolvers, so you don't need to define them manually.
244
+
245
+ #### Setup with PostGraphile
246
+
247
+ 1. Install PostGraphile:
248
+
249
+ ```bash
250
+ pnpm add postgraphile @graphile/crystal graphile-build-pg
251
+ ```
252
+
253
+ 2. Create a PostGraphile schema provider (`server/graphql/schema.ts`):
254
+
255
+ ```typescript
256
+ import { postgraphile } from 'postgraphile'
257
+ import type { GraphQLSchema } from 'graphql'
258
+
259
+ // Define your PostGraphile preset
260
+ const preset = {
261
+ pgServices: [
262
+ {
263
+ name: 'main',
264
+ connectionString: process.env.DATABASE_URL || 'postgres://localhost/mydb',
265
+ schemas: ['public'],
266
+ },
267
+ ],
268
+ grafserv: {
269
+ websockets: false, // Disable websockets for Nuxt compatibility
270
+ },
271
+ }
272
+
273
+ // Create PostGraphile instance
274
+ const pgl = postgraphile(preset)
275
+
276
+ // Export schema provider function
277
+ export async function createPostGraphileSchema(): Promise<GraphQLSchema> {
278
+ const { schema } = await pgl.getSchemaResult()
279
+ return schema
280
+ }
281
+
282
+ // Export the instance if you need direct access
283
+ export { pgl }
284
+ ```
285
+
286
+ 3. Configure Nuxt to use the PostGraphile schema:
287
+
288
+ ```typescript
289
+ // nuxt.config.ts
290
+ import { createPostGraphileSchema } from './server/graphql/schema'
291
+
292
+ export default defineNuxtConfig({
293
+ modules: ['@stonecrop/nuxt-grafserv'],
294
+ grafserv: {
295
+ // Use PostGraphile schema provider function
296
+ schema: createPostGraphileSchema,
297
+ // No resolvers needed - PostGraphile generates everything
298
+ url: '/graphql',
299
+ graphiql: true, // Enable Ruru IDE
300
+ }
301
+ })
302
+ ```
303
+
304
+ #### Direct PostGraphile Instance Usage
305
+
306
+ You can also pass a PostGraphile instance directly:
307
+
308
+ ```typescript
309
+ // nuxt.config.ts
310
+ import { pgl } from './server/graphql/schema'
311
+
312
+ export default defineNuxtConfig({
313
+ grafserv: {
314
+ schema: pgl, // Pass PostGraphile instance directly
315
+ url: '/graphql',
316
+ }
317
+ })
318
+ ```
319
+
320
+ #### PostGraphile with Custom Plugins
321
+
322
+ Enhance your PostGraphile setup with custom plugins:
323
+
324
+ ```typescript
325
+ // server/graphql/schema.ts
326
+ import { postgraphile } from 'postgraphile'
327
+ import { PostGraphileAmberPreset } from 'postgraphile/presets/amber'
328
+ import PgSimplifyInflectorPlugin from '@graphile-contrib/pg-simplify-inflector'
329
+
330
+ const preset = {
331
+ extends: [PostGraphileAmberPreset],
332
+ plugins: [PgSimplifyInflectorPlugin],
333
+ pgServices: [
334
+ {
335
+ name: 'main',
336
+ connectionString: process.env.DATABASE_URL,
337
+ schemas: ['public'],
338
+ },
339
+ ],
340
+ grafserv: {
341
+ websockets: false,
342
+ },
343
+ grafast: {
344
+ explain: process.env.NODE_ENV === 'development', // Enable plan diagrams in dev
345
+ },
346
+ schema: {
347
+ // Add custom behavior overrides
348
+ defaultBehavior: 'connection', // Enable Relay-style connections by default
349
+ },
350
+ }
351
+
352
+ const pgl = postgraphile(preset)
353
+
354
+ export async function createPostGraphileSchema() {
355
+ const { schema } = await pgl.getSchemaResult()
356
+ return schema
357
+ }
358
+ ```
359
+
360
+ #### Benefits of PostGraphile Integration
361
+
362
+ - **Zero Schema Definition**: Automatically generates GraphQL schema from PostgreSQL
363
+ - **Auto-Generated Resolvers**: All queries and mutations created from database schema
364
+ - **Real-time Subscriptions**: Live query support via PostgreSQL LISTEN/NOTIFY
365
+ - **Row-Level Security**: Leverages PostgreSQL RLS for authorization
366
+ - **High Performance**: Uses Grafast execution engine with intelligent batching
367
+ - **Type Safety**: Full TypeScript support for generated schema
368
+
241
369
  ### Custom Graphile Preset
242
370
 
243
371
  Leverage the full power of the Graphile ecosystem with custom presets:
package/dist/module.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { NuxtModule } from '@nuxt/schema';
2
+ import { PromiseOrDirect } from 'grafast';
2
3
  import { GraphQLSchema } from 'graphql';
3
4
  import { GraphileConfig } from 'graphile-config';
4
5
 
@@ -6,13 +7,23 @@ import { GraphileConfig } from 'graphile-config';
6
7
  * Schema provider function - returns a GraphQL schema
7
8
  */
8
9
  type SchemaProvider = () => GraphQLSchema | Promise<GraphQLSchema>;
10
+ /**
11
+ * PostGraphile instance interface (minimal type for compatibility)
12
+ */
13
+ interface PostGraphileInstance {
14
+ getSchema(): PromiseOrDirect<GraphQLSchema>;
15
+ getSchemaResult(): PromiseOrDirect<{
16
+ schema: GraphQLSchema;
17
+ resolvedPreset: GraphileConfig.ResolvedPreset;
18
+ }>;
19
+ }
9
20
  /**
10
21
  * Configuration for the Grafast module
11
22
  */
12
23
  interface ModuleOptions {
13
- /** Path to schema file(s) or a schema provider function */
14
- schema?: string | string[] | SchemaProvider;
15
- /** Path to resolvers file (for .graphql schema files) */
24
+ /** Path to schema file(s), a schema provider function, or a PostGraphile instance */
25
+ schema?: string | string[] | SchemaProvider | PostGraphileInstance;
26
+ /** Path to resolvers file (optional, only needed for .graphql schema files without PostGraphile) */
16
27
  resolvers?: string;
17
28
  /** GraphQL endpoint URL (default: '/graphql/') */
18
29
  url?: string;
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt-grafserv",
3
3
  "configKey": "grafserv",
4
- "version": "0.7.5",
4
+ "version": "0.7.6",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
package/dist/module.mjs CHANGED
@@ -10,7 +10,8 @@ const module$1 = defineNuxtModule({
10
10
  },
11
11
  defaults: (_nuxt) => ({
12
12
  schema: "server/**/*.graphql",
13
- resolvers: "server/resolvers.ts",
13
+ resolvers: void 0,
14
+ // Optional - not needed for PostGraphile setups
14
15
  url: "/graphql/",
15
16
  graphiql: void 0,
16
17
  // Will default based on dev mode
@@ -44,15 +45,31 @@ const module$1 = defineNuxtModule({
44
45
  logger.info(`Nuxt rootDir: ${nuxt.options.rootDir}`);
45
46
  logger.info(`Grafserv server alias: ${config.alias["#grafserv-server"]}`);
46
47
  const resolverPath = options.resolvers ? resolveForVirtualModule(options.resolvers) : void 0;
47
- logger.info(`Resolved resolver path: ${resolverPath}`);
48
+ if (resolverPath) {
49
+ logger.info(`Resolved resolver path: ${resolverPath}`);
50
+ } else {
51
+ logger.info("No resolvers configured (normal for PostGraphile setups)");
52
+ }
53
+ let runtimeSchema;
54
+ if (typeof options.schema === "function" || options.schema && typeof options.schema === "object" && "getSchema" in options.schema) {
55
+ runtimeSchema = options.schema;
56
+ logger.info("Using schema provider function or PostGraphile instance");
57
+ } else if (typeof options.schema === "string") {
58
+ runtimeSchema = resolveForSchema(options.schema);
59
+ logger.info(`Resolved schema path: ${runtimeSchema}`);
60
+ } else if (Array.isArray(options.schema)) {
61
+ runtimeSchema = options.schema.map((s) => resolveForSchema(s));
62
+ logger.info(`Resolved schema paths: ${runtimeSchema.join(", ")}`);
63
+ } else {
64
+ runtimeSchema = options.schema;
65
+ }
48
66
  config.runtimeConfig = config.runtimeConfig || {};
49
67
  config.runtimeConfig.grafserv = {
50
68
  ...options,
51
69
  // Pass resolved resolver path for direct import
52
70
  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
55
- // function passed through
71
+ // Pass schema (either resolved paths or function/instance)
72
+ schema: runtimeSchema
56
73
  };
57
74
  config.virtual = config.virtual || {};
58
75
  if (resolverPath) {
@@ -13,12 +13,29 @@ async function loadTypeDefsFromFiles(schemaPath) {
13
13
  });
14
14
  return sources.map((source) => source.document).filter(Boolean);
15
15
  }
16
+ function isPostGraphileInstance(value) {
17
+ return value !== null && typeof value === "object" && "getSchema" in value && typeof value.getSchema === "function";
18
+ }
16
19
  async function getSchema(options) {
17
20
  if (cachedSchema) {
18
21
  return cachedSchema;
19
22
  }
20
23
  let schema;
21
- if (typeof options.schema === "function") {
24
+ if (isPostGraphileInstance(options.schema)) {
25
+ console.debug("[@stonecrop/nuxt-grafserv] Using PostGraphile instance for schema");
26
+ try {
27
+ if ("getSchemaResult" in options.schema && typeof options.schema.getSchemaResult === "function") {
28
+ const result = await options.schema.getSchemaResult();
29
+ schema = result.schema;
30
+ } else {
31
+ schema = await options.schema.getSchema();
32
+ }
33
+ console.debug("[@stonecrop/nuxt-grafserv] PostGraphile schema loaded successfully");
34
+ } catch (error) {
35
+ console.error("[@stonecrop/nuxt-grafserv] Error loading PostGraphile schema:", error);
36
+ throw error;
37
+ }
38
+ } else if (typeof options.schema === "function") {
22
39
  schema = await options.schema();
23
40
  } else if (options.schema) {
24
41
  const typeDefDocs = await loadTypeDefsFromFiles(options.schema);
@@ -38,8 +55,12 @@ async function getSchema(options) {
38
55
  }
39
56
  } catch (e) {
40
57
  console.error("[@stonecrop/nuxt-grafserv] Error loading resolvers:", e);
41
- console.warn("[@stonecrop/nuxt-grafserv] Could not load resolvers:", e);
58
+ console.warn("[@stonecrop/nuxt-grafserv] Continuing without resolvers - this is normal for PostGraphile setups");
42
59
  }
60
+ } else {
61
+ console.debug(
62
+ "[@stonecrop/nuxt-grafserv] No resolvers specified - using schema-only mode (normal for PostGraphile)"
63
+ );
43
64
  }
44
65
  try {
45
66
  schema = makeGrafastSchema({
@@ -52,7 +73,9 @@ async function getSchema(options) {
52
73
  throw error;
53
74
  }
54
75
  } else {
55
- throw new Error("[@stonecrop/nuxt-grafserv] No schema provided. Configure schema path or provider function.");
76
+ throw new Error(
77
+ "[@stonecrop/nuxt-grafserv] No schema provided. Configure schema path, provider function, or PostGraphile instance."
78
+ );
56
79
  }
57
80
  cachedSchema = schema;
58
81
  return schema;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stonecrop/nuxt-grafserv",
3
- "version": "0.7.5",
3
+ "version": "0.7.6",
4
4
  "description": "Pluggable Grafserv GraphQL server as Nuxt Module",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,7 +44,7 @@
44
44
  "grafserv": "^1.0.0-rc.4",
45
45
  "graphile-config": "^1.0.0-rc.3",
46
46
  "graphql": "^16.12.0",
47
- "@stonecrop/graphql-middleware": "0.7.5"
47
+ "@stonecrop/graphql-middleware": "0.7.6"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@casl/ability": "^6.8.0",
@@ -63,16 +63,17 @@
63
63
  "eslint": "^9.39.2",
64
64
  "jsdom": "^27.4.0",
65
65
  "nuxt": "^4.2.2",
66
+ "postgraphile": "^5.0.0-rc.4",
66
67
  "typescript": "^5.9.3",
67
68
  "vite": "^7.3.1",
68
69
  "vitest": "^4.0.17",
69
70
  "vue-tsc": "^3.2.2",
70
- "@stonecrop/casl-middleware": "0.7.5",
71
- "@stonecrop/rockfoil": "0.7.5"
71
+ "@stonecrop/casl-middleware": "0.7.6",
72
+ "@stonecrop/rockfoil": "0.7.6"
72
73
  },
73
74
  "peerDependencies": {
74
- "@stonecrop/casl-middleware": "0.7.5",
75
- "@stonecrop/rockfoil": "0.7.5"
75
+ "@stonecrop/casl-middleware": "0.7.6",
76
+ "@stonecrop/rockfoil": "0.7.6"
76
77
  },
77
78
  "peerDependenciesMeta": {
78
79
  "@stonecrop/casl-middleware": {
@@ -94,6 +95,7 @@
94
95
  "test": "vitest run",
95
96
  "test:ci": "vitest run --run",
96
97
  "test:coverage": "vitest run --coverage",
98
+ "test:e2e": "vitest run test/e2e",
97
99
  "test:watch": "vitest watch",
98
100
  "test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit"
99
101
  }