polen 0.11.0-next.1 → 0.11.0-next.10
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/build/api/config/configurator.d.ts +35 -23
- package/build/api/config/configurator.d.ts.map +1 -1
- package/build/api/config/configurator.js +0 -6
- package/build/api/config/configurator.js.map +1 -1
- package/build/api/config/merge.d.ts.map +1 -1
- package/build/api/config/merge.js +0 -11
- package/build/api/config/merge.js.map +1 -1
- package/build/api/content/metadata.d.ts +8 -2
- package/build/api/content/metadata.d.ts.map +1 -1
- package/build/api/content/metadata.js +1 -1
- package/build/api/content/metadata.js.map +1 -1
- package/build/api/schema/data-sources/data-sources.d.ts +1 -0
- package/build/api/schema/data-sources/data-sources.d.ts.map +1 -1
- package/build/api/schema/data-sources/data-sources.js +1 -0
- package/build/api/schema/data-sources/data-sources.js.map +1 -1
- package/build/api/schema/data-sources/introspection/introspection.d.ts +83 -0
- package/build/api/schema/data-sources/introspection/introspection.d.ts.map +1 -0
- package/build/api/schema/data-sources/introspection/introspection.js +110 -0
- package/build/api/schema/data-sources/introspection/introspection.js.map +1 -0
- package/build/api/schema/metadata.d.ts +11 -3
- package/build/api/schema/metadata.d.ts.map +1 -1
- package/build/api/schema/metadata.js +1 -1
- package/build/api/schema/metadata.js.map +1 -1
- package/build/api/schema/read.d.ts +83 -9
- package/build/api/schema/read.d.ts.map +1 -1
- package/build/api/schema/read.js +15 -6
- package/build/api/schema/read.js.map +1 -1
- package/build/api/schema-source/schema-source.d.ts +1 -1
- package/build/api/schema-source/schema-source.d.ts.map +1 -1
- package/build/api/schema-source/schema-source.js.map +1 -1
- package/build/api/static/manifest.d.ts +1 -2
- package/build/api/static/manifest.d.ts.map +1 -1
- package/build/api/static/manifest.js +1 -1
- package/build/api/static/manifest.js.map +1 -1
- package/build/api/vite/plugins/build.d.ts.map +1 -1
- package/build/api/vite/plugins/build.js +3 -0
- package/build/api/vite/plugins/build.js.map +1 -1
- package/build/api/vite/plugins/core.js +8 -8
- package/build/api/vite/plugins/core.js.map +1 -1
- package/build/api/vite/plugins/main.d.ts.map +1 -1
- package/build/api/vite/plugins/main.js +1 -8
- package/build/api/vite/plugins/main.js.map +1 -1
- package/build/api/vite/plugins/schema-assets.d.ts.map +1 -1
- package/build/api/vite/plugins/schema-assets.js +52 -11
- package/build/api/vite/plugins/schema-assets.js.map +1 -1
- package/build/cli/commands/open.js +1 -1
- package/build/cli/commands/open.js.map +1 -1
- package/build/lib/grafaid/schema/schema.d.ts +1 -1
- package/build/lib/grafaid/schema/schema.d.ts.map +1 -1
- package/build/lib/grafaid/schema/schema.js +1 -1
- package/build/lib/grafaid/schema/schema.js.map +1 -1
- package/build/lib/kit-temp.js +2 -2
- package/build/lib/kit-temp.js.map +1 -1
- package/build/lib/react-router-aid/react-router-aid.d.ts +5 -3
- package/build/lib/react-router-aid/react-router-aid.d.ts.map +1 -1
- package/build/lib/react-router-aid/react-router-aid.js +7 -4
- package/build/lib/react-router-aid/react-router-aid.js.map +1 -1
- package/build/template/routes/changelog.js +2 -2
- package/build/template/routes/changelog.js.map +1 -1
- package/build/template/routes/index.js +2 -2
- package/build/template/routes/index.js.map +1 -1
- package/build/template/routes/pages.js +2 -2
- package/build/template/routes/pages.js.map +1 -1
- package/build/template/routes/reference.d.ts +27 -4
- package/build/template/routes/reference.d.ts.map +1 -1
- package/build/template/routes/reference.js +81 -20
- package/build/template/routes/reference.js.map +1 -1
- package/build/template/routes/root.js +3 -3
- package/build/template/routes/root.js.map +1 -1
- package/build/template/server/ssg/get-route-paths.d.ts.map +1 -1
- package/build/template/server/ssg/get-route-paths.js +42 -3
- package/build/template/server/ssg/get-route-paths.js.map +1 -1
- package/build/template/sources/schema-source.d.ts +1 -1
- package/build/template/sources/schema-source.d.ts.map +1 -1
- package/build/template/sources/schema-source.js +2 -1
- package/build/template/sources/schema-source.js.map +1 -1
- package/package.json +16 -17
- package/src/api/config/configurator.ts +35 -30
- package/src/api/config/merge.ts +0 -16
- package/src/api/content/metadata.ts +1 -1
- package/src/api/schema/data-sources/data-sources.ts +1 -0
- package/src/api/schema/data-sources/introspection/introspection.ts +213 -0
- package/src/api/schema/metadata.ts +1 -1
- package/src/api/schema/read.ts +107 -16
- package/src/api/schema-source/schema-source.ts +3 -3
- package/src/api/static/manifest.ts +1 -1
- package/src/api/vite/plugins/build.ts +3 -0
- package/src/api/vite/plugins/core.ts +8 -8
- package/src/api/vite/plugins/main.ts +1 -9
- package/src/api/vite/plugins/schema-assets.ts +59 -12
- package/src/cli/commands/open.ts +1 -1
- package/src/lib/grafaid/schema/schema.ts +1 -0
- package/src/lib/kit-temp.ts +2 -2
- package/src/lib/mask/$.test.ts +3 -3
- package/src/lib/react-router-aid/react-router-aid.ts +12 -6
- package/src/template/routes/changelog.tsx +2 -2
- package/src/template/routes/index.tsx +2 -2
- package/src/template/routes/pages.tsx +2 -2
- package/src/template/routes/reference.tsx +88 -20
- package/src/template/routes/root.tsx +3 -3
- package/src/template/server/ssg/get-route-paths.test.ts +132 -0
- package/src/template/server/ssg/get-route-paths.ts +41 -3
- package/src/template/sources/schema-source.ts +2 -1
- package/build/template/routes/reference.$type.$field.d.ts +0 -5
- package/build/template/routes/reference.$type.$field.d.ts.map +0 -1
- package/build/template/routes/reference.$type.$field.js +0 -31
- package/build/template/routes/reference.$type.$field.js.map +0 -1
- package/build/template/routes/reference.$type.d.ts +0 -9
- package/build/template/routes/reference.$type.d.ts.map +0 -1
- package/build/template/routes/reference.$type.js +0 -25
- package/build/template/routes/reference.$type.js.map +0 -1
- package/build/template/routes/reference.version.$version.$type.$field.d.ts +0 -6
- package/build/template/routes/reference.version.$version.$type.$field.d.ts.map +0 -1
- package/build/template/routes/reference.version.$version.$type.$field.js +0 -32
- package/build/template/routes/reference.version.$version.$type.$field.js.map +0 -1
- package/build/template/routes/reference.version.$version.$type.d.ts +0 -11
- package/build/template/routes/reference.version.$version.$type.d.ts.map +0 -1
- package/build/template/routes/reference.version.$version.$type.js +0 -26
- package/build/template/routes/reference.version.$version.$type.js.map +0 -1
- package/src/template/routes/reference.$type.$field.tsx +0 -34
- package/src/template/routes/reference.$type.tsx +0 -29
- package/src/template/routes/reference.version.$version.$type.$field.tsx +0 -35
- package/src/template/routes/reference.version.$version.$type.tsx +0 -30
@@ -75,6 +75,9 @@ export const Build = (config: Config.Config): Vite.Plugin[] => {
|
|
75
75
|
// @see https://github.com/vitejs/vite/issues/20098
|
76
76
|
ssr: {
|
77
77
|
noExternal: true,
|
78
|
+
// Exclude lightningcss from bundling due to native bindings
|
79
|
+
// @see https://github.com/parcel-bundler/lightningcss/issues/701
|
80
|
+
external: ['lightningcss'],
|
78
81
|
},
|
79
82
|
environments: {
|
80
83
|
ssr: {
|
@@ -35,15 +35,15 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
|
|
35
35
|
|
36
36
|
const readSchema = async () => {
|
37
37
|
if (schemaCache === null) {
|
38
|
-
const
|
38
|
+
const schemaResult = await Schema.readOrThrow({
|
39
39
|
...config.schema,
|
40
40
|
projectRoot: config.paths.project.rootDir,
|
41
41
|
})
|
42
42
|
// todo: augmentations scoped to a version
|
43
|
-
|
43
|
+
schemaResult.data?.forEach(version => {
|
44
44
|
SchemaAugmentation.apply(version.after, config.schemaAugmentations)
|
45
45
|
})
|
46
|
-
schemaCache =
|
46
|
+
schemaCache = schemaResult
|
47
47
|
}
|
48
48
|
return schemaCache
|
49
49
|
}
|
@@ -166,8 +166,8 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
|
|
166
166
|
const debug = debugPolen.sub(`module-project-schema`)
|
167
167
|
debug(`load`, { id: viProjectSchema.id })
|
168
168
|
|
169
|
-
const
|
170
|
-
return superjson.stringify(
|
169
|
+
const schemaResult = await readSchema()
|
170
|
+
return superjson.stringify(schemaResult.data)
|
171
171
|
},
|
172
172
|
},
|
173
173
|
{
|
@@ -191,18 +191,18 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
|
|
191
191
|
|
192
192
|
debug(`load`, { id: viProjectData.id })
|
193
193
|
|
194
|
-
const
|
194
|
+
const schemaResult = await readSchema()
|
195
195
|
|
196
196
|
const navbar = []
|
197
197
|
|
198
198
|
// ━ Schema presence causes adding some navbar items
|
199
|
-
if (
|
199
|
+
if (schemaResult.data) {
|
200
200
|
// IMPORTANT: Always ensure paths start with '/' for React Router compatibility.
|
201
201
|
// Without the leading slash, React Router treats paths as relative, which causes
|
202
202
|
// hydration mismatches between SSR (where base path is prepended) and client
|
203
203
|
// (where basename is configured). This ensures consistent behavior.
|
204
204
|
navbar.push({ pathExp: `/reference`, title: `Reference` })
|
205
|
-
if (
|
205
|
+
if (schemaResult.data.length > 1) {
|
206
206
|
navbar.push({ pathExp: `/changelog`, title: `Changelog` })
|
207
207
|
}
|
208
208
|
}
|
@@ -2,9 +2,8 @@ import type { Config } from '#api/config/index'
|
|
2
2
|
import type { Vite } from '#dep/vite/index'
|
3
3
|
import { vitePluginSsrCss } from '@hiogawa/vite-plugin-ssr-css'
|
4
4
|
import ViteReact from '@vitejs/plugin-react-oxc'
|
5
|
-
import {
|
5
|
+
import { Path } from '@wollybeard/kit'
|
6
6
|
import Inspect from 'vite-plugin-inspect'
|
7
|
-
import Restart from 'vite-plugin-restart'
|
8
7
|
import { Branding } from './branding.js'
|
9
8
|
import { Build } from './build.js'
|
10
9
|
import { Core } from './core.js'
|
@@ -26,13 +25,6 @@ export const Main = (
|
|
26
25
|
plugins.push(plugin)
|
27
26
|
}
|
28
27
|
|
29
|
-
if (Arr.isntEmpty(config.watch.also)) {
|
30
|
-
const plugin = Restart({
|
31
|
-
restart: config.watch.also,
|
32
|
-
})
|
33
|
-
plugins.push(plugin)
|
34
|
-
}
|
35
|
-
|
36
28
|
plugins.push(
|
37
29
|
ViteReact(),
|
38
30
|
vitePluginSsrCss({
|
@@ -9,6 +9,7 @@ import { debugPolen } from '#singletons/debug'
|
|
9
9
|
import { Cache } from '@wollybeard/kit'
|
10
10
|
import * as NodeFs from 'node:fs/promises'
|
11
11
|
import * as NodePath from 'node:path'
|
12
|
+
import type { NonEmptyChangeSets } from '../../schema/schema.js'
|
12
13
|
import { polenVirtual } from '../vi.js'
|
13
14
|
|
14
15
|
export const viProjectSchemaMetadata = polenVirtual([`project`, `schema-metadata`])
|
@@ -35,27 +36,28 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
35
36
|
|
36
37
|
// Helper to load and process schema data
|
37
38
|
const loadAndProcessSchemaData = Cache.memoize(async () => {
|
38
|
-
const
|
39
|
+
const schemaResult = await Schema.readOrThrow({
|
39
40
|
...config.schema,
|
40
41
|
projectRoot: config.paths.project.rootDir,
|
41
42
|
})
|
42
43
|
|
43
|
-
if (!
|
44
|
+
if (!schemaResult.data) {
|
44
45
|
const metadata: Schema.SchemaMetadata = { hasSchema: false, versions: [] }
|
45
46
|
return {
|
46
47
|
schemaData: null,
|
47
48
|
metadata,
|
49
|
+
source: schemaResult.source,
|
48
50
|
}
|
49
51
|
}
|
50
52
|
|
51
53
|
// Apply augmentations
|
52
|
-
|
54
|
+
schemaResult.data.forEach(version => {
|
53
55
|
SchemaAugmentation.apply(version.after, config.schemaAugmentations)
|
54
56
|
})
|
55
57
|
|
56
58
|
// Build metadata
|
57
59
|
const versionStrings: string[] = []
|
58
|
-
for (const [index, version] of
|
60
|
+
for (const [index, version] of schemaResult.data.entries()) {
|
59
61
|
const versionName = index === 0 ? Schema.VERSION_LATEST : Schema.dateToVersionString(version.date)
|
60
62
|
versionStrings.push(versionName)
|
61
63
|
}
|
@@ -65,11 +67,12 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
65
67
|
versions: versionStrings,
|
66
68
|
}
|
67
69
|
|
68
|
-
debug(`schemaDataLoaded`, { versionCount:
|
70
|
+
debug(`schemaDataLoaded`, { versionCount: schemaResult.data.length })
|
69
71
|
|
70
72
|
return {
|
71
|
-
schemaData,
|
73
|
+
schemaData: schemaResult.data,
|
72
74
|
metadata,
|
75
|
+
source: schemaResult.source,
|
73
76
|
}
|
74
77
|
})
|
75
78
|
|
@@ -102,10 +105,10 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
102
105
|
|
103
106
|
// Helper to write assets using schema-source API
|
104
107
|
const writeDevAssets = async (
|
105
|
-
schemaData:
|
108
|
+
schemaData: NonEmptyChangeSets,
|
106
109
|
metadata: Schema.SchemaMetadata,
|
107
110
|
) => {
|
108
|
-
|
111
|
+
// schemaData is now guaranteed to be non-null NonEmptyChangeSets
|
109
112
|
|
110
113
|
const devAssetsDir = config.paths.framework.devAssets.schemas
|
111
114
|
await NodeFs.mkdir(devAssetsDir, { recursive: true })
|
@@ -149,6 +152,13 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
149
152
|
debug(`watchingSchemaFile`, { path: config.schema.dataSources.file.path })
|
150
153
|
}
|
151
154
|
|
155
|
+
if (config.schema?.dataSources?.introspection?.url) {
|
156
|
+
// Watch the introspection file if introspection is configured
|
157
|
+
const introspectionFilePath = NodePath.join(config.paths.project.rootDir, `schema.introspection.json`)
|
158
|
+
server.watcher.add(introspectionFilePath)
|
159
|
+
debug(`watchingIntrospectionFile`, { path: introspectionFilePath })
|
160
|
+
}
|
161
|
+
|
152
162
|
// Handle file removal
|
153
163
|
server.watcher.on('unlink', async (file) => {
|
154
164
|
const isSchemaFile = config.schema && (() => {
|
@@ -172,6 +182,15 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
172
182
|
if (absoluteFile.startsWith(absoluteSchemaDir + NodePath.sep)) return true
|
173
183
|
}
|
174
184
|
|
185
|
+
// Check if file is the introspection file
|
186
|
+
if (config.schema.dataSources?.introspection?.url) {
|
187
|
+
const absoluteIntrospectionFile = NodePath.resolve(
|
188
|
+
config.paths.project.rootDir,
|
189
|
+
`schema.introspection.json`,
|
190
|
+
)
|
191
|
+
if (absoluteFile === absoluteIntrospectionFile) return true
|
192
|
+
}
|
193
|
+
|
175
194
|
return false
|
176
195
|
})()
|
177
196
|
|
@@ -181,14 +200,33 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
181
200
|
try {
|
182
201
|
// Clear cache and regenerate
|
183
202
|
loadAndProcessSchemaData.clear()
|
184
|
-
const { schemaData, metadata } = await loadAndProcessSchemaData()
|
185
|
-
|
186
|
-
|
203
|
+
const { schemaData, metadata, source } = await loadAndProcessSchemaData()
|
204
|
+
|
205
|
+
// If file was deleted but can be recreated, attempt recreation
|
206
|
+
if (!schemaData && source.reCreate) {
|
207
|
+
debug(`attemptingSchemaRecreation`, { sourceType: source.type })
|
208
|
+
try {
|
209
|
+
const recreatedData = await source.reCreate()
|
210
|
+
if (recreatedData) {
|
211
|
+
// Clear cache again and reload after recreation
|
212
|
+
loadAndProcessSchemaData.clear()
|
213
|
+
const reloadResult = await loadAndProcessSchemaData()
|
214
|
+
if (reloadResult.schemaData) {
|
215
|
+
await writeDevAssets(reloadResult.schemaData, reloadResult.metadata)
|
216
|
+
debug(`hmr:schemaRecreatedAndWritten`, { versionCount: reloadResult.schemaData.length })
|
217
|
+
}
|
218
|
+
} else {
|
219
|
+
debug(`hmr:schemaRecreationFailed`, { reason: 'reCreate returned null' })
|
220
|
+
}
|
221
|
+
} catch (recreationError) {
|
222
|
+
debug(`hmr:schemaRecreationFailed`, { error: recreationError })
|
223
|
+
}
|
224
|
+
} else if (schemaData) {
|
187
225
|
// Write new assets without the removed file
|
188
226
|
await writeDevAssets(schemaData, metadata)
|
189
227
|
debug(`hmr:schemaAssetsUpdatedAfterRemoval`, { versionCount: schemaData.length })
|
190
228
|
} else {
|
191
|
-
// No schema data - clear all assets
|
229
|
+
// No schema data and cannot recreate - clear all assets
|
192
230
|
const schemaSource = createDevSchemaSource({ hasSchema: false, versions: [] })
|
193
231
|
await schemaSource.clearAllAssets()
|
194
232
|
debug(`hmr:allAssetsCleared`, {})
|
@@ -274,6 +312,15 @@ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
|
|
274
312
|
if (absoluteFile.startsWith(absoluteSchemaDir + NodePath.sep)) return true
|
275
313
|
}
|
276
314
|
|
315
|
+
// Check if file is the introspection file
|
316
|
+
if (config.schema.dataSources?.introspection?.url) {
|
317
|
+
const absoluteIntrospectionFile = NodePath.resolve(
|
318
|
+
config.paths.project.rootDir,
|
319
|
+
`schema.introspection.json`,
|
320
|
+
)
|
321
|
+
if (absoluteFile === absoluteIntrospectionFile) return true
|
322
|
+
}
|
323
|
+
|
277
324
|
return false
|
278
325
|
})()
|
279
326
|
if (isSchemaFile) {
|
package/src/cli/commands/open.ts
CHANGED
@@ -132,7 +132,7 @@ const wrapCache = <fn extends Fn.AnyAnyAsync>(fn: fn): fn => {
|
|
132
132
|
|
133
133
|
// todo: use a proper validation, e.g. zod, better yet: allow to specify the validation in molt itself
|
134
134
|
const parseHeaders = (headersJsonEncoded: string): Record<string, string> => {
|
135
|
-
const headersJson = Json.codec.
|
135
|
+
const headersJson = Json.codec.decode(headersJsonEncoded)
|
136
136
|
if (!Rec.is(headersJson)) {
|
137
137
|
console.log(`--introspection-headers must be a JSON object.`)
|
138
138
|
process.exit(1)
|
package/src/lib/kit-temp.ts
CHANGED
@@ -105,9 +105,9 @@ export const objPolicyFilter = <
|
|
105
105
|
const result: any = mode === `deny` ? { ...obj } : {}
|
106
106
|
|
107
107
|
if (mode === `allow`) {
|
108
|
-
// For allow mode, only add specified keys
|
108
|
+
// For allow mode, only add specified keys that are own properties
|
109
109
|
for (const key of keys) {
|
110
|
-
if (key
|
110
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
111
111
|
// @ts-expect-error
|
112
112
|
result[key] = obj[key]
|
113
113
|
}
|
package/src/lib/mask/$.test.ts
CHANGED
@@ -113,9 +113,9 @@ describe('property-based tests', () => {
|
|
113
113
|
// Result contains only keys that were in both mask and object
|
114
114
|
expect(resultKeys.every(key => keys.includes(key))).toBe(true)
|
115
115
|
|
116
|
-
// All requested keys that
|
116
|
+
// All requested keys that are own properties of obj are in result
|
117
117
|
keys.forEach(key => {
|
118
|
-
if (key
|
118
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
119
119
|
expect(result).toHaveProperty(key, (obj as any)[key])
|
120
120
|
}
|
121
121
|
})
|
@@ -169,7 +169,7 @@ describe('property-based tests', () => {
|
|
169
169
|
const result = Mask.apply(obj as any, Mask.create(keys))
|
170
170
|
|
171
171
|
keys.forEach(key => {
|
172
|
-
if (key
|
172
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
173
173
|
expect(result).toHaveProperty(key)
|
174
174
|
expect((result as any)[key]).toBe((obj as any)[key])
|
175
175
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import type { ReactRouter } from '#dep/react-router/index'
|
2
|
+
import type { React } from '#dep/react/index'
|
2
3
|
import type { Http } from '@wollybeard/kit'
|
3
4
|
|
4
5
|
export * from './get-paths-patterns.js'
|
@@ -18,23 +19,28 @@ export interface RouteHandle {
|
|
18
19
|
statusCode?: Http.Status.Code.All
|
19
20
|
}
|
20
21
|
|
21
|
-
export const
|
22
|
+
export const route = <routeObject extends RouteObject>(
|
22
23
|
routeObject: routeObject,
|
23
24
|
): routeObject => {
|
24
25
|
return {
|
25
|
-
id: routeObject.path,
|
26
26
|
...routeObject,
|
27
27
|
}
|
28
28
|
}
|
29
29
|
|
30
|
-
export type RouteObjectIndexInput =
|
30
|
+
export type RouteObjectIndexInput = RouteObjectIndexInputConfig | React.ComponentType
|
31
|
+
export type RouteObjectIndexInputConfig = Omit<RouteObjectIndex, `index` | `children`>
|
31
32
|
|
32
|
-
export const
|
33
|
-
|
33
|
+
export const routeIndex = (
|
34
|
+
input: RouteObjectIndexInput,
|
34
35
|
): RouteObjectIndex => {
|
36
|
+
const routeConfig: RouteObjectIndexInputConfig = isComponentType(input) ? { Component: input } : input
|
35
37
|
return {
|
36
|
-
...
|
38
|
+
...routeConfig,
|
37
39
|
index: true,
|
38
40
|
children: undefined,
|
39
41
|
}
|
40
42
|
}
|
43
|
+
|
44
|
+
const isComponentType = (value: unknown): value is React.ComponentType => {
|
45
|
+
return typeof value === 'function'
|
46
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import type { GraphqlChangeset } from '#lib/graphql-changeset/index'
|
2
|
-
import {
|
2
|
+
import { route } from '#lib/react-router-aid/react-router-aid'
|
3
3
|
import { createLoader, useLoaderData } from '#lib/react-router-loader/react-router-loader'
|
4
4
|
import { Changelog } from '../components/Changelog.js'
|
5
5
|
import { ChangelogLayout } from '../layouts/index.js'
|
@@ -33,7 +33,7 @@ const Component = () => {
|
|
33
33
|
)
|
34
34
|
}
|
35
35
|
|
36
|
-
export const changelog =
|
36
|
+
export const changelog = route({
|
37
37
|
path: `changelog`,
|
38
38
|
loader,
|
39
39
|
Component,
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import {
|
1
|
+
import { routeIndex } from '#lib/react-router-aid/react-router-aid'
|
2
2
|
import { Box } from '@radix-ui/themes'
|
3
3
|
|
4
4
|
const Component = () => {
|
5
5
|
return <Box>home todo</Box>
|
6
6
|
}
|
7
7
|
|
8
|
-
export const index =
|
8
|
+
export const index = routeIndex({
|
9
9
|
Component,
|
10
10
|
})
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { route } from '#lib/react-router-aid/react-router-aid'
|
2
2
|
import { createLoader, useLoaderData } from '#lib/react-router-loader/react-router-loader'
|
3
3
|
import { SidebarLayout } from '#template/layouts/index'
|
4
4
|
import { MDXProvider } from '@mdx-js/react'
|
@@ -101,7 +101,7 @@ const Component = () => {
|
|
101
101
|
)
|
102
102
|
}
|
103
103
|
|
104
|
-
export const pages =
|
104
|
+
export const pages = route({
|
105
105
|
// Pathless layout route - doesn't affect URL paths
|
106
106
|
loader,
|
107
107
|
Component,
|
@@ -1,19 +1,19 @@
|
|
1
1
|
import type { Content } from '#api/content/$'
|
2
2
|
import { GrafaidOld } from '#lib/grafaid-old/index'
|
3
|
-
import {
|
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 } 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
|
-
import { useVersionPath } from '../hooks/useVersionPath.js'
|
10
12
|
import { SidebarLayout } from '../layouts/index.js'
|
11
13
|
import { VERSION_LATEST } from '../lib/schema-utils/constants.js'
|
12
14
|
import { schemaSource } from '../sources/schema-source.js'
|
13
|
-
import { reference$type } from './reference.$type.js'
|
14
|
-
import { referenceVersion$version$type } from './reference.version.$version.$type.js'
|
15
15
|
|
16
|
-
const loader = createLoader(async ({ params }) => {
|
16
|
+
export const loader = createLoader(async ({ params }) => {
|
17
17
|
// Handle both versioned and unversioned routes:
|
18
18
|
// - Versioned: /reference/version/:version/:type → params.version exists
|
19
19
|
// - Unversioned: /reference/:type → params.version is undefined, defaults to latest
|
@@ -29,7 +29,7 @@ const loader = createLoader(async ({ params }) => {
|
|
29
29
|
}
|
30
30
|
})
|
31
31
|
|
32
|
-
const
|
32
|
+
const RouteReferenceComponent = () => {
|
33
33
|
const data = useLoaderData<typeof loader>()
|
34
34
|
|
35
35
|
if (!data.schema) {
|
@@ -42,8 +42,11 @@ const Component = () => {
|
|
42
42
|
const sidebarItems: Content.Item[] = []
|
43
43
|
const kindEntries = Object.entries(kindMap.list).filter(([_, types]) => types.length > 0)
|
44
44
|
|
45
|
-
// Build path prefix based on current version
|
46
|
-
|
45
|
+
// Build path prefix based on current version from loader data
|
46
|
+
// This ensures sidebar links always match the current version being viewed
|
47
|
+
const versionPath = data.currentVersion === VERSION_LATEST
|
48
|
+
? ``
|
49
|
+
: `version/${data.currentVersion}/`
|
47
50
|
|
48
51
|
for (const [title, types] of kindEntries) {
|
49
52
|
sidebarItems.push({
|
@@ -72,18 +75,83 @@ const Component = () => {
|
|
72
75
|
)
|
73
76
|
}
|
74
77
|
|
75
|
-
//
|
76
|
-
const
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
78
|
+
// Shared hooks for schema data validation and retrieval
|
79
|
+
const useReferenceSchema = () => {
|
80
|
+
const data = useLoaderData<typeof loader>('reference')
|
81
|
+
if (!data?.schema) {
|
82
|
+
throw new Error('Schema not found')
|
83
|
+
}
|
84
|
+
return data
|
85
|
+
}
|
86
|
+
|
87
|
+
const useSchemaType = (typeName: string) => {
|
88
|
+
const { schema } = useReferenceSchema()
|
89
|
+
const type = schema.getType(typeName)
|
90
|
+
if (!type) {
|
91
|
+
throw new Error(`Could not find type ${typeName}`)
|
92
|
+
}
|
93
|
+
return type
|
94
|
+
}
|
95
|
+
|
96
|
+
const useSchemaField = (typeName: string, fieldName: string) => {
|
97
|
+
const type = useSchemaType(typeName)
|
98
|
+
if (!Grafaid.Schema.TypesLike.isFielded(type)) {
|
99
|
+
throw new Error(`Type ${typeName} does not have fields`)
|
100
|
+
}
|
101
|
+
|
102
|
+
const fields = type.getFields()
|
103
|
+
const field = fields[fieldName]
|
104
|
+
if (!field) {
|
105
|
+
throw new Error(`Could not find field ${fieldName} on type ${typeName}`)
|
106
|
+
}
|
107
|
+
return field
|
108
|
+
}
|
109
|
+
|
110
|
+
const RouteComponentIndex = () => {
|
111
|
+
return <div>Select a type from the sidebar to view its documentation.</div>
|
112
|
+
}
|
113
|
+
|
114
|
+
const RouteComponentType = () => {
|
115
|
+
const params = useParams() as { type: string }
|
116
|
+
const type = useSchemaType(params.type)
|
117
|
+
return <NamedType data={type} />
|
118
|
+
}
|
119
|
+
|
120
|
+
const RouteComponentTypeField = () => {
|
121
|
+
const params = useParams() as { type: string; field: string }
|
122
|
+
const field = useSchemaField(params.type, params.field)
|
123
|
+
return <Field data={field} />
|
124
|
+
}
|
125
|
+
|
126
|
+
const typeAndFieldRoutes = [
|
127
|
+
routeIndex(RouteComponentIndex),
|
128
|
+
route({
|
129
|
+
path: `:type`,
|
130
|
+
Component: RouteComponentType,
|
131
|
+
errorElement: <MissingSchema />,
|
132
|
+
children: [
|
133
|
+
route({
|
134
|
+
path: `:field`,
|
135
|
+
Component: RouteComponentTypeField,
|
136
|
+
errorElement: <MissingSchema />,
|
137
|
+
}),
|
138
|
+
],
|
139
|
+
}),
|
140
|
+
]
|
82
141
|
|
83
|
-
|
84
|
-
|
142
|
+
/**
|
143
|
+
* Reference documentation with proper nested structure - all routes in one file
|
144
|
+
*/
|
145
|
+
export const reference = route({
|
146
|
+
id: 'reference',
|
85
147
|
path: `reference`,
|
86
148
|
loader,
|
87
|
-
Component,
|
88
|
-
children: [
|
149
|
+
Component: RouteReferenceComponent,
|
150
|
+
children: [
|
151
|
+
...typeAndFieldRoutes,
|
152
|
+
route({
|
153
|
+
path: `version/:version`,
|
154
|
+
children: typeAndFieldRoutes,
|
155
|
+
}),
|
156
|
+
],
|
89
157
|
})
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import type { ReactRouter } from '#dep/react-router/index'
|
2
|
-
import {
|
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'
|
@@ -105,7 +105,7 @@ if (PROJECT_SCHEMA) {
|
|
105
105
|
//
|
106
106
|
//
|
107
107
|
|
108
|
-
const notFoundRoute =
|
108
|
+
const notFoundRoute = route({
|
109
109
|
id: `*_not_found`,
|
110
110
|
path: `*`,
|
111
111
|
Component: NotFound,
|
@@ -122,7 +122,7 @@ children.push(notFoundRoute)
|
|
122
122
|
//
|
123
123
|
//
|
124
124
|
|
125
|
-
export const root =
|
125
|
+
export const root = route({
|
126
126
|
path: `/`,
|
127
127
|
Component,
|
128
128
|
children,
|