polen 0.11.0-next.7 → 0.11.0-next.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.
Files changed (86) hide show
  1. package/build/api/config/configurator.d.ts +35 -4
  2. package/build/api/config/configurator.d.ts.map +1 -1
  3. package/build/api/config/configurator.js.map +1 -1
  4. package/build/api/schema/data-sources/data-sources.d.ts +1 -0
  5. package/build/api/schema/data-sources/data-sources.d.ts.map +1 -1
  6. package/build/api/schema/data-sources/data-sources.js +1 -0
  7. package/build/api/schema/data-sources/data-sources.js.map +1 -1
  8. package/build/api/schema/data-sources/introspection/introspection.d.ts +83 -0
  9. package/build/api/schema/data-sources/introspection/introspection.d.ts.map +1 -0
  10. package/build/api/schema/data-sources/introspection/introspection.js +110 -0
  11. package/build/api/schema/data-sources/introspection/introspection.js.map +1 -0
  12. package/build/api/schema/read.d.ts +83 -9
  13. package/build/api/schema/read.d.ts.map +1 -1
  14. package/build/api/schema/read.js +15 -6
  15. package/build/api/schema/read.js.map +1 -1
  16. package/build/api/schema-source/schema-source.d.ts +1 -1
  17. package/build/api/schema-source/schema-source.d.ts.map +1 -1
  18. package/build/api/schema-source/schema-source.js.map +1 -1
  19. package/build/api/vite/plugins/core.js +8 -8
  20. package/build/api/vite/plugins/core.js.map +1 -1
  21. package/build/api/vite/plugins/schema-assets.d.ts.map +1 -1
  22. package/build/api/vite/plugins/schema-assets.js +52 -11
  23. package/build/api/vite/plugins/schema-assets.js.map +1 -1
  24. package/build/cli/commands/open.js +1 -1
  25. package/build/cli/commands/open.js.map +1 -1
  26. package/build/lib/grafaid/schema/schema.d.ts +1 -1
  27. package/build/lib/grafaid/schema/schema.d.ts.map +1 -1
  28. package/build/lib/grafaid/schema/schema.js +1 -1
  29. package/build/lib/grafaid/schema/schema.js.map +1 -1
  30. package/build/lib/kit-temp.js +2 -2
  31. package/build/lib/kit-temp.js.map +1 -1
  32. package/build/lib/react-router-aid/react-router-aid.d.ts +5 -3
  33. package/build/lib/react-router-aid/react-router-aid.d.ts.map +1 -1
  34. package/build/lib/react-router-aid/react-router-aid.js +7 -4
  35. package/build/lib/react-router-aid/react-router-aid.js.map +1 -1
  36. package/build/template/routes/changelog.js +2 -2
  37. package/build/template/routes/changelog.js.map +1 -1
  38. package/build/template/routes/index.js +2 -2
  39. package/build/template/routes/index.js.map +1 -1
  40. package/build/template/routes/pages.js +2 -2
  41. package/build/template/routes/pages.js.map +1 -1
  42. package/build/template/routes/reference.d.ts +27 -4
  43. package/build/template/routes/reference.d.ts.map +1 -1
  44. package/build/template/routes/reference.js +76 -17
  45. package/build/template/routes/reference.js.map +1 -1
  46. package/build/template/routes/root.js +3 -3
  47. package/build/template/routes/root.js.map +1 -1
  48. package/build/template/sources/schema-source.d.ts +1 -1
  49. package/package.json +1 -1
  50. package/src/api/config/configurator.ts +35 -4
  51. package/src/api/schema/data-sources/data-sources.ts +1 -0
  52. package/src/api/schema/data-sources/introspection/introspection.ts +213 -0
  53. package/src/api/schema/read.ts +107 -16
  54. package/src/api/schema-source/schema-source.ts +3 -3
  55. package/src/api/vite/plugins/core.ts +8 -8
  56. package/src/api/vite/plugins/schema-assets.ts +59 -12
  57. package/src/cli/commands/open.ts +1 -1
  58. package/src/lib/grafaid/schema/schema.ts +1 -0
  59. package/src/lib/kit-temp.ts +2 -2
  60. package/src/lib/mask/$.test.ts +3 -3
  61. package/src/lib/react-router-aid/react-router-aid.ts +12 -6
  62. package/src/template/routes/changelog.tsx +2 -2
  63. package/src/template/routes/index.tsx +2 -2
  64. package/src/template/routes/pages.tsx +2 -2
  65. package/src/template/routes/reference.tsx +83 -17
  66. package/src/template/routes/root.tsx +3 -3
  67. package/build/template/routes/reference.$type.$field.d.ts +0 -5
  68. package/build/template/routes/reference.$type.$field.d.ts.map +0 -1
  69. package/build/template/routes/reference.$type.$field.js +0 -31
  70. package/build/template/routes/reference.$type.$field.js.map +0 -1
  71. package/build/template/routes/reference.$type.d.ts +0 -9
  72. package/build/template/routes/reference.$type.d.ts.map +0 -1
  73. package/build/template/routes/reference.$type.js +0 -25
  74. package/build/template/routes/reference.$type.js.map +0 -1
  75. package/build/template/routes/reference.version.$version.$type.$field.d.ts +0 -6
  76. package/build/template/routes/reference.version.$version.$type.$field.d.ts.map +0 -1
  77. package/build/template/routes/reference.version.$version.$type.$field.js +0 -32
  78. package/build/template/routes/reference.version.$version.$type.$field.js.map +0 -1
  79. package/build/template/routes/reference.version.$version.$type.d.ts +0 -11
  80. package/build/template/routes/reference.version.$version.$type.d.ts.map +0 -1
  81. package/build/template/routes/reference.version.$version.$type.js +0 -26
  82. package/build/template/routes/reference.version.$version.$type.js.map +0 -1
  83. package/src/template/routes/reference.$type.$field.tsx +0 -34
  84. package/src/template/routes/reference.$type.tsx +0 -29
  85. package/src/template/routes/reference.version.$version.$type.$field.tsx +0 -35
  86. package/src/template/routes/reference.version.$version.$type.tsx +0 -30
