@uniweb/kit 0.13.6 → 0.13.7
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/package.json +2 -2
- package/src/hooks/useEntityDetail.js +47 -25
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniweb/kit",
|
|
3
|
-
"version": "0.13.
|
|
3
|
+
"version": "0.13.7",
|
|
4
4
|
"description": "Standard component library for Uniweb foundations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -44,8 +44,8 @@
|
|
|
44
44
|
"shiki": "^3.0.0",
|
|
45
45
|
"tailwind-merge": "^3.6.0",
|
|
46
46
|
"temml": "^0.13.2",
|
|
47
|
+
"@uniweb/core": "^0.13.0",
|
|
47
48
|
"@uniweb/semantic-parser": "^1.3.1",
|
|
48
|
-
"@uniweb/core": "^0.12.1",
|
|
49
49
|
"@uniweb/scene": "^0.1.3"
|
|
50
50
|
},
|
|
51
51
|
"peerDependencies": {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
* }
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
|
-
import { getUniweb,
|
|
47
|
+
import { getUniweb, resolveFetchConfigs, buildDetailConfig } from '@uniweb/core'
|
|
48
48
|
import { useFetched } from './useFetched.js'
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -60,46 +60,68 @@ import { useFetched } from './useFetched.js'
|
|
|
60
60
|
export function useEntityDetail(record, options = {}) {
|
|
61
61
|
const collection = options?.collection
|
|
62
62
|
const request = buildDetailRequest(record, collection)
|
|
63
|
-
|
|
63
|
+
const result = useFetched(request)
|
|
64
|
+
|
|
65
|
+
// No separate detail source for this collection — nothing was stripped from
|
|
66
|
+
// the cascade, so the record the caller already holds IS the whole record.
|
|
67
|
+
// Returning it beats both alternatives: `null` makes every caller null-check
|
|
68
|
+
// a case that cannot fail, and requesting the per-record file anyway is a
|
|
69
|
+
// guaranteed 404, because that file is only written for a `deferred:`
|
|
70
|
+
// collection. `useFetched` is still called above — unconditionally, as the
|
|
71
|
+
// rules of hooks require — and simply skips on a null request.
|
|
72
|
+
if (record && collection && !request) {
|
|
73
|
+
return { data: record, error: null, loading: false }
|
|
74
|
+
}
|
|
75
|
+
return result
|
|
64
76
|
}
|
|
65
77
|
|
|
66
78
|
/**
|
|
67
79
|
* Build the fetch request for one record's full payload.
|
|
68
80
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
81
|
+
* ⛔ THIS MUST NOT DECIDE THE ADDRESS ITSELF, and it used to. It read
|
|
82
|
+
* `config.collections[name].detailUrl` directly and otherwise composed
|
|
83
|
+
* `/data/<name>/<slug>.json` by hand, which was wrong three ways: it 404'd on
|
|
84
|
+
* any collection without `deferred:` (that file is only written for one), it
|
|
85
|
+
* could not see a host's live record lane at all, and its hand-rolled `{slug}`
|
|
86
|
+
* replace ignored a route whose param is named anything else.
|
|
87
|
+
*
|
|
88
|
+
* Every one of those is already solved once, in the resolution the runtime and
|
|
89
|
+
* the prerenderer share. So this hands the collection to that resolution and
|
|
90
|
+
* asks it the same question they ask: `resolveFetchConfigs` decides where the
|
|
91
|
+
* collection lives (a host's lane, or the compiled artifact) and what its
|
|
92
|
+
* per-record source is, then `buildDetailConfig` turns that plus a param into a
|
|
93
|
+
* request. A fourth answer computed here is a fourth thing to drift.
|
|
94
|
+
*
|
|
95
|
+
* Returns null when the collection has no separate detail source — the common
|
|
96
|
+
* case, and not a failure. The caller's record is already whole.
|
|
97
|
+
*
|
|
98
|
+
* Exported for tests only — not re-exported from the package index.
|
|
73
99
|
*
|
|
74
100
|
* @param {Object|null} record
|
|
75
101
|
* @param {string} collection
|
|
76
|
-
* @returns {{path?: string, url?: string, schema: string}|null}
|
|
102
|
+
* @returns {{path?: string, url?: string, endpoint?: string, schema: string}|null}
|
|
77
103
|
*/
|
|
78
104
|
export function buildDetailRequest(record, collection) {
|
|
79
105
|
const slug = record?.slug
|
|
80
106
|
if (!slug || !collection) return null
|
|
81
107
|
|
|
82
|
-
// Look up the collection's per-record source pattern. Authors with
|
|
83
|
-
// API-backed collections declare `detailUrl:` in site.yml; markdown
|
|
84
|
-
// collections leave it null and use the static-file default.
|
|
85
108
|
const website = getUniweb()?.activeWebsite
|
|
86
|
-
const
|
|
87
|
-
const detailUrl = (collConfig && typeof collConfig.detailUrl === 'string')
|
|
88
|
-
? collConfig.detailUrl
|
|
89
|
-
: null
|
|
109
|
+
const config = website?.config
|
|
90
110
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
111
|
+
// One synthetic source, resolved by the shared rule — same inputs the
|
|
112
|
+
// EntityStore passes, so the hook cannot disagree with the page it sits on.
|
|
113
|
+
const resolved = resolveFetchConfigs([{ collection, schema: collection }], {
|
|
114
|
+
collections: config?.collections ?? null,
|
|
115
|
+
records: config?.records ?? null,
|
|
116
|
+
locale: website?.getActiveLocale?.() ?? null,
|
|
117
|
+
defaultLocale: website?.getDefaultLocale?.() ?? null,
|
|
118
|
+
}).get(collection)
|
|
119
|
+
|
|
120
|
+
if (!resolved) return null
|
|
97
121
|
|
|
98
|
-
//
|
|
99
|
-
// `
|
|
100
|
-
|
|
101
|
-
// same feature: the three must resolve one record to one URL.
|
|
102
|
-
return { path: recordDataUrl(collection, slug), schema: collection }
|
|
122
|
+
// `slug` is this hook's contract with its caller (the record must carry one).
|
|
123
|
+
// The `{param}` alias means a host-written record pattern resolves too.
|
|
124
|
+
return buildDetailConfig(resolved, { paramName: 'slug', paramValue: slug })
|
|
103
125
|
}
|
|
104
126
|
|
|
105
127
|
export default useEntityDetail
|