@@ -1,17 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { GrafaidOld } from '#lib/grafaid-old/index';
3
- import { createRoute } from '#lib/react-router-aid/react-router-aid';
3
+ import { Grafaid } from '#lib/grafaid/index';
4
+ import { route, routeIndex } from '#lib/react-router-aid/react-router-aid';
4
5
  import { createLoader, useLoaderData } from '#lib/react-router-loader/react-router-loader';
5
6
  import { Box } from '@radix-ui/themes';
6
- import { Outlet } from 'react-router';
7
+ import { Outlet, useParams, useRouteLoaderData } from 'react-router';
8
+ import { Field } from '../components/Field.js';
7
9
  import { MissingSchema } from '../components/MissingSchema.js';
10
+ import { NamedType } from '../components/NamedType.js';
8
11
  import { VersionSelector } from '../components/VersionSelector.js';
9
12
  import { SidebarLayout } from '../layouts/index.js';
10
13
  import { VERSION_LATEST } from '../lib/schema-utils/constants.js';
11
14
  import { schemaSource } from '../sources/schema-source.js';
12
- import { reference$type } from './reference.$type.js';
13
- import { referenceVersion$version$type } from './reference.version.$version.$type.js';
14
- const loader = createLoader(async ({ params }) => {
15
+ export const loader = createLoader(async ({ params }) => {
15
16
  // Handle both versioned and unversioned routes:
16
17
  // - Versioned: /reference/version/:version/:type → params.version exists
17
18
  // - Unversioned: /reference/:type → params.version is undefined, defaults to latest
@@ -24,7 +25,7 @@ const loader = createLoader(async ({ params }) => {
24
25
  availableVersions,
25
26
  };
26
27
  });
27
- const Component = () => {
28
+ const RouteReferenceComponent = () => {
28
29
  const data = useLoaderData();
29
30
  if (!data.schema) {
30
31
  return _jsx(MissingSchema, {});
@@ -53,18 +54,76 @@ const Component = () => {
53
54
  }
54
55
  return (_jsxs(SidebarLayout, { sidebar: sidebarItems, children: [_jsx(Box, { mb: `4`, children: _jsx(VersionSelector, { availableVersions: data.availableVersions, currentVersion: data.currentVersion }) }), _jsx(Outlet, {})] }));
55
56
  };
56
- // Create the versioned reference route with explicit version prefix
57
- const referenceVersioned = createRoute({
58
- path: `version/:version`,
59
- loader,
60
- Component,
61
- children: [referenceVersion$version$type],
62
- });
63
- // Create the main reference route with explicit version path and fallback type path
64
- export const reference = createRoute({
57
+ // Shared hooks for schema data validation and retrieval
58
+ const useReferenceSchema = () => {
59
+ const data = useRouteLoaderData('reference');
60
+ if (!data?.schema) {
61
+ throw new Error('Schema not found');
62
+ }
63
+ return data;
64
+ };
65
+ const useSchemaType = (typeName) => {
66
+ const { schema } = useReferenceSchema();
67
+ const type = schema.getType(typeName);
68
+ if (!type) {
69
+ throw new Error(`Could not find type ${typeName}`);
70
+ }
71
+ return type;
72
+ };
73
+ const useSchemaField = (typeName, fieldName) => {
74
+ const type = useSchemaType(typeName);
75
+ if (!Grafaid.Schema.TypesLike.isFielded(type)) {
76
+ throw new Error(`Type ${typeName} does not have fields`);
77
+ }
78
+ const fields = type.getFields();
79
+ const field = fields[fieldName];
80
+ if (!field) {
81
+ throw new Error(`Could not find field ${fieldName} on type ${typeName}`);
82
+ }
83
+ return field;
84
+ };
85
+ const RouteComponentIndex = () => {
86
+ return _jsx("div", { children: "Select a type from the sidebar to view its documentation." });
87
+ };
88
+ const RouteComponentType = () => {
89
+ const params = useParams();
90
+ const type = useSchemaType(params.type);
91
+ return _jsx(NamedType, { data: type });
92
+ };
93
+ const RouteComponentTypeField = () => {
94
+ const params = useParams();
95
+ const field = useSchemaField(params.type, params.field);
96
+ return _jsx(Field, { data: field });
97
+ };
98
+ const typeAndFieldRoutes = [
99
+ routeIndex(RouteComponentIndex),
100
+ route({
101
+ path: `:type`,
102
+ Component: RouteComponentType,
103
+ errorElement: _jsx(MissingSchema, {}),
104
+ children: [
105
+ route({
106
+ path: `:field`,
107
+ Component: RouteComponentTypeField,
108
+ errorElement: _jsx(MissingSchema, {}),
109
+ }),
110
+ ],
111
+ }),
112
+ ];
113
+ /**
114
+ * Reference documentation with proper nested structure - all routes in one file
115
+ */
116
+ export const reference = route({
117
+ id: 'reference',
65
118
  path: `reference`,
66
119
  loader,
67
- Component,
68
- children: [referenceVersioned, reference$type],
120
+ Component: RouteReferenceComponent,
121
+ children: [
122
+ ...typeAndFieldRoutes,
123
+ route({
124
+ path: `version/:version`,
125
+ children: typeAndFieldRoutes,
126
+ }),
127
+ ],
69
128
  });
70
129
  //# sourceMappingURL=reference.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reference.js","sourceRoot":"","sources":["../../../src/template/routes/reference.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"reference.js","sourceRoot":"","sources":["../../../src/template/routes/reference.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { createRoute } from '#lib/react-router-aid/react-router-aid';
2
+ import { route } from '#lib/react-router-aid/react-router-aid';
3
3
  import { Box, Flex, Theme } from '@radix-ui/themes';
4
4
  import { Link as LinkReactRouter } from 'react-router';
5
5
  import { Outlet, ScrollRestoration } from 'react-router';
@@ -50,7 +50,7 @@ if (PROJECT_SCHEMA) {
50
50
  //
51
51
  //
52
52
  //
53
- const notFoundRoute = createRoute({
53
+ const notFoundRoute = route({
54
54
  id: `*_not_found`,
55
55
  path: `*`,
56
56
  Component: NotFound,
@@ -65,7 +65,7 @@ children.push(notFoundRoute);
65
65
  // ━━━━━━━━━━━━━━ • Root Route
66
66
  //
67
67
  //
68
- export const root = createRoute({
68
+ export const root = route({
69
69
  path: `/`,
70
70
  Component,
71
71
  children,
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../../src/template/routes/root.tsx"],"names":[],"mappings":"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"}
@@ -10,6 +10,6 @@ export declare const schemaSource: {
10
10
  clearAllAssets: () => Promise<void>;
11
11
  removeAsset: (version: string) => Promise<void>;
12
12
  writeMetadata: (metadata: import("../../api/schema/metadata.js").SchemaMetadata) => Promise<void>;
13
- writeAllAssets: (schemaData: Awaited<ReturnType<typeof import("../../api/schema/read.js").readOrThrow>>, metadata: import("../../api/schema/metadata.js").SchemaMetadata) => Promise<void>;
13
+ writeAllAssets: (schemaData: Awaited<ReturnType<typeof import("../../api/schema/read.js").readOrThrow>>["data"], metadata: import("../../api/schema/metadata.js").SchemaMetadata) => Promise<void>;
14
14
  };
15
15
  //# sourceMappingURL=schema-source.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polen",
3
- "version": "0.11.0-next.7",
3
+ "version": "0.11.0-next.9",
4
4
  "type": "module",
5
5
  "description": "A framework for delightful GraphQL developer portals",
6
6
  "author": {
@@ -31,25 +31,56 @@ export interface ConfigInput {
31
31
  * - `file` - Load from a single SDL file (default: schema.graphql)
32
32
  * - `directory` - Load multiple SDL files with date prefixes (enables changelog)
33
33
  * - `memory` - Define schemas programmatically in configuration
34
+ * - `introspection` - Fetch schema from a GraphQL endpoint
35
+ * - `data` - Use pre-built schema objects
34
36
  *
35
37
  * @example
36
38
  * ```ts
37
- * // Single file
39
+ * // Default: looks for schema.graphql
40
+ * schema: {}
41
+ *
42
+ * // Load via introspection
38
43
  * schema: {
39
- * useDataSources: 'file',
40
44
  * dataSources: {
41
- * file: { path: './my-schema.graphql' }
45
+ * introspection: {
46
+ * url: 'https://api.example.com/graphql',
47
+ * headers: { 'Authorization': `Bearer ${process.env.API_TOKEN}` }
48
+ * }
42
49
  * }
43
50
  * }
44
51
  *
45
52
  * // Multiple versions for changelog
46
53
  * schema: {
47
- * useDataSources: 'directory',
48
54
  * dataSources: {
49
55
  * directory: { path: './schema' }
50
56
  * }
51
57
  * }
58
+ *
59
+ * // Custom source order
60
+ * schema: {
61
+ * useDataSources: ['introspection', 'file'],
62
+ * dataSources: {
63
+ * introspection: { url: 'https://api.example.com/graphql' },
64
+ * file: { path: './fallback.graphql' }
65
+ * }
66
+ * }
52
67
  * ```
68
+ *
69
+ * **Two introspection features**:
70
+ * 1. **File Convention**: Polen auto-detects `schema.introspection.json` files
71
+ * 2. **Config-driven**: Polen fetches and caches introspection for you
72
+ *
73
+ * **Interoperability**: The `schema.introspection.json` file uses the standard
74
+ * GraphQL introspection format, compatible with GraphQL Codegen, Apollo CLI, etc.
75
+ *
76
+ * **Lifecycle**:
77
+ * - First run: Fetches from endpoint, saves to `schema.introspection.json`
78
+ * - Subsequent runs: Loads from JSON file (no network request)
79
+ * - To refresh: Delete the JSON file
80
+ * - Runs during `polen dev` and `polen build`, never at runtime
81
+ *
82
+ * **Query details**: Uses the standard introspection query from the GraphQL spec
83
+ * @see https://spec.graphql.org/draft/#sec-Introspection
53
84
  */
54
85
  schema?: SchemaConfigInput
55
86
  /**
@@ -1,3 +1,4 @@
1
+ export * as Introspection from './introspection/introspection.js'
1
2
  export * as Memory from './memory/memory.js'
2
3
  export * as SchemaDirectory from './schema-directory/schema-directory.js'
3
4
  export * as SchemaFile from './schema-file/schema-file.js'
@@ -0,0 +1,213 @@
1
+ import { Grafaid } from '#lib/grafaid/index'
2
+ import { GraphqlChange } from '#lib/graphql-change/index'
3
+ import type { GraphqlChangeset } from '#lib/graphql-changeset/index'
4
+ import { GraphqlSchemaLoader } from '#lib/graphql-schema-loader/index'
5
+ import { Fs, Json, Path } from '@wollybeard/kit'
6
+ import type { NonEmptyChangeSets, SchemaReadResult } from '../../schema.js'
7
+
8
+ /**
9
+ * Configuration for loading schema via GraphQL introspection.
10
+ *
11
+ * Polen supports two introspection features:
12
+ * 1. **File Convention**: Automatically detects `schema.introspection.json` if present
13
+ * 2. **Automatic Introspection**: Fetches from your endpoint and creates the file
14
+ *
15
+ * When configured, Polen will:
16
+ * - Execute the standard GraphQL introspection query against your endpoint
17
+ * - Save the result to `schema.introspection.json` in your project root
18
+ * - Use this cached file for subsequent builds (no network requests)
19
+ *
20
+ * The saved file contains a standard GraphQL introspection query result as defined
21
+ * in the GraphQL specification, making it compatible with any tool that works with
22
+ * introspection data (GraphQL Codegen, Apollo CLI, etc.).
23
+ *
24
+ * To refresh the schema, delete `schema.introspection.json` and rebuild.
25
+ *
26
+ * **Technical details**:
27
+ * - Uses Graffle's introspection extension
28
+ * - Performs the full introspection query (all types, fields, descriptions, etc.)
29
+ * - No customization of the query is currently supported
30
+ *
31
+ * @see https://spec.graphql.org/draft/#sec-Introspection - GraphQL Introspection spec
32
+ * @see https://github.com/graphql/graphql-js/blob/main/src/utilities/getIntrospectionQuery.ts - Reference implementation
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * // Basic introspection
37
+ * introspection: {
38
+ * url: 'https://api.example.com/graphql'
39
+ * }
40
+ *
41
+ * // With authentication
42
+ * introspection: {
43
+ * url: 'https://api.example.com/graphql',
44
+ * headers: {
45
+ * 'Authorization': `Bearer ${process.env.API_TOKEN}`
46
+ * }
47
+ * }
48
+ * ```
49
+ */
50
+ export interface ConfigInput {
51
+ /**
52
+ * The GraphQL endpoint URL to introspect.
53
+ *
54
+ * Must be a valid GraphQL endpoint that supports introspection queries.
55
+ *
56
+ * @example 'https://api.example.com/graphql'
57
+ */
58
+ url?: string
59
+ /**
60
+ * Optional headers to include in the introspection request.
61
+ *
62
+ * Use this for authentication, API keys, or any custom headers
63
+ * required by your GraphQL endpoint.
64
+ *
65
+ * @example
66
+ * ```ts
67
+ * headers: {
68
+ * 'Authorization': `Bearer ${process.env.API_TOKEN}`,
69
+ * 'X-API-Key': process.env.API_KEY
70
+ * }
71
+ * ```
72
+ */
73
+ headers?: Record<string, string>
74
+ projectRoot?: string
75
+ }
76
+
77
+ export interface Config {
78
+ url: string
79
+ headers?: Record<string, string>
80
+ projectRoot: string
81
+ }
82
+
83
+ export const normalizeConfig = (configInput: ConfigInput): Config => {
84
+ if (!configInput.url) {
85
+ throw new Error(`Introspection data source requires a URL`)
86
+ }
87
+
88
+ if (!configInput.projectRoot) {
89
+ throw new Error(`Introspection data source requires a projectRoot`)
90
+ }
91
+
92
+ const config: Config = {
93
+ url: configInput.url,
94
+ headers: configInput.headers,
95
+ projectRoot: configInput.projectRoot,
96
+ }
97
+
98
+ return config
99
+ }
100
+
101
+ const INTROSPECTION_FILE_NAME = `schema.introspection.json`
102
+
103
+ const getIntrospectionFilePath = (projectRoot: string) => {
104
+ return Path.join(projectRoot, INTROSPECTION_FILE_NAME)
105
+ }
106
+
107
+ export const readOrThrow = async (
108
+ configInput: ConfigInput,
109
+ ): Promise<SchemaReadResult> => {
110
+ const config = normalizeConfig(configInput)
111
+ const introspectionFilePath = getIntrospectionFilePath(config.projectRoot)
112
+
113
+ // Check if introspection file exists
114
+ const introspectionFileContent = await Fs.read(introspectionFilePath)
115
+ let schema: Grafaid.Schema.Schema
116
+
117
+ if (introspectionFileContent) {
118
+ // Load from existing file - no reCreate capability
119
+ try {
120
+ const introspectionData = Json.codec.decode(introspectionFileContent)
121
+
122
+ // Validate introspection data structure before passing to fromIntrospectionQuery
123
+ if (!introspectionData || typeof introspectionData !== 'object') {
124
+ throw new Error('Introspection data must be a valid JSON object')
125
+ }
126
+
127
+ // Allow fromIntrospectionQuery to handle validation of the introspection format
128
+ // It will provide more specific GraphQL-related error messages
129
+ if (!('data' in introspectionData)) {
130
+ throw new Error(
131
+ 'Introspection data missing required "data" property (expected GraphQL introspection result format)',
132
+ )
133
+ }
134
+
135
+ schema = Grafaid.Schema.fromIntrospectionQuery(introspectionData as any)
136
+ } catch (error) {
137
+ if (error instanceof SyntaxError) {
138
+ throw new Error(`Invalid JSON in ${introspectionFilePath}: ${error.message}`)
139
+ } else {
140
+ throw new Error(
141
+ `Invalid introspection data in ${introspectionFilePath}: ${
142
+ error instanceof Error ? error.message : String(error)
143
+ }. Delete this file to fetch fresh introspection data.`,
144
+ )
145
+ }
146
+ }
147
+
148
+ const schemaData = await createSingleSchemaChangeset(schema)
149
+ return {
150
+ data: schemaData,
151
+ source: { type: 'introspectionFile' },
152
+ }
153
+ } else {
154
+ // Fetch via introspection - can reCreate
155
+ const introspectionResult = await GraphqlSchemaLoader.load({
156
+ type: `introspect`,
157
+ url: config.url,
158
+ headers: config.headers,
159
+ })
160
+
161
+ schema = introspectionResult
162
+
163
+ // Get the raw introspection result for saving
164
+ const __schema = Grafaid.Schema.toIntrospectionQuery(schema)
165
+
166
+ // Wrap in GraphQL response format for consistency with API responses
167
+ const introspectionData = { data: { __schema } }
168
+
169
+ // Write to file
170
+ await Fs.write({
171
+ path: introspectionFilePath,
172
+ content: Json.codec.encode(introspectionData as any),
173
+ })
174
+
175
+ const schemaData = await createSingleSchemaChangeset(schema)
176
+ return {
177
+ data: schemaData,
178
+ source: {
179
+ type: 'introspectionAuto',
180
+ reCreate: async () => {
181
+ // Re-fetch using captured config - capture closure
182
+ const result = await readOrThrow(configInput)
183
+ return result.data
184
+ },
185
+ },
186
+ }
187
+ }
188
+ }
189
+
190
+ /**
191
+ * Create a single changeset from a schema object.
192
+ * This is the core logic for handling single (unversioned) schemas from introspection.
193
+ */
194
+ export const createSingleSchemaChangeset = async (schema: Grafaid.Schema.Schema): Promise<NonEmptyChangeSets> => {
195
+ const date = new Date() // Generate date here for unversioned schema
196
+ const after = schema
197
+ const before = Grafaid.Schema.empty
198
+ const changes = await GraphqlChange.calcChangeset({
199
+ before,
200
+ after,
201
+ })
202
+
203
+ const changeset: GraphqlChangeset.ChangeSet = {
204
+ date,
205
+ after,
206
+ before,
207
+ changes,
208
+ }
209
+
210
+ const result: NonEmptyChangeSets = [changeset]
211
+
212
+ return result
213
+ }
@@ -1,38 +1,104 @@
1
- import { Arr } from '@wollybeard/kit'
1
+ import { Arr, Fs, Path } from '@wollybeard/kit'
2
2
  import * as DataSources from './data-sources/data-sources.js'
3
3
  import type { NonEmptyChangeSets } from './schema.js'
4
4
 
5
- export type DataSourceType = `file` | `directory` | `memory` | `data`
5
+ export type DataSourceType =
6
+ | `file`
7
+ | `directory`
8
+ | `memory`
9
+ | `data`
10
+ | `introspection`
11
+ | `introspectionFile`
12
+ | `introspectionAuto`
13
+
14
+ /**
15
+ * Result of schema reading with provenance tracking for file watching and debugging.
16
+ */
17
+ export interface SchemaReadResult {
18
+ data: NonEmptyChangeSets | null
19
+ source: {
20
+ type: DataSourceType
21
+ /**
22
+ * Recreate the schema data and file after it has been deleted.
23
+ *
24
+ * This function re-fetches data from the original source and recreates
25
+ * the schema file on disk. Only called by file watchers after deletion.
26
+ *
27
+ * @returns Promise resolving to the recreated schema data, or null if recreation fails
28
+ */
29
+ reCreate?: () => Promise<NonEmptyChangeSets | null>
30
+ }
31
+ }
6
32
 
7
33
  /**
8
34
  * Schema configuration for Polen.
35
+ *
36
+ * Polen supports multiple ways to load your GraphQL schema, from simple files
37
+ * to dynamic introspection. Configure which sources to use and in what order.
38
+ *
39
+ * @example
40
+ * ```ts
41
+ * // Load from a file (default)
42
+ * schema: {} // Looks for schema.graphql
43
+ *
44
+ * // Load via introspection
45
+ * schema: {
46
+ * dataSources: {
47
+ * introspection: {
48
+ * url: 'https://api.example.com/graphql',
49
+ * headers: { 'Authorization': 'Bearer token' }
50
+ * }
51
+ * }
52
+ * }
53
+ *
54
+ * // Try multiple sources in order
55
+ * schema: {
56
+ * useDataSources: ['introspection', 'file'],
57
+ * dataSources: {
58
+ * introspection: { url: 'https://api.example.com/graphql' },
59
+ * file: { path: './fallback-schema.graphql' }
60
+ * }
61
+ * }
62
+ * ```
9
63
  */
10
64
  export interface Config {
11
65
  /**
12
66
  * Whether to enable schema loading.
13
67
  *
14
- * Set to `false` to disable schema features entirely.
68
+ * Set to `false` to disable schema features entirely. This removes
69
+ * the Reference and Changelog pages from your portal.
15
70
  *
16
- * @default `true`
71
+ * @default true
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * // Disable schema features
76
+ * schema: { enabled: false }
77
+ * ```
17
78
  */
18
79
  enabled?: boolean
19
80
  /**
20
81
  * Which data sources to use for loading schemas.
21
82
  *
22
- * - `file` - Load from a single SDL file
23
- * - `directory` - Load multiple SDL files from a directory
83
+ * - `file` - Load from a single SDL file (default: `./schema.graphql`)
84
+ * - `directory` - Load multiple SDL files from a directory (default: `./schema/`)
24
85
  * - `memory` - Use schemas defined in configuration
25
86
  * - `data` - Use a pre-built schema object
87
+ * - `introspection` - Load schema via GraphQL introspection
26
88
  *
27
- * If not specified, Polen will try all sources in order until one succeeds.
89
+ * If not specified, Polen tries all sources in this order:
90
+ * 1. `data` 2. `directory` 3. `file` 4. `memory` 5. `introspection`
28
91
  *
29
92
  * @example
30
93
  * ```ts
31
94
  * // Use only file source
32
95
  * useDataSources: 'file'
33
96
  *
34
- * // Try multiple sources
35
- * useDataSources: ['directory', 'file']
97
+ * // Try multiple sources in custom order
98
+ * useDataSources: ['introspection', 'file']
99
+ *
100
+ * // Default behavior (try all sources)
101
+ * // useDataSources: undefined
36
102
  * ```
37
103
  */
38
104
  useDataSources?: Arr.Maybe<DataSourceType>
@@ -56,22 +122,38 @@ export interface Config {
56
122
  * Pre-built schema object to use directly.
57
123
  */
58
124
  data?: NonEmptyChangeSets
125
+ /**
126
+ * Configuration for loading schema via GraphQL introspection.
127
+ *
128
+ * Introspection fetches your schema directly from a running GraphQL endpoint.
129
+ * The schema is saved to `schema.introspection.json` in your project root.
130
+ * Delete this file to force a fresh introspection on the next build.
131
+ *
132
+ * @example
133
+ * ```ts
134
+ * introspection: {
135
+ * url: 'https://api.example.com/graphql',
136
+ * headers: { 'Authorization': 'Bearer token' }
137
+ * }
138
+ * ```
139
+ */
140
+ introspection?: DataSources.Introspection.ConfigInput
59
141
  }
60
142
  projectRoot: string
61
143
  }
62
144
 
63
145
  export const readOrThrow = async (
64
146
  config: Config,
65
- ): Promise<null | NonEmptyChangeSets> => {
147
+ ): Promise<SchemaReadResult> => {
66
148
  if (config.enabled === false) {
67
- return null
149
+ return { data: null, source: { type: 'data' } }
68
150
  }
69
151
 
70
152
  const useDataSources = config.useDataSources ? Arr.sure(config.useDataSources) : null
71
153
  const usingDataSource = (dataSource: DataSourceType) => useDataSources === null || useDataSources.includes(dataSource)
72
154
 
73
155
  if (usingDataSource(`data`) && config.dataSources?.data) {
74
- return config.dataSources.data
156
+ return { data: config.dataSources.data, source: { type: 'data' } }
75
157
  }
76
158
 
77
159
  if (usingDataSource(`directory`)) {
@@ -80,7 +162,7 @@ export const readOrThrow = async (
80
162
  ...config.dataSources?.directory,
81
163
  }
82
164
  const result = await DataSources.SchemaDirectory.readOrThrow(directoryConfig)
83
- if (result) return result
165
+ if (result) return { data: result, source: { type: 'directory' } }
84
166
  }
85
167
 
86
168
  if (usingDataSource(`file`)) {
@@ -89,7 +171,7 @@ export const readOrThrow = async (
89
171
  ...config.dataSources?.file,
90
172
  }
91
173
  const result = await DataSources.SchemaFile.readOrThrow(fileConfig)
92
- if (result) return result
174
+ if (result) return { data: result, source: { type: 'file' } }
93
175
  }
94
176
 
95
177
  if (usingDataSource(`memory`) && config.dataSources?.memory) {
@@ -98,8 +180,17 @@ export const readOrThrow = async (
98
180
  ...config.dataSources.memory,
99
181
  }
100
182
  const result = await DataSources.Memory.read(memoryConfig)
101
- if (result) return result
183
+ if (result) return { data: result, source: { type: 'memory' } }
184
+ }
185
+
186
+ if (usingDataSource(`introspection`) && config.dataSources?.introspection) {
187
+ const introspectionConfig = {
188
+ projectRoot: config.projectRoot,
189
+ ...config.dataSources.introspection,
190
+ }
191
+ const result = await DataSources.Introspection.readOrThrow(introspectionConfig)
192
+ if (result.data) return result
102
193
  }
103
194
 
104
- return null
195
+ return { data: null, source: { type: 'data' } }
105
196
  }