@gaddario98/react-core 2.0.0 → 2.0.2
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/dist/form/index.js +4566 -1
- package/dist/form/index.js.map +1 -1
- package/dist/form/index.mjs +4566 -1
- package/dist/form/index.mjs.map +1 -1
- package/dist/index.d.ts +2152 -7
- package/dist/index.js +20713 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20713 -1
- package/dist/index.mjs.map +1 -1
- package/dist/localization/index.js +318 -1
- package/dist/localization/index.js.map +1 -1
- package/dist/localization/index.mjs +318 -1
- package/dist/localization/index.mjs.map +1 -1
- package/dist/notifications/index.js +84 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/index.mjs +84 -0
- package/dist/notifications/index.mjs.map +1 -0
- package/dist/pages/index.js +4652 -1
- package/dist/pages/index.js.map +1 -1
- package/dist/pages/index.mjs +4652 -1
- package/dist/pages/index.mjs.map +1 -1
- package/dist/providers/index.d.ts +12 -1
- package/dist/providers/index.js +17 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/index.mjs +17 -1
- package/dist/providers/index.mjs.map +1 -1
- package/dist/queries/index.js +8903 -1
- package/dist/queries/index.js.map +1 -1
- package/dist/queries/index.mjs +8903 -1
- package/dist/queries/index.mjs.map +1 -1
- package/dist/state/index.js +1927 -1
- package/dist/state/index.js.map +1 -1
- package/dist/state/index.mjs +1927 -1
- package/dist/state/index.mjs.map +1 -1
- package/dist/utiles/index.d.ts +15 -1
- package/dist/utiles/index.js +2973 -1
- package/dist/utiles/index.js.map +1 -1
- package/dist/utiles/index.mjs +2973 -1
- package/dist/utiles/index.mjs.map +1 -1
- package/package.json +12 -6
- package/dist/form/index.d.ts +0 -1
- package/dist/localization/index.d.ts +0 -1
- package/dist/pages/index.d.ts +0 -1
- package/dist/queries/index.d.ts +0 -1
- package/dist/state/index.d.ts +0 -1
package/dist/pages/index.js
CHANGED
|
@@ -1 +1,4652 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var jsxRuntime=require('react/jsx-runtime'),React=require('react'),reactQueries=require('@gaddario98/react-queries'),compilerRuntime=require('react/compiler-runtime'),reactState=require('@gaddario98/react-state'),equal=require('fast-deep-equal'),reactForm=require('@gaddario98/react-form');/******************************************************************************
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
|
|
4
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
5
|
+
purpose with or without fee is hereby granted.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
9
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
11
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
12
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
13
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
***************************************************************************** */
|
|
15
|
+
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
|
|
16
|
+
|
|
17
|
+
function __rest(s, e) {
|
|
18
|
+
var t = {};
|
|
19
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p];
|
|
20
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
21
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]];
|
|
22
|
+
}
|
|
23
|
+
return t;
|
|
24
|
+
}
|
|
25
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
26
|
+
var e = new Error(message);
|
|
27
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
28
|
+
};function hasInitialValue(atom) {
|
|
29
|
+
return "init" in atom;
|
|
30
|
+
}
|
|
31
|
+
function isActuallyWritableAtom(atom) {
|
|
32
|
+
return !!atom.write;
|
|
33
|
+
}
|
|
34
|
+
function isAtomStateInitialized(atomState) {
|
|
35
|
+
return "v" in atomState || "e" in atomState;
|
|
36
|
+
}
|
|
37
|
+
function returnAtomValue(atomState) {
|
|
38
|
+
if ("e" in atomState) {
|
|
39
|
+
throw atomState.e;
|
|
40
|
+
}
|
|
41
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && !("v" in atomState)) {
|
|
42
|
+
throw new Error("[Bug] atom state is not initialized");
|
|
43
|
+
}
|
|
44
|
+
return atomState.v;
|
|
45
|
+
}
|
|
46
|
+
const promiseStateMap = /* @__PURE__ */ new WeakMap();
|
|
47
|
+
function isPendingPromise(value) {
|
|
48
|
+
var _a;
|
|
49
|
+
return isPromiseLike$1(value) && !!((_a = promiseStateMap.get(value)) == null ? void 0 : _a[0]);
|
|
50
|
+
}
|
|
51
|
+
function abortPromise(promise) {
|
|
52
|
+
const promiseState = promiseStateMap.get(promise);
|
|
53
|
+
if (promiseState == null ? void 0 : promiseState[0]) {
|
|
54
|
+
promiseState[0] = false;
|
|
55
|
+
promiseState[1].forEach((fn) => fn());
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function registerAbortHandler(promise, abortHandler) {
|
|
59
|
+
let promiseState = promiseStateMap.get(promise);
|
|
60
|
+
if (!promiseState) {
|
|
61
|
+
promiseState = [true, /* @__PURE__ */ new Set()];
|
|
62
|
+
promiseStateMap.set(promise, promiseState);
|
|
63
|
+
const settle = () => {
|
|
64
|
+
promiseState[0] = false;
|
|
65
|
+
};
|
|
66
|
+
promise.then(settle, settle);
|
|
67
|
+
}
|
|
68
|
+
promiseState[1].add(abortHandler);
|
|
69
|
+
}
|
|
70
|
+
function isPromiseLike$1(p) {
|
|
71
|
+
return typeof (p == null ? void 0 : p.then) === "function";
|
|
72
|
+
}
|
|
73
|
+
function addPendingPromiseToDependency(atom, promise, dependencyAtomState) {
|
|
74
|
+
if (!dependencyAtomState.p.has(atom)) {
|
|
75
|
+
dependencyAtomState.p.add(atom);
|
|
76
|
+
const cleanup = () => dependencyAtomState.p.delete(atom);
|
|
77
|
+
promise.then(cleanup, cleanup);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function getMountedOrPendingDependents(atom, atomState, mountedMap) {
|
|
81
|
+
var _a;
|
|
82
|
+
const dependents = /* @__PURE__ */ new Set();
|
|
83
|
+
for (const a of ((_a = mountedMap.get(atom)) == null ? void 0 : _a.t) || []) {
|
|
84
|
+
dependents.add(a);
|
|
85
|
+
}
|
|
86
|
+
for (const atomWithPendingPromise of atomState.p) {
|
|
87
|
+
dependents.add(atomWithPendingPromise);
|
|
88
|
+
}
|
|
89
|
+
return dependents;
|
|
90
|
+
}
|
|
91
|
+
const atomRead = (_store, atom, ...params) => atom.read(...params);
|
|
92
|
+
const atomWrite = (_store, atom, ...params) => atom.write(...params);
|
|
93
|
+
const atomOnInit = (store, atom) => {
|
|
94
|
+
if (atom.INTERNAL_onInit) {
|
|
95
|
+
return atom.INTERNAL_onInit(store);
|
|
96
|
+
}
|
|
97
|
+
if (atom.unstable_onInit) {
|
|
98
|
+
console.warn(
|
|
99
|
+
"[DEPRECATED] atom.unstable_onInit is renamed to atom.INTERNAL_onInit."
|
|
100
|
+
);
|
|
101
|
+
return atom.unstable_onInit(store);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const atomOnMount = (_store, atom, setAtom) => {
|
|
105
|
+
var _a;
|
|
106
|
+
return (_a = atom.onMount) == null ? void 0 : _a.call(atom, setAtom);
|
|
107
|
+
};
|
|
108
|
+
const ensureAtomState = (store, atom) => {
|
|
109
|
+
var _a;
|
|
110
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
111
|
+
const atomStateMap = buildingBlocks[0];
|
|
112
|
+
const storeHooks = buildingBlocks[6];
|
|
113
|
+
const atomOnInit2 = buildingBlocks[9];
|
|
114
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && !atom) {
|
|
115
|
+
throw new Error("Atom is undefined or null");
|
|
116
|
+
}
|
|
117
|
+
let atomState = atomStateMap.get(atom);
|
|
118
|
+
if (!atomState) {
|
|
119
|
+
atomState = { d: /* @__PURE__ */ new Map(), p: /* @__PURE__ */ new Set(), n: 0 };
|
|
120
|
+
atomStateMap.set(atom, atomState);
|
|
121
|
+
(_a = storeHooks.i) == null ? void 0 : _a.call(storeHooks, atom);
|
|
122
|
+
atomOnInit2 == null ? void 0 : atomOnInit2(store, atom);
|
|
123
|
+
}
|
|
124
|
+
return atomState;
|
|
125
|
+
};
|
|
126
|
+
const flushCallbacks = (store) => {
|
|
127
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
128
|
+
const mountedMap = buildingBlocks[1];
|
|
129
|
+
const changedAtoms = buildingBlocks[3];
|
|
130
|
+
const mountCallbacks = buildingBlocks[4];
|
|
131
|
+
const unmountCallbacks = buildingBlocks[5];
|
|
132
|
+
const storeHooks = buildingBlocks[6];
|
|
133
|
+
const recomputeInvalidatedAtoms2 = buildingBlocks[13];
|
|
134
|
+
const errors = [];
|
|
135
|
+
const call = (fn) => {
|
|
136
|
+
try {
|
|
137
|
+
fn();
|
|
138
|
+
} catch (e) {
|
|
139
|
+
errors.push(e);
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
do {
|
|
143
|
+
if (storeHooks.f) {
|
|
144
|
+
call(storeHooks.f);
|
|
145
|
+
}
|
|
146
|
+
const callbacks = /* @__PURE__ */ new Set();
|
|
147
|
+
const add = callbacks.add.bind(callbacks);
|
|
148
|
+
changedAtoms.forEach((atom) => {
|
|
149
|
+
var _a;
|
|
150
|
+
return (_a = mountedMap.get(atom)) == null ? void 0 : _a.l.forEach(add);
|
|
151
|
+
});
|
|
152
|
+
changedAtoms.clear();
|
|
153
|
+
unmountCallbacks.forEach(add);
|
|
154
|
+
unmountCallbacks.clear();
|
|
155
|
+
mountCallbacks.forEach(add);
|
|
156
|
+
mountCallbacks.clear();
|
|
157
|
+
callbacks.forEach(call);
|
|
158
|
+
if (changedAtoms.size) {
|
|
159
|
+
recomputeInvalidatedAtoms2(store);
|
|
160
|
+
}
|
|
161
|
+
} while (changedAtoms.size || unmountCallbacks.size || mountCallbacks.size);
|
|
162
|
+
if (errors.length) {
|
|
163
|
+
throw new AggregateError(errors);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
const recomputeInvalidatedAtoms = (store) => {
|
|
167
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
168
|
+
const mountedMap = buildingBlocks[1];
|
|
169
|
+
const invalidatedAtoms = buildingBlocks[2];
|
|
170
|
+
const changedAtoms = buildingBlocks[3];
|
|
171
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
172
|
+
const readAtomState2 = buildingBlocks[14];
|
|
173
|
+
const mountDependencies2 = buildingBlocks[17];
|
|
174
|
+
const topSortedReversed = [];
|
|
175
|
+
const visiting = /* @__PURE__ */ new WeakSet();
|
|
176
|
+
const visited = /* @__PURE__ */ new WeakSet();
|
|
177
|
+
const stack = Array.from(changedAtoms);
|
|
178
|
+
while (stack.length) {
|
|
179
|
+
const a = stack[stack.length - 1];
|
|
180
|
+
const aState = ensureAtomState2(store, a);
|
|
181
|
+
if (visited.has(a)) {
|
|
182
|
+
stack.pop();
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (visiting.has(a)) {
|
|
186
|
+
if (invalidatedAtoms.get(a) === aState.n) {
|
|
187
|
+
topSortedReversed.push([a, aState]);
|
|
188
|
+
} else if ((undefined ? undefined.MODE : void 0) !== "production" && invalidatedAtoms.has(a)) {
|
|
189
|
+
throw new Error("[Bug] invalidated atom exists");
|
|
190
|
+
}
|
|
191
|
+
visited.add(a);
|
|
192
|
+
stack.pop();
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
visiting.add(a);
|
|
196
|
+
for (const d of getMountedOrPendingDependents(a, aState, mountedMap)) {
|
|
197
|
+
if (!visiting.has(d)) {
|
|
198
|
+
stack.push(d);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
for (let i = topSortedReversed.length - 1; i >= 0; --i) {
|
|
203
|
+
const [a, aState] = topSortedReversed[i];
|
|
204
|
+
let hasChangedDeps = false;
|
|
205
|
+
for (const dep of aState.d.keys()) {
|
|
206
|
+
if (dep !== a && changedAtoms.has(dep)) {
|
|
207
|
+
hasChangedDeps = true;
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (hasChangedDeps) {
|
|
212
|
+
readAtomState2(store, a);
|
|
213
|
+
mountDependencies2(store, a);
|
|
214
|
+
}
|
|
215
|
+
invalidatedAtoms.delete(a);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
const storeMutationSet = /* @__PURE__ */ new WeakSet();
|
|
219
|
+
const readAtomState = (store, atom) => {
|
|
220
|
+
var _a, _b;
|
|
221
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
222
|
+
const mountedMap = buildingBlocks[1];
|
|
223
|
+
const invalidatedAtoms = buildingBlocks[2];
|
|
224
|
+
const changedAtoms = buildingBlocks[3];
|
|
225
|
+
const storeHooks = buildingBlocks[6];
|
|
226
|
+
const atomRead2 = buildingBlocks[7];
|
|
227
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
228
|
+
const flushCallbacks2 = buildingBlocks[12];
|
|
229
|
+
const recomputeInvalidatedAtoms2 = buildingBlocks[13];
|
|
230
|
+
const readAtomState2 = buildingBlocks[14];
|
|
231
|
+
const writeAtomState2 = buildingBlocks[16];
|
|
232
|
+
const mountDependencies2 = buildingBlocks[17];
|
|
233
|
+
const atomState = ensureAtomState2(store, atom);
|
|
234
|
+
if (isAtomStateInitialized(atomState)) {
|
|
235
|
+
if (mountedMap.has(atom) && invalidatedAtoms.get(atom) !== atomState.n) {
|
|
236
|
+
return atomState;
|
|
237
|
+
}
|
|
238
|
+
let hasChangedDeps = false;
|
|
239
|
+
for (const [a, n] of atomState.d) {
|
|
240
|
+
if (readAtomState2(store, a).n !== n) {
|
|
241
|
+
hasChangedDeps = true;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if (!hasChangedDeps) {
|
|
246
|
+
return atomState;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
atomState.d.clear();
|
|
250
|
+
let isSync = true;
|
|
251
|
+
function mountDependenciesIfAsync() {
|
|
252
|
+
if (mountedMap.has(atom)) {
|
|
253
|
+
mountDependencies2(store, atom);
|
|
254
|
+
recomputeInvalidatedAtoms2(store);
|
|
255
|
+
flushCallbacks2(store);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
function getter(a) {
|
|
259
|
+
var _a2;
|
|
260
|
+
if (a === atom) {
|
|
261
|
+
const aState2 = ensureAtomState2(store, a);
|
|
262
|
+
if (!isAtomStateInitialized(aState2)) {
|
|
263
|
+
if (hasInitialValue(a)) {
|
|
264
|
+
setAtomStateValueOrPromise(store, a, a.init);
|
|
265
|
+
} else {
|
|
266
|
+
throw new Error("no atom init");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
return returnAtomValue(aState2);
|
|
270
|
+
}
|
|
271
|
+
const aState = readAtomState2(store, a);
|
|
272
|
+
try {
|
|
273
|
+
return returnAtomValue(aState);
|
|
274
|
+
} finally {
|
|
275
|
+
atomState.d.set(a, aState.n);
|
|
276
|
+
if (isPendingPromise(atomState.v)) {
|
|
277
|
+
addPendingPromiseToDependency(atom, atomState.v, aState);
|
|
278
|
+
}
|
|
279
|
+
if (mountedMap.has(atom)) {
|
|
280
|
+
(_a2 = mountedMap.get(a)) == null ? void 0 : _a2.t.add(atom);
|
|
281
|
+
}
|
|
282
|
+
if (!isSync) {
|
|
283
|
+
mountDependenciesIfAsync();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
let controller;
|
|
288
|
+
let setSelf;
|
|
289
|
+
const options = {
|
|
290
|
+
get signal() {
|
|
291
|
+
if (!controller) {
|
|
292
|
+
controller = new AbortController();
|
|
293
|
+
}
|
|
294
|
+
return controller.signal;
|
|
295
|
+
},
|
|
296
|
+
get setSelf() {
|
|
297
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && !isActuallyWritableAtom(atom)) {
|
|
298
|
+
console.warn("setSelf function cannot be used with read-only atom");
|
|
299
|
+
}
|
|
300
|
+
if (!setSelf && isActuallyWritableAtom(atom)) {
|
|
301
|
+
setSelf = (...args) => {
|
|
302
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && isSync) {
|
|
303
|
+
console.warn("setSelf function cannot be called in sync");
|
|
304
|
+
}
|
|
305
|
+
if (!isSync) {
|
|
306
|
+
try {
|
|
307
|
+
return writeAtomState2(store, atom, ...args);
|
|
308
|
+
} finally {
|
|
309
|
+
recomputeInvalidatedAtoms2(store);
|
|
310
|
+
flushCallbacks2(store);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
return setSelf;
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const prevEpochNumber = atomState.n;
|
|
319
|
+
try {
|
|
320
|
+
if ((undefined ? undefined.MODE : void 0) !== "production") {
|
|
321
|
+
storeMutationSet.delete(store);
|
|
322
|
+
}
|
|
323
|
+
const valueOrPromise = atomRead2(store, atom, getter, options);
|
|
324
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && storeMutationSet.has(store)) {
|
|
325
|
+
console.warn(
|
|
326
|
+
"Detected store mutation during atom read. This is not supported."
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
setAtomStateValueOrPromise(store, atom, valueOrPromise);
|
|
330
|
+
if (isPromiseLike$1(valueOrPromise)) {
|
|
331
|
+
registerAbortHandler(valueOrPromise, () => controller == null ? void 0 : controller.abort());
|
|
332
|
+
valueOrPromise.then(mountDependenciesIfAsync, mountDependenciesIfAsync);
|
|
333
|
+
}
|
|
334
|
+
(_a = storeHooks.r) == null ? void 0 : _a.call(storeHooks, atom);
|
|
335
|
+
return atomState;
|
|
336
|
+
} catch (error) {
|
|
337
|
+
delete atomState.v;
|
|
338
|
+
atomState.e = error;
|
|
339
|
+
++atomState.n;
|
|
340
|
+
return atomState;
|
|
341
|
+
} finally {
|
|
342
|
+
isSync = false;
|
|
343
|
+
if (prevEpochNumber !== atomState.n && invalidatedAtoms.get(atom) === prevEpochNumber) {
|
|
344
|
+
invalidatedAtoms.set(atom, atomState.n);
|
|
345
|
+
changedAtoms.add(atom);
|
|
346
|
+
(_b = storeHooks.c) == null ? void 0 : _b.call(storeHooks, atom);
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
const invalidateDependents = (store, atom) => {
|
|
351
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
352
|
+
const mountedMap = buildingBlocks[1];
|
|
353
|
+
const invalidatedAtoms = buildingBlocks[2];
|
|
354
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
355
|
+
const stack = [atom];
|
|
356
|
+
while (stack.length) {
|
|
357
|
+
const a = stack.pop();
|
|
358
|
+
const aState = ensureAtomState2(store, a);
|
|
359
|
+
for (const d of getMountedOrPendingDependents(a, aState, mountedMap)) {
|
|
360
|
+
const dState = ensureAtomState2(store, d);
|
|
361
|
+
invalidatedAtoms.set(d, dState.n);
|
|
362
|
+
stack.push(d);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const writeAtomState = (store, atom, ...args) => {
|
|
367
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
368
|
+
const changedAtoms = buildingBlocks[3];
|
|
369
|
+
const storeHooks = buildingBlocks[6];
|
|
370
|
+
const atomWrite2 = buildingBlocks[8];
|
|
371
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
372
|
+
const flushCallbacks2 = buildingBlocks[12];
|
|
373
|
+
const recomputeInvalidatedAtoms2 = buildingBlocks[13];
|
|
374
|
+
const readAtomState2 = buildingBlocks[14];
|
|
375
|
+
const invalidateDependents2 = buildingBlocks[15];
|
|
376
|
+
const mountDependencies2 = buildingBlocks[17];
|
|
377
|
+
let isSync = true;
|
|
378
|
+
const getter = (a) => returnAtomValue(readAtomState2(store, a));
|
|
379
|
+
const setter = (a, ...args2) => {
|
|
380
|
+
var _a;
|
|
381
|
+
const aState = ensureAtomState2(store, a);
|
|
382
|
+
try {
|
|
383
|
+
if (a === atom) {
|
|
384
|
+
if (!hasInitialValue(a)) {
|
|
385
|
+
throw new Error("atom not writable");
|
|
386
|
+
}
|
|
387
|
+
if ((undefined ? undefined.MODE : void 0) !== "production") {
|
|
388
|
+
storeMutationSet.add(store);
|
|
389
|
+
}
|
|
390
|
+
const prevEpochNumber = aState.n;
|
|
391
|
+
const v = args2[0];
|
|
392
|
+
setAtomStateValueOrPromise(store, a, v);
|
|
393
|
+
mountDependencies2(store, a);
|
|
394
|
+
if (prevEpochNumber !== aState.n) {
|
|
395
|
+
changedAtoms.add(a);
|
|
396
|
+
invalidateDependents2(store, a);
|
|
397
|
+
(_a = storeHooks.c) == null ? void 0 : _a.call(storeHooks, a);
|
|
398
|
+
}
|
|
399
|
+
return void 0;
|
|
400
|
+
} else {
|
|
401
|
+
return writeAtomState(store, a, ...args2);
|
|
402
|
+
}
|
|
403
|
+
} finally {
|
|
404
|
+
if (!isSync) {
|
|
405
|
+
recomputeInvalidatedAtoms2(store);
|
|
406
|
+
flushCallbacks2(store);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
try {
|
|
411
|
+
return atomWrite2(store, atom, getter, setter, ...args);
|
|
412
|
+
} finally {
|
|
413
|
+
isSync = false;
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
const mountDependencies = (store, atom) => {
|
|
417
|
+
var _a;
|
|
418
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
419
|
+
const mountedMap = buildingBlocks[1];
|
|
420
|
+
const changedAtoms = buildingBlocks[3];
|
|
421
|
+
const storeHooks = buildingBlocks[6];
|
|
422
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
423
|
+
const invalidateDependents2 = buildingBlocks[15];
|
|
424
|
+
const mountAtom2 = buildingBlocks[18];
|
|
425
|
+
const unmountAtom2 = buildingBlocks[19];
|
|
426
|
+
const atomState = ensureAtomState2(store, atom);
|
|
427
|
+
const mounted = mountedMap.get(atom);
|
|
428
|
+
if (mounted && !isPendingPromise(atomState.v)) {
|
|
429
|
+
for (const [a, n] of atomState.d) {
|
|
430
|
+
if (!mounted.d.has(a)) {
|
|
431
|
+
const aState = ensureAtomState2(store, a);
|
|
432
|
+
const aMounted = mountAtom2(store, a);
|
|
433
|
+
aMounted.t.add(atom);
|
|
434
|
+
mounted.d.add(a);
|
|
435
|
+
if (n !== aState.n) {
|
|
436
|
+
changedAtoms.add(a);
|
|
437
|
+
invalidateDependents2(store, a);
|
|
438
|
+
(_a = storeHooks.c) == null ? void 0 : _a.call(storeHooks, a);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
for (const a of mounted.d) {
|
|
443
|
+
if (!atomState.d.has(a)) {
|
|
444
|
+
mounted.d.delete(a);
|
|
445
|
+
const aMounted = unmountAtom2(store, a);
|
|
446
|
+
aMounted == null ? void 0 : aMounted.t.delete(atom);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
const mountAtom = (store, atom) => {
|
|
452
|
+
var _a;
|
|
453
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
454
|
+
const mountedMap = buildingBlocks[1];
|
|
455
|
+
const mountCallbacks = buildingBlocks[4];
|
|
456
|
+
const storeHooks = buildingBlocks[6];
|
|
457
|
+
const atomOnMount2 = buildingBlocks[10];
|
|
458
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
459
|
+
const flushCallbacks2 = buildingBlocks[12];
|
|
460
|
+
const recomputeInvalidatedAtoms2 = buildingBlocks[13];
|
|
461
|
+
const readAtomState2 = buildingBlocks[14];
|
|
462
|
+
const writeAtomState2 = buildingBlocks[16];
|
|
463
|
+
const atomState = ensureAtomState2(store, atom);
|
|
464
|
+
let mounted = mountedMap.get(atom);
|
|
465
|
+
if (!mounted) {
|
|
466
|
+
readAtomState2(store, atom);
|
|
467
|
+
for (const a of atomState.d.keys()) {
|
|
468
|
+
const aMounted = mountAtom(store, a);
|
|
469
|
+
aMounted.t.add(atom);
|
|
470
|
+
}
|
|
471
|
+
mounted = {
|
|
472
|
+
l: /* @__PURE__ */ new Set(),
|
|
473
|
+
d: new Set(atomState.d.keys()),
|
|
474
|
+
t: /* @__PURE__ */ new Set()
|
|
475
|
+
};
|
|
476
|
+
mountedMap.set(atom, mounted);
|
|
477
|
+
if (isActuallyWritableAtom(atom)) {
|
|
478
|
+
const processOnMount = () => {
|
|
479
|
+
let isSync = true;
|
|
480
|
+
const setAtom = (...args) => {
|
|
481
|
+
try {
|
|
482
|
+
return writeAtomState2(store, atom, ...args);
|
|
483
|
+
} finally {
|
|
484
|
+
if (!isSync) {
|
|
485
|
+
recomputeInvalidatedAtoms2(store);
|
|
486
|
+
flushCallbacks2(store);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
try {
|
|
491
|
+
const onUnmount = atomOnMount2(store, atom, setAtom);
|
|
492
|
+
if (onUnmount) {
|
|
493
|
+
mounted.u = () => {
|
|
494
|
+
isSync = true;
|
|
495
|
+
try {
|
|
496
|
+
onUnmount();
|
|
497
|
+
} finally {
|
|
498
|
+
isSync = false;
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
} finally {
|
|
503
|
+
isSync = false;
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
mountCallbacks.add(processOnMount);
|
|
507
|
+
}
|
|
508
|
+
(_a = storeHooks.m) == null ? void 0 : _a.call(storeHooks, atom);
|
|
509
|
+
}
|
|
510
|
+
return mounted;
|
|
511
|
+
};
|
|
512
|
+
const unmountAtom = (store, atom) => {
|
|
513
|
+
var _a, _b;
|
|
514
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
515
|
+
const mountedMap = buildingBlocks[1];
|
|
516
|
+
const unmountCallbacks = buildingBlocks[5];
|
|
517
|
+
const storeHooks = buildingBlocks[6];
|
|
518
|
+
const ensureAtomState2 = buildingBlocks[11];
|
|
519
|
+
const unmountAtom2 = buildingBlocks[19];
|
|
520
|
+
const atomState = ensureAtomState2(store, atom);
|
|
521
|
+
let mounted = mountedMap.get(atom);
|
|
522
|
+
if (!mounted || mounted.l.size) {
|
|
523
|
+
return mounted;
|
|
524
|
+
}
|
|
525
|
+
let isDependent = false;
|
|
526
|
+
for (const a of mounted.t) {
|
|
527
|
+
if ((_a = mountedMap.get(a)) == null ? void 0 : _a.d.has(atom)) {
|
|
528
|
+
isDependent = true;
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (!isDependent) {
|
|
533
|
+
if (mounted.u) {
|
|
534
|
+
unmountCallbacks.add(mounted.u);
|
|
535
|
+
}
|
|
536
|
+
mounted = void 0;
|
|
537
|
+
mountedMap.delete(atom);
|
|
538
|
+
for (const a of atomState.d.keys()) {
|
|
539
|
+
const aMounted = unmountAtom2(store, a);
|
|
540
|
+
aMounted == null ? void 0 : aMounted.t.delete(atom);
|
|
541
|
+
}
|
|
542
|
+
(_b = storeHooks.u) == null ? void 0 : _b.call(storeHooks, atom);
|
|
543
|
+
return void 0;
|
|
544
|
+
}
|
|
545
|
+
return mounted;
|
|
546
|
+
};
|
|
547
|
+
const setAtomStateValueOrPromise = (store, atom, valueOrPromise) => {
|
|
548
|
+
const ensureAtomState2 = getInternalBuildingBlocks(store)[11];
|
|
549
|
+
const atomState = ensureAtomState2(store, atom);
|
|
550
|
+
const hasPrevValue = "v" in atomState;
|
|
551
|
+
const prevValue = atomState.v;
|
|
552
|
+
if (isPromiseLike$1(valueOrPromise)) {
|
|
553
|
+
for (const a of atomState.d.keys()) {
|
|
554
|
+
addPendingPromiseToDependency(
|
|
555
|
+
atom,
|
|
556
|
+
valueOrPromise,
|
|
557
|
+
ensureAtomState2(store, a)
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
atomState.v = valueOrPromise;
|
|
562
|
+
delete atomState.e;
|
|
563
|
+
if (!hasPrevValue || !Object.is(prevValue, atomState.v)) {
|
|
564
|
+
++atomState.n;
|
|
565
|
+
if (isPromiseLike$1(prevValue)) {
|
|
566
|
+
abortPromise(prevValue);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
const storeGet = (store, atom) => {
|
|
571
|
+
const readAtomState2 = getInternalBuildingBlocks(store)[14];
|
|
572
|
+
return returnAtomValue(readAtomState2(store, atom));
|
|
573
|
+
};
|
|
574
|
+
const storeSet = (store, atom, ...args) => {
|
|
575
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
576
|
+
const flushCallbacks2 = buildingBlocks[12];
|
|
577
|
+
const recomputeInvalidatedAtoms2 = buildingBlocks[13];
|
|
578
|
+
const writeAtomState2 = buildingBlocks[16];
|
|
579
|
+
try {
|
|
580
|
+
return writeAtomState2(store, atom, ...args);
|
|
581
|
+
} finally {
|
|
582
|
+
recomputeInvalidatedAtoms2(store);
|
|
583
|
+
flushCallbacks2(store);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
const storeSub = (store, atom, listener) => {
|
|
587
|
+
const buildingBlocks = getInternalBuildingBlocks(store);
|
|
588
|
+
const flushCallbacks2 = buildingBlocks[12];
|
|
589
|
+
const mountAtom2 = buildingBlocks[18];
|
|
590
|
+
const unmountAtom2 = buildingBlocks[19];
|
|
591
|
+
const mounted = mountAtom2(store, atom);
|
|
592
|
+
const listeners = mounted.l;
|
|
593
|
+
listeners.add(listener);
|
|
594
|
+
flushCallbacks2(store);
|
|
595
|
+
return () => {
|
|
596
|
+
listeners.delete(listener);
|
|
597
|
+
unmountAtom2(store, atom);
|
|
598
|
+
flushCallbacks2(store);
|
|
599
|
+
};
|
|
600
|
+
};
|
|
601
|
+
const buildingBlockMap = /* @__PURE__ */ new WeakMap();
|
|
602
|
+
const getInternalBuildingBlocks = (store) => {
|
|
603
|
+
const buildingBlocks = buildingBlockMap.get(store);
|
|
604
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && !buildingBlocks) {
|
|
605
|
+
throw new Error(
|
|
606
|
+
"Store must be created by buildStore to read its building blocks"
|
|
607
|
+
);
|
|
608
|
+
}
|
|
609
|
+
return buildingBlocks;
|
|
610
|
+
};
|
|
611
|
+
function buildStore(...buildArgs) {
|
|
612
|
+
const store = {
|
|
613
|
+
get(atom) {
|
|
614
|
+
const storeGet2 = getInternalBuildingBlocks(store)[21];
|
|
615
|
+
return storeGet2(store, atom);
|
|
616
|
+
},
|
|
617
|
+
set(atom, ...args) {
|
|
618
|
+
const storeSet2 = getInternalBuildingBlocks(store)[22];
|
|
619
|
+
return storeSet2(store, atom, ...args);
|
|
620
|
+
},
|
|
621
|
+
sub(atom, listener) {
|
|
622
|
+
const storeSub2 = getInternalBuildingBlocks(store)[23];
|
|
623
|
+
return storeSub2(store, atom, listener);
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
const buildingBlocks = [
|
|
627
|
+
// store state
|
|
628
|
+
/* @__PURE__ */ new WeakMap(),
|
|
629
|
+
// atomStateMap
|
|
630
|
+
/* @__PURE__ */ new WeakMap(),
|
|
631
|
+
// mountedMap
|
|
632
|
+
/* @__PURE__ */ new WeakMap(),
|
|
633
|
+
// invalidatedAtoms
|
|
634
|
+
/* @__PURE__ */ new Set(),
|
|
635
|
+
// changedAtoms
|
|
636
|
+
/* @__PURE__ */ new Set(),
|
|
637
|
+
// mountCallbacks
|
|
638
|
+
/* @__PURE__ */ new Set(),
|
|
639
|
+
// unmountCallbacks
|
|
640
|
+
{},
|
|
641
|
+
// storeHooks
|
|
642
|
+
// atom interceptors
|
|
643
|
+
atomRead,
|
|
644
|
+
atomWrite,
|
|
645
|
+
atomOnInit,
|
|
646
|
+
atomOnMount,
|
|
647
|
+
// building-block functions
|
|
648
|
+
ensureAtomState,
|
|
649
|
+
flushCallbacks,
|
|
650
|
+
recomputeInvalidatedAtoms,
|
|
651
|
+
readAtomState,
|
|
652
|
+
invalidateDependents,
|
|
653
|
+
writeAtomState,
|
|
654
|
+
mountDependencies,
|
|
655
|
+
mountAtom,
|
|
656
|
+
unmountAtom,
|
|
657
|
+
setAtomStateValueOrPromise,
|
|
658
|
+
storeGet,
|
|
659
|
+
storeSet,
|
|
660
|
+
storeSub,
|
|
661
|
+
void 0
|
|
662
|
+
].map((fn, i) => buildArgs[i] || fn);
|
|
663
|
+
buildingBlockMap.set(store, Object.freeze(buildingBlocks));
|
|
664
|
+
return store;
|
|
665
|
+
}let keyCount = 0;
|
|
666
|
+
function atom(read, write) {
|
|
667
|
+
const key = `atom${++keyCount}`;
|
|
668
|
+
const config = {
|
|
669
|
+
toString() {
|
|
670
|
+
return (undefined ? undefined.MODE : void 0) !== "production" && this.debugLabel ? key + ":" + this.debugLabel : key;
|
|
671
|
+
}
|
|
672
|
+
};
|
|
673
|
+
if (typeof read === "function") {
|
|
674
|
+
config.read = read;
|
|
675
|
+
} else {
|
|
676
|
+
config.init = read;
|
|
677
|
+
config.read = defaultRead;
|
|
678
|
+
config.write = defaultWrite;
|
|
679
|
+
}
|
|
680
|
+
if (write) {
|
|
681
|
+
config.write = write;
|
|
682
|
+
}
|
|
683
|
+
return config;
|
|
684
|
+
}
|
|
685
|
+
function defaultRead(get) {
|
|
686
|
+
return get(this);
|
|
687
|
+
}
|
|
688
|
+
function defaultWrite(get, set, arg) {
|
|
689
|
+
return set(
|
|
690
|
+
this,
|
|
691
|
+
typeof arg === "function" ? arg(get(this)) : arg
|
|
692
|
+
);
|
|
693
|
+
}
|
|
694
|
+
function createStore() {
|
|
695
|
+
return buildStore();
|
|
696
|
+
}
|
|
697
|
+
let defaultStore;
|
|
698
|
+
function getDefaultStore() {
|
|
699
|
+
if (!defaultStore) {
|
|
700
|
+
defaultStore = createStore();
|
|
701
|
+
if ((undefined ? undefined.MODE : void 0) !== "production") {
|
|
702
|
+
globalThis.__JOTAI_DEFAULT_STORE__ || (globalThis.__JOTAI_DEFAULT_STORE__ = defaultStore);
|
|
703
|
+
if (globalThis.__JOTAI_DEFAULT_STORE__ !== defaultStore) {
|
|
704
|
+
console.warn(
|
|
705
|
+
"Detected multiple Jotai instances. It may cause unexpected behavior with the default store. https://github.com/pmndrs/jotai/discussions/2044"
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
return defaultStore;
|
|
711
|
+
}const StoreContext = React.createContext(
|
|
712
|
+
void 0
|
|
713
|
+
);
|
|
714
|
+
function useStore(options) {
|
|
715
|
+
const store = React.useContext(StoreContext);
|
|
716
|
+
return store || getDefaultStore();
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
const isPromiseLike = (x) => typeof (x == null ? void 0 : x.then) === "function";
|
|
720
|
+
const attachPromiseStatus = (promise) => {
|
|
721
|
+
if (!promise.status) {
|
|
722
|
+
promise.status = "pending";
|
|
723
|
+
promise.then(
|
|
724
|
+
(v) => {
|
|
725
|
+
promise.status = "fulfilled";
|
|
726
|
+
promise.value = v;
|
|
727
|
+
},
|
|
728
|
+
(e) => {
|
|
729
|
+
promise.status = "rejected";
|
|
730
|
+
promise.reason = e;
|
|
731
|
+
}
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
};
|
|
735
|
+
const use = React.use || // A shim for older React versions
|
|
736
|
+
((promise) => {
|
|
737
|
+
if (promise.status === "pending") {
|
|
738
|
+
throw promise;
|
|
739
|
+
} else if (promise.status === "fulfilled") {
|
|
740
|
+
return promise.value;
|
|
741
|
+
} else if (promise.status === "rejected") {
|
|
742
|
+
throw promise.reason;
|
|
743
|
+
} else {
|
|
744
|
+
attachPromiseStatus(promise);
|
|
745
|
+
throw promise;
|
|
746
|
+
}
|
|
747
|
+
});
|
|
748
|
+
const continuablePromiseMap = /* @__PURE__ */ new WeakMap();
|
|
749
|
+
const createContinuablePromise = (promise, getValue) => {
|
|
750
|
+
let continuablePromise = continuablePromiseMap.get(promise);
|
|
751
|
+
if (!continuablePromise) {
|
|
752
|
+
continuablePromise = new Promise((resolve, reject) => {
|
|
753
|
+
let curr = promise;
|
|
754
|
+
const onFulfilled = (me) => (v) => {
|
|
755
|
+
if (curr === me) {
|
|
756
|
+
resolve(v);
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
const onRejected = (me) => (e) => {
|
|
760
|
+
if (curr === me) {
|
|
761
|
+
reject(e);
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
const onAbort = () => {
|
|
765
|
+
try {
|
|
766
|
+
const nextValue = getValue();
|
|
767
|
+
if (isPromiseLike(nextValue)) {
|
|
768
|
+
continuablePromiseMap.set(nextValue, continuablePromise);
|
|
769
|
+
curr = nextValue;
|
|
770
|
+
nextValue.then(onFulfilled(nextValue), onRejected(nextValue));
|
|
771
|
+
registerAbortHandler(nextValue, onAbort);
|
|
772
|
+
} else {
|
|
773
|
+
resolve(nextValue);
|
|
774
|
+
}
|
|
775
|
+
} catch (e) {
|
|
776
|
+
reject(e);
|
|
777
|
+
}
|
|
778
|
+
};
|
|
779
|
+
promise.then(onFulfilled(promise), onRejected(promise));
|
|
780
|
+
registerAbortHandler(promise, onAbort);
|
|
781
|
+
});
|
|
782
|
+
continuablePromiseMap.set(promise, continuablePromise);
|
|
783
|
+
}
|
|
784
|
+
return continuablePromise;
|
|
785
|
+
};
|
|
786
|
+
function useAtomValue(atom, options) {
|
|
787
|
+
const { delay, unstable_promiseStatus: promiseStatus = !React.use } = {};
|
|
788
|
+
const store = useStore();
|
|
789
|
+
const [[valueFromReducer, storeFromReducer, atomFromReducer], rerender] = React.useReducer(
|
|
790
|
+
(prev) => {
|
|
791
|
+
const nextValue = store.get(atom);
|
|
792
|
+
if (Object.is(prev[0], nextValue) && prev[1] === store && prev[2] === atom) {
|
|
793
|
+
return prev;
|
|
794
|
+
}
|
|
795
|
+
return [nextValue, store, atom];
|
|
796
|
+
},
|
|
797
|
+
void 0,
|
|
798
|
+
() => [store.get(atom), store, atom]
|
|
799
|
+
);
|
|
800
|
+
let value = valueFromReducer;
|
|
801
|
+
if (storeFromReducer !== store || atomFromReducer !== atom) {
|
|
802
|
+
rerender();
|
|
803
|
+
value = store.get(atom);
|
|
804
|
+
}
|
|
805
|
+
React.useEffect(() => {
|
|
806
|
+
const unsub = store.sub(atom, () => {
|
|
807
|
+
if (promiseStatus) {
|
|
808
|
+
try {
|
|
809
|
+
const value2 = store.get(atom);
|
|
810
|
+
if (isPromiseLike(value2)) {
|
|
811
|
+
attachPromiseStatus(
|
|
812
|
+
createContinuablePromise(value2, () => store.get(atom))
|
|
813
|
+
);
|
|
814
|
+
}
|
|
815
|
+
} catch (e) {
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
if (typeof delay === "number") {
|
|
819
|
+
setTimeout(rerender, delay);
|
|
820
|
+
return;
|
|
821
|
+
}
|
|
822
|
+
rerender();
|
|
823
|
+
});
|
|
824
|
+
rerender();
|
|
825
|
+
return unsub;
|
|
826
|
+
}, [store, atom, delay, promiseStatus]);
|
|
827
|
+
React.useDebugValue(value);
|
|
828
|
+
if (isPromiseLike(value)) {
|
|
829
|
+
const promise = createContinuablePromise(value, () => store.get(atom));
|
|
830
|
+
if (promiseStatus) {
|
|
831
|
+
attachPromiseStatus(promise);
|
|
832
|
+
}
|
|
833
|
+
return use(promise);
|
|
834
|
+
}
|
|
835
|
+
return value;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
function useSetAtom(atom, options) {
|
|
839
|
+
const store = useStore();
|
|
840
|
+
const setAtom = React.useCallback(
|
|
841
|
+
(...args) => {
|
|
842
|
+
if ((undefined ? undefined.MODE : void 0) !== "production" && !("write" in atom)) {
|
|
843
|
+
throw new Error("not writable atom");
|
|
844
|
+
}
|
|
845
|
+
return store.set(atom, ...args);
|
|
846
|
+
},
|
|
847
|
+
[store, atom]
|
|
848
|
+
);
|
|
849
|
+
return setAtom;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
function useAtom(atom, options) {
|
|
853
|
+
return [
|
|
854
|
+
useAtomValue(atom),
|
|
855
|
+
// We do wrong type assertion here, which results in throwing an error.
|
|
856
|
+
useSetAtom(atom)
|
|
857
|
+
];
|
|
858
|
+
}/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
859
|
+
/**
|
|
860
|
+
* Optimized shallow equality check for objects and functions
|
|
861
|
+
* @param objA - First object to compare
|
|
862
|
+
* @param objB - Second object to compare
|
|
863
|
+
* @returns True if objects are shallow equal
|
|
864
|
+
*/
|
|
865
|
+
function shallowEqual(objA, objB) {
|
|
866
|
+
if (objA === objB) return true;
|
|
867
|
+
if (!objA || !objB) return false;
|
|
868
|
+
if (typeof objA !== 'object' || typeof objB !== 'object') {
|
|
869
|
+
return objA === objB;
|
|
870
|
+
}
|
|
871
|
+
if (typeof objA === 'function' && typeof objB === 'function') {
|
|
872
|
+
return objA.name === objB.name && objA.toString() === objB.toString();
|
|
873
|
+
}
|
|
874
|
+
const keysA = Object.keys(objA);
|
|
875
|
+
const keysB = Object.keys(objB);
|
|
876
|
+
if (keysA.length !== keysB.length) return false;
|
|
877
|
+
for (const key of keysA) {
|
|
878
|
+
if (!keysB.includes(key)) return false;
|
|
879
|
+
const valA = objA[key];
|
|
880
|
+
const valB = objB[key];
|
|
881
|
+
if (typeof valA === 'function' && typeof valB === 'function') {
|
|
882
|
+
if (valA.name !== valB.name || valA.toString() !== valB.toString()) {
|
|
883
|
+
return false;
|
|
884
|
+
}
|
|
885
|
+
continue;
|
|
886
|
+
}
|
|
887
|
+
if (valA !== valB) return false;
|
|
888
|
+
}
|
|
889
|
+
return true;
|
|
890
|
+
}
|
|
891
|
+
/**
|
|
892
|
+
* Checks if a value is stable for React dependency arrays
|
|
893
|
+
* @param value - Value to check for stability
|
|
894
|
+
* @returns True if value is considered stable
|
|
895
|
+
*/
|
|
896
|
+
function isStableValue(value) {
|
|
897
|
+
if (value === null || value === undefined) return true;
|
|
898
|
+
if (typeof value !== 'object' && typeof value !== 'function') return true;
|
|
899
|
+
if (typeof value === 'function') return value.toString().length < 1000;
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
/**
|
|
903
|
+
* Creates an optimized dependency array by filtering unstable values
|
|
904
|
+
* @param deps - Array of dependencies to optimize
|
|
905
|
+
* @returns Filtered array of stable dependencies
|
|
906
|
+
*/
|
|
907
|
+
function optimizeDeps(deps) {
|
|
908
|
+
return deps.filter(dep => isStableValue(dep) || typeof dep === 'object');
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Custom prop comparator for React.memo() to prevent unnecessary re-renders
|
|
912
|
+
* Compares props shallowly and ignores function references if they have the same name
|
|
913
|
+
* @param prevProps - Previous component props
|
|
914
|
+
* @param nextProps - Next component props
|
|
915
|
+
* @returns True if props are equal (component should NOT re-render)
|
|
916
|
+
*/
|
|
917
|
+
function memoPropsComparator(prevProps, nextProps) {
|
|
918
|
+
return shallowEqual(prevProps, nextProps);
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Deep equality check for complex objects
|
|
922
|
+
* Use sparingly - prefer shallow equality for performance
|
|
923
|
+
* Uses fast-deep-equal library for optimized deep comparison with circular reference protection
|
|
924
|
+
* @param objA - First object
|
|
925
|
+
* @param objB - Second object
|
|
926
|
+
* @returns True if objects are deeply equal
|
|
927
|
+
*/
|
|
928
|
+
function deepEqual(objA, objB) {
|
|
929
|
+
return equal(objA, objB);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* Memoization cache for expensive computations
|
|
933
|
+
* Simple LRU cache with configurable size
|
|
934
|
+
*/
|
|
935
|
+
class MemoizationCache {
|
|
936
|
+
constructor(maxSize = 100) {
|
|
937
|
+
this.cache = new Map();
|
|
938
|
+
this.maxSize = maxSize;
|
|
939
|
+
}
|
|
940
|
+
get(key) {
|
|
941
|
+
const value = this.cache.get(key);
|
|
942
|
+
if (value !== undefined) {
|
|
943
|
+
// Move to end (most recently used)
|
|
944
|
+
this.cache.delete(key);
|
|
945
|
+
this.cache.set(key, value);
|
|
946
|
+
}
|
|
947
|
+
return value;
|
|
948
|
+
}
|
|
949
|
+
set(key, value) {
|
|
950
|
+
// Delete oldest entry if cache is full
|
|
951
|
+
if (this.cache.size >= this.maxSize) {
|
|
952
|
+
const firstKey = this.cache.keys().next().value;
|
|
953
|
+
if (firstKey !== undefined) {
|
|
954
|
+
this.cache.delete(firstKey);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
this.cache.set(key, value);
|
|
958
|
+
}
|
|
959
|
+
has(key) {
|
|
960
|
+
return this.cache.has(key);
|
|
961
|
+
}
|
|
962
|
+
clear() {
|
|
963
|
+
this.cache.clear();
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Creates a memoized function with custom cache key generator
|
|
968
|
+
* @param fn - Function to memoize
|
|
969
|
+
* @param cacheKeyFn - Optional function to generate cache key from arguments
|
|
970
|
+
* @returns Memoized function
|
|
971
|
+
*/
|
|
972
|
+
function memoize(fn, cacheKeyFn) {
|
|
973
|
+
const cache = new MemoizationCache();
|
|
974
|
+
return (...args) => {
|
|
975
|
+
const cacheKey = cacheKeyFn ? cacheKeyFn(...args) : JSON.stringify(args);
|
|
976
|
+
if (cache.has(cacheKey)) {
|
|
977
|
+
return cache.get(cacheKey);
|
|
978
|
+
}
|
|
979
|
+
const result = fn(...args);
|
|
980
|
+
cache.set(cacheKey, result);
|
|
981
|
+
return result;
|
|
982
|
+
};
|
|
983
|
+
}function atomFamily(initializeAtom, areEqual) {
|
|
984
|
+
let shouldRemove = null;
|
|
985
|
+
const atoms = new Map();
|
|
986
|
+
const listeners = new Set();
|
|
987
|
+
function createAtom(param) {
|
|
988
|
+
let item;
|
|
989
|
+
{
|
|
990
|
+
item = atoms.get(param);
|
|
991
|
+
}
|
|
992
|
+
if (item !== undefined) {
|
|
993
|
+
if (shouldRemove?.(item[1], param)) {
|
|
994
|
+
createAtom.remove(param);
|
|
995
|
+
}
|
|
996
|
+
else {
|
|
997
|
+
return item[0];
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
const newAtom = initializeAtom(param);
|
|
1001
|
+
atoms.set(param, [newAtom, Date.now()]);
|
|
1002
|
+
notifyListeners('CREATE', param, newAtom);
|
|
1003
|
+
return newAtom;
|
|
1004
|
+
}
|
|
1005
|
+
function notifyListeners(type, param, atom) {
|
|
1006
|
+
for (const listener of listeners) {
|
|
1007
|
+
listener({ type, param, atom });
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
createAtom.unstable_listen = (callback) => {
|
|
1011
|
+
listeners.add(callback);
|
|
1012
|
+
return () => {
|
|
1013
|
+
listeners.delete(callback);
|
|
1014
|
+
};
|
|
1015
|
+
};
|
|
1016
|
+
createAtom.getParams = () => atoms.keys();
|
|
1017
|
+
createAtom.remove = (param) => {
|
|
1018
|
+
{
|
|
1019
|
+
if (!atoms.has(param))
|
|
1020
|
+
return;
|
|
1021
|
+
const [atom] = atoms.get(param);
|
|
1022
|
+
atoms.delete(param);
|
|
1023
|
+
notifyListeners('REMOVE', param, atom);
|
|
1024
|
+
}
|
|
1025
|
+
};
|
|
1026
|
+
createAtom.setShouldRemove = (fn) => {
|
|
1027
|
+
shouldRemove = fn;
|
|
1028
|
+
if (!shouldRemove)
|
|
1029
|
+
return;
|
|
1030
|
+
for (const [key, [atom, createdAt]] of atoms) {
|
|
1031
|
+
if (shouldRemove(createdAt, key)) {
|
|
1032
|
+
atoms.delete(key);
|
|
1033
|
+
notifyListeners('REMOVE', key, atom);
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
};
|
|
1037
|
+
return createAtom;
|
|
1038
|
+
}const pageVariablesAtomFamily = atomFamily(_pageId => atom({}));
|
|
1039
|
+
/**
|
|
1040
|
+
* Global atom storing all page variables.
|
|
1041
|
+
* Key format: "scopeId:pageId"
|
|
1042
|
+
*/
|
|
1043
|
+
const pageVariablesAtom = atom({});
|
|
1044
|
+
/**
|
|
1045
|
+
* Helper to generate composite keys for page variables.
|
|
1046
|
+
*/
|
|
1047
|
+
const getPageVariablesCompositeKey = (scopeId, key) => `${scopeId}:${key}`;
|
|
1048
|
+
/**
|
|
1049
|
+
* Creates a derived atom for accessing page variables of a specific scope.
|
|
1050
|
+
*/
|
|
1051
|
+
const createScopePageVariablesAtom = scopeId => atom(get => {
|
|
1052
|
+
const allPageVariables = get(pageVariablesAtom);
|
|
1053
|
+
const prefix = `${scopeId}:`;
|
|
1054
|
+
const scopePageVariables = {};
|
|
1055
|
+
for (const [key, value] of Object.entries(allPageVariables)) {
|
|
1056
|
+
if (key.startsWith(prefix)) {
|
|
1057
|
+
scopePageVariables[key.slice(prefix.length)] = value;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
return scopePageVariables;
|
|
1061
|
+
}, (get, set, update) => {
|
|
1062
|
+
const allPageVariables = get(pageVariablesAtom);
|
|
1063
|
+
const prefix = `${scopeId}:`;
|
|
1064
|
+
const newPageVariables = Object.assign({}, allPageVariables);
|
|
1065
|
+
// Remove old scope entries
|
|
1066
|
+
for (const key of Object.keys(newPageVariables)) {
|
|
1067
|
+
if (key.startsWith(prefix)) {
|
|
1068
|
+
delete newPageVariables[key];
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
// Add new scope entries
|
|
1072
|
+
for (const [key, value] of Object.entries(update)) {
|
|
1073
|
+
newPageVariables[`${prefix}${key}`] = value;
|
|
1074
|
+
}
|
|
1075
|
+
set(pageVariablesAtom, newPageVariables);
|
|
1076
|
+
});const getValueAtPath = (obj, path) => {
|
|
1077
|
+
if (!path) return undefined;
|
|
1078
|
+
const normalized = path.replace(/\[(\d+)\]/g, '.$1');
|
|
1079
|
+
const parts = normalized.split('.').filter(Boolean);
|
|
1080
|
+
let current = obj;
|
|
1081
|
+
for (const part of parts) {
|
|
1082
|
+
if (current == null) return undefined;
|
|
1083
|
+
if (typeof current !== 'object') return undefined;
|
|
1084
|
+
current = current[part];
|
|
1085
|
+
}
|
|
1086
|
+
return current;
|
|
1087
|
+
};
|
|
1088
|
+
const usePageValues = ({
|
|
1089
|
+
pageId,
|
|
1090
|
+
initialValues
|
|
1091
|
+
}) => {
|
|
1092
|
+
const {
|
|
1093
|
+
get: getApiValues
|
|
1094
|
+
} = reactQueries.useApiValues({
|
|
1095
|
+
scopeId: pageId
|
|
1096
|
+
});
|
|
1097
|
+
const {
|
|
1098
|
+
get: getFormValues,
|
|
1099
|
+
set: setFormValues
|
|
1100
|
+
} = reactForm.useFormValues({
|
|
1101
|
+
formId: pageId
|
|
1102
|
+
});
|
|
1103
|
+
const subscriptions = React.useRef(new Map());
|
|
1104
|
+
const [trigger, setTrigger] = React.useState(0);
|
|
1105
|
+
const [pageVariables, setPageVariables] = useAtom(pageVariablesAtomFamily(pageId));
|
|
1106
|
+
const initialized = React.useRef(false);
|
|
1107
|
+
React.useEffect(() => {
|
|
1108
|
+
if (!initialized.current && initialValues) {
|
|
1109
|
+
setPageVariables(initialValues);
|
|
1110
|
+
initialized.current = true;
|
|
1111
|
+
}
|
|
1112
|
+
}, [initialValues, setPageVariables]);
|
|
1113
|
+
const dataRef = React.useRef({
|
|
1114
|
+
state: pageVariables
|
|
1115
|
+
});
|
|
1116
|
+
// Sync dataRef with latest values
|
|
1117
|
+
React.useEffect(() => {
|
|
1118
|
+
let internalTrigger = false;
|
|
1119
|
+
subscriptions.current.forEach((_, key) => {
|
|
1120
|
+
const [type, keyPath] = key.split(':');
|
|
1121
|
+
if (type === 'state') {
|
|
1122
|
+
const newValue = getValueAtPath(pageVariables, keyPath);
|
|
1123
|
+
const oldValue = getValueAtPath(dataRef.current.state, keyPath);
|
|
1124
|
+
internalTrigger = internalTrigger || !equal(newValue, oldValue);
|
|
1125
|
+
}
|
|
1126
|
+
});
|
|
1127
|
+
dataRef.current = {
|
|
1128
|
+
state: pageVariables
|
|
1129
|
+
};
|
|
1130
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1131
|
+
if (internalTrigger) {
|
|
1132
|
+
setTrigger(v => v + 1);
|
|
1133
|
+
}
|
|
1134
|
+
}, [pageVariables]);
|
|
1135
|
+
// get che legge dallo store e registra le dipendenze
|
|
1136
|
+
const get = React.useCallback((type, key, defaultValue) => {
|
|
1137
|
+
var _a;
|
|
1138
|
+
const keyMap = `${type}:${key}`;
|
|
1139
|
+
switch (type) {
|
|
1140
|
+
case 'mutation':
|
|
1141
|
+
{
|
|
1142
|
+
const value = getApiValues(type, key, defaultValue);
|
|
1143
|
+
subscriptions.current.set(keyMap, value);
|
|
1144
|
+
break;
|
|
1145
|
+
}
|
|
1146
|
+
case 'query':
|
|
1147
|
+
{
|
|
1148
|
+
const value = getApiValues(type, key, defaultValue);
|
|
1149
|
+
subscriptions.current.set(keyMap, value);
|
|
1150
|
+
break;
|
|
1151
|
+
}
|
|
1152
|
+
case 'form':
|
|
1153
|
+
{
|
|
1154
|
+
const value = getFormValues(key, defaultValue);
|
|
1155
|
+
subscriptions.current.set(keyMap, value);
|
|
1156
|
+
break;
|
|
1157
|
+
}
|
|
1158
|
+
case 'state':
|
|
1159
|
+
{
|
|
1160
|
+
const value = (_a = getValueAtPath(dataRef.current['state'], String(key))) !== null && _a !== void 0 ? _a : defaultValue;
|
|
1161
|
+
subscriptions.current.set(keyMap, value);
|
|
1162
|
+
break;
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
return subscriptions.current.get(keyMap);
|
|
1166
|
+
},
|
|
1167
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1168
|
+
[pageId, trigger, getApiValues, getFormValues]);
|
|
1169
|
+
// set stabile
|
|
1170
|
+
const set = React.useCallback(type => {
|
|
1171
|
+
if (type === 'form') {
|
|
1172
|
+
return setFormValues;
|
|
1173
|
+
}
|
|
1174
|
+
return (key, value) => {
|
|
1175
|
+
setPageVariables(prev => Object.assign(Object.assign({}, prev), {
|
|
1176
|
+
[key]: value
|
|
1177
|
+
}));
|
|
1178
|
+
};
|
|
1179
|
+
}, [setPageVariables, setFormValues]);
|
|
1180
|
+
return {
|
|
1181
|
+
get,
|
|
1182
|
+
set
|
|
1183
|
+
};
|
|
1184
|
+
};const getStableKey = (content, index) => {
|
|
1185
|
+
var _a;
|
|
1186
|
+
return (_a = content.key) !== null && _a !== void 0 ? _a : `content-${index}`;
|
|
1187
|
+
};
|
|
1188
|
+
const PageContentItemInner = ({
|
|
1189
|
+
item,
|
|
1190
|
+
pageId,
|
|
1191
|
+
ns
|
|
1192
|
+
}) => {
|
|
1193
|
+
var _a;
|
|
1194
|
+
const {
|
|
1195
|
+
get,
|
|
1196
|
+
set
|
|
1197
|
+
} = usePageValues({
|
|
1198
|
+
pageId
|
|
1199
|
+
});
|
|
1200
|
+
const isHidden = React.useMemo(() => {
|
|
1201
|
+
if (typeof item.hidden === 'function') {
|
|
1202
|
+
return item.hidden({
|
|
1203
|
+
get,
|
|
1204
|
+
set
|
|
1205
|
+
});
|
|
1206
|
+
}
|
|
1207
|
+
return !!item.hidden;
|
|
1208
|
+
}, [get, item, set]);
|
|
1209
|
+
if (isHidden) return null;
|
|
1210
|
+
return jsxRuntime.jsx(RenderComponents, {
|
|
1211
|
+
content: item,
|
|
1212
|
+
ns: ns,
|
|
1213
|
+
pageId: pageId
|
|
1214
|
+
}, (_a = item.key) !== null && _a !== void 0 ? _a : '');
|
|
1215
|
+
};
|
|
1216
|
+
const PageContentItem = React.memo(PageContentItemInner);
|
|
1217
|
+
const useGenerateContentRender = ({
|
|
1218
|
+
pageId,
|
|
1219
|
+
ns = '',
|
|
1220
|
+
contents = [],
|
|
1221
|
+
formData
|
|
1222
|
+
}) => {
|
|
1223
|
+
const {
|
|
1224
|
+
get,
|
|
1225
|
+
set
|
|
1226
|
+
} = usePageValues({
|
|
1227
|
+
pageId
|
|
1228
|
+
});
|
|
1229
|
+
const contentsWithQueriesDeps = React.useMemo(() => {
|
|
1230
|
+
if (typeof contents === 'function') {
|
|
1231
|
+
return contents({
|
|
1232
|
+
get,
|
|
1233
|
+
set
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
return Array.isArray(contents) ? contents : [];
|
|
1237
|
+
}, [contents, get, set]);
|
|
1238
|
+
// Memoize form elements separately - only recalculate when formData.elements changes
|
|
1239
|
+
const formElementsWithKey = React.useMemo(() => {
|
|
1240
|
+
if (!Array.isArray(formData.elements)) return [];
|
|
1241
|
+
return formData.elements.map((el, idx) => Object.assign(Object.assign({}, el), {
|
|
1242
|
+
key: `form-element-${el.index || idx}`
|
|
1243
|
+
}));
|
|
1244
|
+
}, [formData.elements]);
|
|
1245
|
+
// Memoize dynamic elements - only recalculate when contents change
|
|
1246
|
+
const dynamicElements = React.useMemo(() => contentsWithQueriesDeps.map((content, index) => {
|
|
1247
|
+
var _a;
|
|
1248
|
+
const stableKey = getStableKey(content, index);
|
|
1249
|
+
return {
|
|
1250
|
+
element: jsxRuntime.jsx(PageContentItem, {
|
|
1251
|
+
item: content,
|
|
1252
|
+
ns: ns,
|
|
1253
|
+
pageId: pageId
|
|
1254
|
+
}, stableKey),
|
|
1255
|
+
index: (_a = content.index) !== null && _a !== void 0 ? _a : index,
|
|
1256
|
+
renderInFooter: !!content.renderInFooter,
|
|
1257
|
+
renderInHeader: !!content.renderInHeader,
|
|
1258
|
+
key: stableKey
|
|
1259
|
+
};
|
|
1260
|
+
}), [contentsWithQueriesDeps, ns, pageId]);
|
|
1261
|
+
// Merge and sort - only when either array changes
|
|
1262
|
+
const memorizedContents = React.useMemo(() => [...dynamicElements, ...formElementsWithKey].sort((a, b) => a.index - b.index || String(a.key).localeCompare(String(b.key))), [dynamicElements, formElementsWithKey]);
|
|
1263
|
+
return {
|
|
1264
|
+
components: memorizedContents,
|
|
1265
|
+
allContents: [...contentsWithQueriesDeps, ...formData.formContents]
|
|
1266
|
+
};
|
|
1267
|
+
};const useGenerateContent = t0 => {
|
|
1268
|
+
const $ = compilerRuntime.c(18);
|
|
1269
|
+
const {
|
|
1270
|
+
pageId,
|
|
1271
|
+
ns: t1,
|
|
1272
|
+
contents: t2,
|
|
1273
|
+
pageConfig
|
|
1274
|
+
} = t0;
|
|
1275
|
+
const ns = t1 === undefined ? "" : t1;
|
|
1276
|
+
let t3;
|
|
1277
|
+
if ($[0] !== t2) {
|
|
1278
|
+
t3 = t2 === undefined ? [] : t2;
|
|
1279
|
+
$[0] = t2;
|
|
1280
|
+
$[1] = t3;
|
|
1281
|
+
} else {
|
|
1282
|
+
t3 = $[1];
|
|
1283
|
+
}
|
|
1284
|
+
const contents = t3;
|
|
1285
|
+
const {
|
|
1286
|
+
formData
|
|
1287
|
+
} = pageConfig;
|
|
1288
|
+
let t4;
|
|
1289
|
+
if ($[2] !== contents || $[3] !== formData || $[4] !== ns || $[5] !== pageId) {
|
|
1290
|
+
t4 = {
|
|
1291
|
+
formData,
|
|
1292
|
+
pageId,
|
|
1293
|
+
contents,
|
|
1294
|
+
ns
|
|
1295
|
+
};
|
|
1296
|
+
$[2] = contents;
|
|
1297
|
+
$[3] = formData;
|
|
1298
|
+
$[4] = ns;
|
|
1299
|
+
$[5] = pageId;
|
|
1300
|
+
$[6] = t4;
|
|
1301
|
+
} else {
|
|
1302
|
+
t4 = $[6];
|
|
1303
|
+
}
|
|
1304
|
+
const {
|
|
1305
|
+
allContents,
|
|
1306
|
+
components
|
|
1307
|
+
} = useGenerateContentRender(t4);
|
|
1308
|
+
let t5;
|
|
1309
|
+
if ($[7] !== components) {
|
|
1310
|
+
t5 = components.filter(_temp$1).map(_temp2$1);
|
|
1311
|
+
$[7] = components;
|
|
1312
|
+
$[8] = t5;
|
|
1313
|
+
} else {
|
|
1314
|
+
t5 = $[8];
|
|
1315
|
+
}
|
|
1316
|
+
const body = t5;
|
|
1317
|
+
let t6;
|
|
1318
|
+
if ($[9] !== components) {
|
|
1319
|
+
t6 = components.filter(_temp3).map(_temp4);
|
|
1320
|
+
$[9] = components;
|
|
1321
|
+
$[10] = t6;
|
|
1322
|
+
} else {
|
|
1323
|
+
t6 = $[10];
|
|
1324
|
+
}
|
|
1325
|
+
const header = t6;
|
|
1326
|
+
let t7;
|
|
1327
|
+
if ($[11] !== components) {
|
|
1328
|
+
t7 = components.filter(_temp5).map(_temp6);
|
|
1329
|
+
$[11] = components;
|
|
1330
|
+
$[12] = t7;
|
|
1331
|
+
} else {
|
|
1332
|
+
t7 = $[12];
|
|
1333
|
+
}
|
|
1334
|
+
const footer = t7;
|
|
1335
|
+
let t8;
|
|
1336
|
+
if ($[13] !== allContents || $[14] !== body || $[15] !== footer || $[16] !== header) {
|
|
1337
|
+
t8 = {
|
|
1338
|
+
header,
|
|
1339
|
+
body,
|
|
1340
|
+
footer,
|
|
1341
|
+
allContents
|
|
1342
|
+
};
|
|
1343
|
+
$[13] = allContents;
|
|
1344
|
+
$[14] = body;
|
|
1345
|
+
$[15] = footer;
|
|
1346
|
+
$[16] = header;
|
|
1347
|
+
$[17] = t8;
|
|
1348
|
+
} else {
|
|
1349
|
+
t8 = $[17];
|
|
1350
|
+
}
|
|
1351
|
+
return t8;
|
|
1352
|
+
};
|
|
1353
|
+
function _temp$1(el) {
|
|
1354
|
+
return !el.renderInFooter && !el.renderInHeader;
|
|
1355
|
+
}
|
|
1356
|
+
function _temp2$1(item) {
|
|
1357
|
+
return item.element;
|
|
1358
|
+
}
|
|
1359
|
+
function _temp3(el_0) {
|
|
1360
|
+
return el_0.renderInHeader;
|
|
1361
|
+
}
|
|
1362
|
+
function _temp4(item_0) {
|
|
1363
|
+
return item_0.element;
|
|
1364
|
+
}
|
|
1365
|
+
function _temp5(el_1) {
|
|
1366
|
+
return el_1.renderInFooter;
|
|
1367
|
+
}
|
|
1368
|
+
function _temp6(item_1) {
|
|
1369
|
+
return item_1.element;
|
|
1370
|
+
}/**
|
|
1371
|
+
* Metadata Store, DOM Application, and Server Collection
|
|
1372
|
+
*
|
|
1373
|
+
* Architecture:
|
|
1374
|
+
* - `createMetadataStore()` → request-scoped store (SSR-safe)
|
|
1375
|
+
* - `applyMetadataToDom(resolved)` → client-side DOM manipulation
|
|
1376
|
+
* - `collectMetadataToHtml(resolved)` → server-side HTML string collection
|
|
1377
|
+
* - `setMetadata / getMetadata / resetMetadata` → backward-compatible global API
|
|
1378
|
+
*
|
|
1379
|
+
* @module config/metadata
|
|
1380
|
+
*/
|
|
1381
|
+
// ─── Platform detection ──────────────────────────────────────
|
|
1382
|
+
const isWeb = typeof document !== 'undefined';
|
|
1383
|
+
// ─── Request-scoped Metadata Store ───────────────────────────
|
|
1384
|
+
/**
|
|
1385
|
+
* Create a new request-scoped metadata store.
|
|
1386
|
+
* In SSR, each incoming request should create its own store
|
|
1387
|
+
* to avoid cross-request data leaks.
|
|
1388
|
+
* On the client, a single global store is used (see below).
|
|
1389
|
+
*/
|
|
1390
|
+
function createMetadataStore() {
|
|
1391
|
+
let metadata = {};
|
|
1392
|
+
return {
|
|
1393
|
+
getMetadata: () => Object.assign({}, metadata),
|
|
1394
|
+
setMetadata: meta => {
|
|
1395
|
+
metadata = Object.assign(Object.assign({}, metadata), meta);
|
|
1396
|
+
},
|
|
1397
|
+
reset: () => {
|
|
1398
|
+
metadata = {};
|
|
1399
|
+
}
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
/** Global store for client-side usage (singleton) */
|
|
1403
|
+
const globalStore = createMetadataStore();
|
|
1404
|
+
// ─── DOM helpers ─────────────────────────────────────────────
|
|
1405
|
+
function updateOrCreateMeta(selector, content, attributes = {}) {
|
|
1406
|
+
let element = document.querySelector(selector);
|
|
1407
|
+
if (!element) {
|
|
1408
|
+
element = document.createElement('meta');
|
|
1409
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
1410
|
+
element === null || element === void 0 ? void 0 : element.setAttribute(key, value);
|
|
1411
|
+
});
|
|
1412
|
+
document.head.appendChild(element);
|
|
1413
|
+
}
|
|
1414
|
+
element.setAttribute('content', content);
|
|
1415
|
+
}
|
|
1416
|
+
function updateOrCreateLink(selector, attributes) {
|
|
1417
|
+
let element = document.querySelector(selector);
|
|
1418
|
+
if (!element) {
|
|
1419
|
+
element = document.createElement('link');
|
|
1420
|
+
document.head.appendChild(element);
|
|
1421
|
+
}
|
|
1422
|
+
Object.entries(attributes).forEach(([key, value]) => {
|
|
1423
|
+
element.setAttribute(key, value);
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
// ─── applyMetadataToDom ─────────────────────────────────────
|
|
1427
|
+
/**
|
|
1428
|
+
* Apply resolved metadata to the document `<head>`.
|
|
1429
|
+
* Client-only: this function does nothing if `document` is not available.
|
|
1430
|
+
* Covers: title, description, canonical, lang, keywords, author, viewport,
|
|
1431
|
+
* themeColor, Open Graph (advanced), Twitter Card, alternates/hreflang,
|
|
1432
|
+
* icons, manifest, structured data JSON-LD, AI hints, robots, customMeta.
|
|
1433
|
+
*/
|
|
1434
|
+
function applyMetadataToDom(resolved) {
|
|
1435
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1436
|
+
if (!isWeb) return;
|
|
1437
|
+
// ── Title ───────────────────────────────────────────────────
|
|
1438
|
+
if (resolved.title) {
|
|
1439
|
+
document.title = resolved.title;
|
|
1440
|
+
}
|
|
1441
|
+
// ── Standard meta tags ──────────────────────────────────────
|
|
1442
|
+
if (resolved.description) {
|
|
1443
|
+
updateOrCreateMeta('meta[name="description"]', resolved.description, {
|
|
1444
|
+
name: 'description'
|
|
1445
|
+
});
|
|
1446
|
+
}
|
|
1447
|
+
if ((_a = resolved.keywords) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1448
|
+
updateOrCreateMeta('meta[name="keywords"]', resolved.keywords.join(', '), {
|
|
1449
|
+
name: 'keywords'
|
|
1450
|
+
});
|
|
1451
|
+
}
|
|
1452
|
+
if (resolved.author) {
|
|
1453
|
+
updateOrCreateMeta('meta[name="author"]', resolved.author, {
|
|
1454
|
+
name: 'author'
|
|
1455
|
+
});
|
|
1456
|
+
}
|
|
1457
|
+
if (resolved.viewport) {
|
|
1458
|
+
updateOrCreateMeta('meta[name="viewport"]', resolved.viewport, {
|
|
1459
|
+
name: 'viewport'
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
if (resolved.themeColor) {
|
|
1463
|
+
updateOrCreateMeta('meta[name="theme-color"]', resolved.themeColor, {
|
|
1464
|
+
name: 'theme-color'
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
// ── Canonical ───────────────────────────────────────────────
|
|
1468
|
+
if (resolved.canonical) {
|
|
1469
|
+
updateOrCreateLink('link[rel="canonical"]', {
|
|
1470
|
+
rel: 'canonical',
|
|
1471
|
+
href: resolved.canonical
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
// ── Language ────────────────────────────────────────────────
|
|
1475
|
+
if (resolved.lang) {
|
|
1476
|
+
document.documentElement.lang = resolved.lang;
|
|
1477
|
+
}
|
|
1478
|
+
// ── Open Graph ──────────────────────────────────────────────
|
|
1479
|
+
if (resolved.openGraph) {
|
|
1480
|
+
const og = resolved.openGraph;
|
|
1481
|
+
if (og.title) {
|
|
1482
|
+
updateOrCreateMeta('meta[property="og:title"]', og.title, {
|
|
1483
|
+
property: 'og:title'
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
if (og.description) {
|
|
1487
|
+
updateOrCreateMeta('meta[property="og:description"]', og.description, {
|
|
1488
|
+
property: 'og:description'
|
|
1489
|
+
});
|
|
1490
|
+
}
|
|
1491
|
+
if (og.type) {
|
|
1492
|
+
updateOrCreateMeta('meta[property="og:type"]', og.type, {
|
|
1493
|
+
property: 'og:type'
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
if (og.url) {
|
|
1497
|
+
updateOrCreateMeta('meta[property="og:url"]', og.url, {
|
|
1498
|
+
property: 'og:url'
|
|
1499
|
+
});
|
|
1500
|
+
}
|
|
1501
|
+
if (og.siteName) {
|
|
1502
|
+
updateOrCreateMeta('meta[property="og:site_name"]', og.siteName, {
|
|
1503
|
+
property: 'og:site_name'
|
|
1504
|
+
});
|
|
1505
|
+
}
|
|
1506
|
+
if (og.locale) {
|
|
1507
|
+
updateOrCreateMeta('meta[property="og:locale"]', og.locale, {
|
|
1508
|
+
property: 'og:locale'
|
|
1509
|
+
});
|
|
1510
|
+
}
|
|
1511
|
+
// OG images (advanced: multiple + alt/width/height)
|
|
1512
|
+
if ((_b = og.images) === null || _b === void 0 ? void 0 : _b.length) {
|
|
1513
|
+
applyOgImages(og.images);
|
|
1514
|
+
} else if (og.image) {
|
|
1515
|
+
const img = typeof og.image === 'string' ? {
|
|
1516
|
+
url: og.image
|
|
1517
|
+
} : og.image;
|
|
1518
|
+
applyOgImages([img]);
|
|
1519
|
+
}
|
|
1520
|
+
// OG article metadata
|
|
1521
|
+
if (og.article) {
|
|
1522
|
+
const art = og.article;
|
|
1523
|
+
if (art.publishedTime) {
|
|
1524
|
+
updateOrCreateMeta('meta[property="article:published_time"]', art.publishedTime, {
|
|
1525
|
+
property: 'article:published_time'
|
|
1526
|
+
});
|
|
1527
|
+
}
|
|
1528
|
+
if (art.modifiedTime) {
|
|
1529
|
+
updateOrCreateMeta('meta[property="article:modified_time"]', art.modifiedTime, {
|
|
1530
|
+
property: 'article:modified_time'
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
if (art.expirationTime) {
|
|
1534
|
+
updateOrCreateMeta('meta[property="article:expiration_time"]', art.expirationTime, {
|
|
1535
|
+
property: 'article:expiration_time'
|
|
1536
|
+
});
|
|
1537
|
+
}
|
|
1538
|
+
if (art.section) {
|
|
1539
|
+
updateOrCreateMeta('meta[property="article:section"]', art.section, {
|
|
1540
|
+
property: 'article:section'
|
|
1541
|
+
});
|
|
1542
|
+
}
|
|
1543
|
+
const authors = Array.isArray(art.author) ? art.author : art.author ? [art.author] : [];
|
|
1544
|
+
authors.forEach((author, i) => {
|
|
1545
|
+
updateOrCreateMeta(`meta[property="article:author"][data-index="${i}"]`, author, {
|
|
1546
|
+
property: 'article:author',
|
|
1547
|
+
'data-index': String(i)
|
|
1548
|
+
});
|
|
1549
|
+
});
|
|
1550
|
+
(_c = art.tags) === null || _c === void 0 ? void 0 : _c.forEach((tag, i) => {
|
|
1551
|
+
updateOrCreateMeta(`meta[property="article:tag"][data-index="${i}"]`, tag, {
|
|
1552
|
+
property: 'article:tag',
|
|
1553
|
+
'data-index': String(i)
|
|
1554
|
+
});
|
|
1555
|
+
});
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
// ── Twitter Card ────────────────────────────────────────────
|
|
1559
|
+
if (resolved.twitter) {
|
|
1560
|
+
const tw = resolved.twitter;
|
|
1561
|
+
if (tw.card) {
|
|
1562
|
+
updateOrCreateMeta('meta[name="twitter:card"]', tw.card, {
|
|
1563
|
+
name: 'twitter:card'
|
|
1564
|
+
});
|
|
1565
|
+
}
|
|
1566
|
+
if (tw.site) {
|
|
1567
|
+
updateOrCreateMeta('meta[name="twitter:site"]', tw.site, {
|
|
1568
|
+
name: 'twitter:site'
|
|
1569
|
+
});
|
|
1570
|
+
}
|
|
1571
|
+
if (tw.creator) {
|
|
1572
|
+
updateOrCreateMeta('meta[name="twitter:creator"]', tw.creator, {
|
|
1573
|
+
name: 'twitter:creator'
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
if (tw.title) {
|
|
1577
|
+
updateOrCreateMeta('meta[name="twitter:title"]', tw.title, {
|
|
1578
|
+
name: 'twitter:title'
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
if (tw.description) {
|
|
1582
|
+
updateOrCreateMeta('meta[name="twitter:description"]', tw.description, {
|
|
1583
|
+
name: 'twitter:description'
|
|
1584
|
+
});
|
|
1585
|
+
}
|
|
1586
|
+
if (tw.image) {
|
|
1587
|
+
updateOrCreateMeta('meta[name="twitter:image"]', tw.image, {
|
|
1588
|
+
name: 'twitter:image'
|
|
1589
|
+
});
|
|
1590
|
+
}
|
|
1591
|
+
if (tw.imageAlt) {
|
|
1592
|
+
updateOrCreateMeta('meta[name="twitter:image:alt"]', tw.imageAlt, {
|
|
1593
|
+
name: 'twitter:image:alt'
|
|
1594
|
+
});
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
// ── Alternates / hreflang ───────────────────────────────────
|
|
1598
|
+
if (resolved.alternates) {
|
|
1599
|
+
const alt = resolved.alternates;
|
|
1600
|
+
if (alt.canonical) {
|
|
1601
|
+
updateOrCreateLink('link[rel="canonical"]', {
|
|
1602
|
+
rel: 'canonical',
|
|
1603
|
+
href: alt.canonical
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
if (alt.languages) {
|
|
1607
|
+
// Remove old hreflang links first
|
|
1608
|
+
document.querySelectorAll('link[rel="alternate"][hreflang]').forEach(el => el.remove());
|
|
1609
|
+
Object.entries(alt.languages).forEach(([locale, url]) => {
|
|
1610
|
+
const link = document.createElement('link');
|
|
1611
|
+
link.rel = 'alternate';
|
|
1612
|
+
link.hreflang = locale;
|
|
1613
|
+
link.href = url;
|
|
1614
|
+
document.head.appendChild(link);
|
|
1615
|
+
});
|
|
1616
|
+
}
|
|
1617
|
+
if (alt.media) {
|
|
1618
|
+
Object.entries(alt.media).forEach(([mediaQuery, url]) => {
|
|
1619
|
+
updateOrCreateLink(`link[rel="alternate"][media="${mediaQuery}"]`, {
|
|
1620
|
+
rel: 'alternate',
|
|
1621
|
+
media: mediaQuery,
|
|
1622
|
+
href: url
|
|
1623
|
+
});
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
if (alt.types) {
|
|
1627
|
+
Object.entries(alt.types).forEach(([mimeType, items]) => {
|
|
1628
|
+
items.forEach((item, i) => {
|
|
1629
|
+
const selector = `link[rel="alternate"][type="${mimeType}"][data-index="${i}"]`;
|
|
1630
|
+
const attrs = {
|
|
1631
|
+
rel: 'alternate',
|
|
1632
|
+
type: mimeType,
|
|
1633
|
+
href: item.url,
|
|
1634
|
+
'data-index': String(i)
|
|
1635
|
+
};
|
|
1636
|
+
if (item.title) attrs.title = item.title;
|
|
1637
|
+
updateOrCreateLink(selector, attrs);
|
|
1638
|
+
});
|
|
1639
|
+
});
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
// ── Icons ───────────────────────────────────────────────────
|
|
1643
|
+
if (resolved.icons) {
|
|
1644
|
+
applyIcons(resolved.icons.icon, 'icon');
|
|
1645
|
+
applyIcons(resolved.icons.apple, 'apple-touch-icon');
|
|
1646
|
+
if (resolved.icons.shortcut) {
|
|
1647
|
+
updateOrCreateLink('link[rel="shortcut icon"]', {
|
|
1648
|
+
rel: 'shortcut icon',
|
|
1649
|
+
href: resolved.icons.shortcut
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
// ── Manifest ────────────────────────────────────────────────
|
|
1654
|
+
if (resolved.manifest) {
|
|
1655
|
+
updateOrCreateLink('link[rel="manifest"]', {
|
|
1656
|
+
rel: 'manifest',
|
|
1657
|
+
href: resolved.manifest
|
|
1658
|
+
});
|
|
1659
|
+
}
|
|
1660
|
+
// ── Structured data JSON-LD ─────────────────────────────────
|
|
1661
|
+
if (resolved.structuredData) {
|
|
1662
|
+
const schemaScriptId = 'react-pages-schema-org';
|
|
1663
|
+
let scriptElement = document.querySelector(`script[id="${schemaScriptId}"]`);
|
|
1664
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
1665
|
+
if (!scriptElement) {
|
|
1666
|
+
scriptElement = document.createElement('script');
|
|
1667
|
+
scriptElement.type = 'application/ld+json';
|
|
1668
|
+
scriptElement.id = schemaScriptId;
|
|
1669
|
+
document.head.appendChild(scriptElement);
|
|
1670
|
+
}
|
|
1671
|
+
scriptElement.textContent = JSON.stringify(Object.assign({
|
|
1672
|
+
'@context': 'https://schema.org',
|
|
1673
|
+
'@type': resolved.structuredData.type
|
|
1674
|
+
}, resolved.structuredData.schema));
|
|
1675
|
+
}
|
|
1676
|
+
// ── AI crawler hints ────────────────────────────────────────
|
|
1677
|
+
if (resolved.aiHints) {
|
|
1678
|
+
const hints = resolved.aiHints;
|
|
1679
|
+
if (hints.contentClassification) {
|
|
1680
|
+
updateOrCreateMeta('meta[name="ai-content-classification"]', hints.contentClassification, {
|
|
1681
|
+
name: 'ai-content-classification'
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
if ((_d = hints.modelHints) === null || _d === void 0 ? void 0 : _d.length) {
|
|
1685
|
+
updateOrCreateMeta('meta[name="ai-model-hints"]', hints.modelHints.join(', '), {
|
|
1686
|
+
name: 'ai-model-hints'
|
|
1687
|
+
});
|
|
1688
|
+
}
|
|
1689
|
+
if (hints.contextualInfo) {
|
|
1690
|
+
updateOrCreateMeta('meta[name="ai-context"]', hints.contextualInfo, {
|
|
1691
|
+
name: 'ai-context'
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
if (hints.excludeFromIndexing) {
|
|
1695
|
+
updateOrCreateMeta('meta[name="ai-exclude-from-indexing"]', 'true', {
|
|
1696
|
+
name: 'ai-exclude-from-indexing'
|
|
1697
|
+
});
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
// ── Robots ──────────────────────────────────────────────────
|
|
1701
|
+
if (resolved.robots || resolved.disableIndexing) {
|
|
1702
|
+
const robots = (_e = resolved.robots) !== null && _e !== void 0 ? _e : {};
|
|
1703
|
+
const noindex = resolved.disableIndexing || robots.noindex;
|
|
1704
|
+
const nofollow = resolved.disableIndexing || robots.nofollow;
|
|
1705
|
+
const robotsValue = [noindex ? 'noindex' : 'index', nofollow ? 'nofollow' : 'follow', robots.noarchive && 'noarchive', robots.nosnippet && 'nosnippet', robots.maxImagePreview && `max-image-preview:${robots.maxImagePreview}`, robots.maxSnippet != null && `max-snippet:${robots.maxSnippet}`].filter(Boolean).join(', ');
|
|
1706
|
+
updateOrCreateMeta('meta[name="robots"]', robotsValue, {
|
|
1707
|
+
name: 'robots'
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
// ── Custom meta tags ────────────────────────────────────────
|
|
1711
|
+
if ((_f = resolved.customMeta) === null || _f === void 0 ? void 0 : _f.length) {
|
|
1712
|
+
resolved.customMeta.forEach(tag => {
|
|
1713
|
+
const selector = tag.id ? `meta[id="${tag.id}"]` : tag.name ? `meta[name="${tag.name}"]` : tag.property ? `meta[property="${tag.property}"]` : `meta[http-equiv="${tag.httpEquiv}"]`;
|
|
1714
|
+
const attributes = tag.name ? {
|
|
1715
|
+
name: tag.name
|
|
1716
|
+
} : tag.property ? {
|
|
1717
|
+
property: tag.property
|
|
1718
|
+
} : tag.httpEquiv ? {
|
|
1719
|
+
'http-equiv': tag.httpEquiv
|
|
1720
|
+
} : {};
|
|
1721
|
+
if (tag.id) attributes.id = tag.id;
|
|
1722
|
+
updateOrCreateMeta(selector, tag.content, attributes);
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
}
|
|
1726
|
+
/** Apply OG images to the DOM (supports multiple images with alt/width/height) */
|
|
1727
|
+
function applyOgImages(images) {
|
|
1728
|
+
// Remove existing OG image tags to avoid stale data
|
|
1729
|
+
document.querySelectorAll('meta[property="og:image"], meta[property="og:image:alt"], meta[property="og:image:width"], meta[property="og:image:height"], meta[property="og:image:type"]').forEach(el => el.remove());
|
|
1730
|
+
images.forEach(img => {
|
|
1731
|
+
const ogImg = document.createElement('meta');
|
|
1732
|
+
ogImg.setAttribute('property', 'og:image');
|
|
1733
|
+
ogImg.setAttribute('content', img.url);
|
|
1734
|
+
document.head.appendChild(ogImg);
|
|
1735
|
+
if (img.alt) {
|
|
1736
|
+
const altMeta = document.createElement('meta');
|
|
1737
|
+
altMeta.setAttribute('property', 'og:image:alt');
|
|
1738
|
+
altMeta.setAttribute('content', img.alt);
|
|
1739
|
+
document.head.appendChild(altMeta);
|
|
1740
|
+
}
|
|
1741
|
+
if (img.width) {
|
|
1742
|
+
const wMeta = document.createElement('meta');
|
|
1743
|
+
wMeta.setAttribute('property', 'og:image:width');
|
|
1744
|
+
wMeta.setAttribute('content', String(img.width));
|
|
1745
|
+
document.head.appendChild(wMeta);
|
|
1746
|
+
}
|
|
1747
|
+
if (img.height) {
|
|
1748
|
+
const hMeta = document.createElement('meta');
|
|
1749
|
+
hMeta.setAttribute('property', 'og:image:height');
|
|
1750
|
+
hMeta.setAttribute('content', String(img.height));
|
|
1751
|
+
document.head.appendChild(hMeta);
|
|
1752
|
+
}
|
|
1753
|
+
if (img.type) {
|
|
1754
|
+
const tMeta = document.createElement('meta');
|
|
1755
|
+
tMeta.setAttribute('property', 'og:image:type');
|
|
1756
|
+
tMeta.setAttribute('content', img.type);
|
|
1757
|
+
document.head.appendChild(tMeta);
|
|
1758
|
+
}
|
|
1759
|
+
});
|
|
1760
|
+
}
|
|
1761
|
+
/** Apply icon link tags to the DOM */
|
|
1762
|
+
function applyIcons(icons, rel) {
|
|
1763
|
+
if (!icons) return;
|
|
1764
|
+
const iconList = typeof icons === 'string' ? [{
|
|
1765
|
+
url: icons
|
|
1766
|
+
}] : Array.isArray(icons) ? icons : [icons];
|
|
1767
|
+
// Remove old icons of this rel
|
|
1768
|
+
document.querySelectorAll(`link[rel="${rel}"]`).forEach(el => el.remove());
|
|
1769
|
+
iconList.forEach(icon => {
|
|
1770
|
+
const link = document.createElement('link');
|
|
1771
|
+
link.rel = rel;
|
|
1772
|
+
link.href = icon.url;
|
|
1773
|
+
if (icon.type) link.type = icon.type;
|
|
1774
|
+
if (icon.sizes) link.setAttribute('sizes', icon.sizes);
|
|
1775
|
+
if (icon.color) link.setAttribute('color', icon.color);
|
|
1776
|
+
document.head.appendChild(link);
|
|
1777
|
+
});
|
|
1778
|
+
}
|
|
1779
|
+
// ─── collectMetadataToHtml (SSR) ─────────────────────────────
|
|
1780
|
+
/**
|
|
1781
|
+
* Collect resolved metadata as an HTML string for SSR injection into `<head>`.
|
|
1782
|
+
* Pure function — no DOM, no side effects.
|
|
1783
|
+
*/
|
|
1784
|
+
function collectMetadataToHtml(resolved) {
|
|
1785
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1786
|
+
const tags = [];
|
|
1787
|
+
if (resolved.title) {
|
|
1788
|
+
tags.push(`<title>${escapeHtml(resolved.title)}</title>`);
|
|
1789
|
+
}
|
|
1790
|
+
if (resolved.description) {
|
|
1791
|
+
tags.push(`<meta name="description" content="${escapeAttr(resolved.description)}" />`);
|
|
1792
|
+
}
|
|
1793
|
+
if (resolved.canonical) {
|
|
1794
|
+
tags.push(`<link rel="canonical" href="${escapeAttr(resolved.canonical)}" />`);
|
|
1795
|
+
}
|
|
1796
|
+
if ((_a = resolved.keywords) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1797
|
+
tags.push(`<meta name="keywords" content="${escapeAttr(resolved.keywords.join(', '))}" />`);
|
|
1798
|
+
}
|
|
1799
|
+
if (resolved.author) {
|
|
1800
|
+
tags.push(`<meta name="author" content="${escapeAttr(resolved.author)}" />`);
|
|
1801
|
+
}
|
|
1802
|
+
if (resolved.viewport) {
|
|
1803
|
+
tags.push(`<meta name="viewport" content="${escapeAttr(resolved.viewport)}" />`);
|
|
1804
|
+
}
|
|
1805
|
+
if (resolved.themeColor) {
|
|
1806
|
+
tags.push(`<meta name="theme-color" content="${escapeAttr(resolved.themeColor)}" />`);
|
|
1807
|
+
}
|
|
1808
|
+
// Open Graph
|
|
1809
|
+
if (resolved.openGraph) {
|
|
1810
|
+
const og = resolved.openGraph;
|
|
1811
|
+
if (og.type) tags.push(ogMeta('og:type', og.type));
|
|
1812
|
+
if (og.title) tags.push(ogMeta('og:title', og.title));
|
|
1813
|
+
if (og.description) tags.push(ogMeta('og:description', og.description));
|
|
1814
|
+
if (og.url) tags.push(ogMeta('og:url', og.url));
|
|
1815
|
+
if (og.siteName) tags.push(ogMeta('og:site_name', og.siteName));
|
|
1816
|
+
if (og.locale) tags.push(ogMeta('og:locale', og.locale));
|
|
1817
|
+
const images = (_b = og.images) !== null && _b !== void 0 ? _b : og.image ? [typeof og.image === 'string' ? {
|
|
1818
|
+
url: og.image
|
|
1819
|
+
} : og.image] : [];
|
|
1820
|
+
images.forEach(img => {
|
|
1821
|
+
tags.push(ogMeta('og:image', img.url));
|
|
1822
|
+
if (img.alt) tags.push(ogMeta('og:image:alt', img.alt));
|
|
1823
|
+
if (img.width) tags.push(ogMeta('og:image:width', String(img.width)));
|
|
1824
|
+
if (img.height) tags.push(ogMeta('og:image:height', String(img.height)));
|
|
1825
|
+
if (img.type) tags.push(ogMeta('og:image:type', img.type));
|
|
1826
|
+
});
|
|
1827
|
+
if (og.article) {
|
|
1828
|
+
const art = og.article;
|
|
1829
|
+
if (art.publishedTime) tags.push(ogMeta('article:published_time', art.publishedTime));
|
|
1830
|
+
if (art.modifiedTime) tags.push(ogMeta('article:modified_time', art.modifiedTime));
|
|
1831
|
+
if (art.section) tags.push(ogMeta('article:section', art.section));
|
|
1832
|
+
const authors = Array.isArray(art.author) ? art.author : art.author ? [art.author] : [];
|
|
1833
|
+
authors.forEach(a => tags.push(ogMeta('article:author', a)));
|
|
1834
|
+
(_c = art.tags) === null || _c === void 0 ? void 0 : _c.forEach(t => tags.push(ogMeta('article:tag', t)));
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
// Twitter Card
|
|
1838
|
+
if (resolved.twitter) {
|
|
1839
|
+
const tw = resolved.twitter;
|
|
1840
|
+
if (tw.card) tags.push(nameMeta('twitter:card', tw.card));
|
|
1841
|
+
if (tw.site) tags.push(nameMeta('twitter:site', tw.site));
|
|
1842
|
+
if (tw.creator) tags.push(nameMeta('twitter:creator', tw.creator));
|
|
1843
|
+
if (tw.title) tags.push(nameMeta('twitter:title', tw.title));
|
|
1844
|
+
if (tw.description) tags.push(nameMeta('twitter:description', tw.description));
|
|
1845
|
+
if (tw.image) tags.push(nameMeta('twitter:image', tw.image));
|
|
1846
|
+
if (tw.imageAlt) tags.push(nameMeta('twitter:image:alt', tw.imageAlt));
|
|
1847
|
+
}
|
|
1848
|
+
// Alternates / hreflang
|
|
1849
|
+
if ((_d = resolved.alternates) === null || _d === void 0 ? void 0 : _d.languages) {
|
|
1850
|
+
Object.entries(resolved.alternates.languages).forEach(([locale, url]) => {
|
|
1851
|
+
tags.push(`<link rel="alternate" hreflang="${escapeAttr(locale)}" href="${escapeAttr(url)}" />`);
|
|
1852
|
+
});
|
|
1853
|
+
}
|
|
1854
|
+
// Icons
|
|
1855
|
+
if (resolved.icons) {
|
|
1856
|
+
collectIconTags(resolved.icons.icon, 'icon', tags);
|
|
1857
|
+
collectIconTags(resolved.icons.apple, 'apple-touch-icon', tags);
|
|
1858
|
+
if (resolved.icons.shortcut) {
|
|
1859
|
+
tags.push(`<link rel="shortcut icon" href="${escapeAttr(resolved.icons.shortcut)}" />`);
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
// Manifest
|
|
1863
|
+
if (resolved.manifest) {
|
|
1864
|
+
tags.push(`<link rel="manifest" href="${escapeAttr(resolved.manifest)}" />`);
|
|
1865
|
+
}
|
|
1866
|
+
// Structured data JSON-LD
|
|
1867
|
+
if (resolved.structuredData) {
|
|
1868
|
+
const jsonLd = JSON.stringify(Object.assign({
|
|
1869
|
+
'@context': 'https://schema.org',
|
|
1870
|
+
'@type': resolved.structuredData.type
|
|
1871
|
+
}, resolved.structuredData.schema));
|
|
1872
|
+
tags.push(`<script type="application/ld+json">${jsonLd}</script>`);
|
|
1873
|
+
}
|
|
1874
|
+
// Robots
|
|
1875
|
+
if (resolved.robots || resolved.disableIndexing) {
|
|
1876
|
+
const robots = (_e = resolved.robots) !== null && _e !== void 0 ? _e : {};
|
|
1877
|
+
const noindex = resolved.disableIndexing || robots.noindex;
|
|
1878
|
+
const nofollow = resolved.disableIndexing || robots.nofollow;
|
|
1879
|
+
const robotsValue = [noindex ? 'noindex' : 'index', nofollow ? 'nofollow' : 'follow', robots.noarchive && 'noarchive', robots.nosnippet && 'nosnippet', robots.maxImagePreview && `max-image-preview:${robots.maxImagePreview}`, robots.maxSnippet != null && `max-snippet:${robots.maxSnippet}`].filter(Boolean).join(', ');
|
|
1880
|
+
tags.push(`<meta name="robots" content="${escapeAttr(robotsValue)}" />`);
|
|
1881
|
+
}
|
|
1882
|
+
// Custom meta tags
|
|
1883
|
+
(_f = resolved.customMeta) === null || _f === void 0 ? void 0 : _f.forEach(tag => {
|
|
1884
|
+
if (tag.property) {
|
|
1885
|
+
tags.push(ogMeta(tag.property, tag.content));
|
|
1886
|
+
} else if (tag.name) {
|
|
1887
|
+
tags.push(nameMeta(tag.name, tag.content));
|
|
1888
|
+
} else if (tag.httpEquiv) {
|
|
1889
|
+
tags.push(`<meta http-equiv="${escapeAttr(tag.httpEquiv)}" content="${escapeAttr(tag.content)}" />`);
|
|
1890
|
+
}
|
|
1891
|
+
});
|
|
1892
|
+
return tags.join('\n');
|
|
1893
|
+
}
|
|
1894
|
+
function collectIconTags(icons, rel, tags) {
|
|
1895
|
+
if (!icons) return;
|
|
1896
|
+
const iconList = typeof icons === 'string' ? [{
|
|
1897
|
+
url: icons
|
|
1898
|
+
}] : Array.isArray(icons) ? icons : [icons];
|
|
1899
|
+
iconList.forEach(icon => {
|
|
1900
|
+
let tag = `<link rel="${rel}" href="${escapeAttr(icon.url)}"`;
|
|
1901
|
+
if (icon.type) tag += ` type="${escapeAttr(icon.type)}"`;
|
|
1902
|
+
if (icon.sizes) tag += ` sizes="${escapeAttr(icon.sizes)}"`;
|
|
1903
|
+
if (icon.color) tag += ` color="${escapeAttr(icon.color)}"`;
|
|
1904
|
+
tag += ' />';
|
|
1905
|
+
tags.push(tag);
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
// ─── HTML helpers ────────────────────────────────────────────
|
|
1909
|
+
function escapeHtml(str) {
|
|
1910
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
1911
|
+
}
|
|
1912
|
+
function escapeAttr(str) {
|
|
1913
|
+
return str.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<').replace(/>/g, '>');
|
|
1914
|
+
}
|
|
1915
|
+
function ogMeta(property, content) {
|
|
1916
|
+
return `<meta property="${escapeAttr(property)}" content="${escapeAttr(content)}" />`;
|
|
1917
|
+
}
|
|
1918
|
+
function nameMeta(name, content) {
|
|
1919
|
+
return `<meta name="${escapeAttr(name)}" content="${escapeAttr(content)}" />`;
|
|
1920
|
+
}
|
|
1921
|
+
// ─── Backward-compatible global API ──────────────────────────
|
|
1922
|
+
// These wrap the global store + applyMetadataToDom for existing consumers.
|
|
1923
|
+
/**
|
|
1924
|
+
* Apply metadata configuration to the page.
|
|
1925
|
+
* Merges with existing metadata in the global store.
|
|
1926
|
+
* On web: also applies changes to the DOM.
|
|
1927
|
+
*
|
|
1928
|
+
* @deprecated Prefer using `MetadataStoreProvider` + `resolveMetadata` + `applyMetadataToDom`
|
|
1929
|
+
* for SSR-safe, request-scoped metadata management.
|
|
1930
|
+
*/
|
|
1931
|
+
const setMetadata = config => {
|
|
1932
|
+
// For backward compat, treat the config as already resolved (strings only).
|
|
1933
|
+
// Evaluator functions should have been resolved by useMetadata before calling this.
|
|
1934
|
+
const resolved = config;
|
|
1935
|
+
globalStore.setMetadata(resolved);
|
|
1936
|
+
if (isWeb) {
|
|
1937
|
+
applyMetadataToDom(resolved);
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
/**
|
|
1941
|
+
* Get current metadata from the global store.
|
|
1942
|
+
* @deprecated Prefer using `MetadataStoreProvider` context in SSR.
|
|
1943
|
+
*/
|
|
1944
|
+
const getMetadata = () => {
|
|
1945
|
+
return globalStore.getMetadata();
|
|
1946
|
+
};
|
|
1947
|
+
/**
|
|
1948
|
+
* Reset all metadata in the global store.
|
|
1949
|
+
* @deprecated Prefer using `MetadataStoreProvider` context in SSR.
|
|
1950
|
+
*/
|
|
1951
|
+
const resetMetadata = () => {
|
|
1952
|
+
globalStore.reset();
|
|
1953
|
+
};/**
|
|
1954
|
+
* resolveMetadata — Pure function that evaluates dynamic MetadataConfig into ResolvedMetadata.
|
|
1955
|
+
*
|
|
1956
|
+
* All evaluator functions (title, description, og fields, twitter fields, etc.)
|
|
1957
|
+
* are called with the provided context. The result is a plain object with no functions.
|
|
1958
|
+
*
|
|
1959
|
+
* This function has NO side effects: no DOM, no global state.
|
|
1960
|
+
*
|
|
1961
|
+
* @module config/resolveMetadata
|
|
1962
|
+
*/
|
|
1963
|
+
/**
|
|
1964
|
+
* Safely evaluate a value that may be a function or a plain value.
|
|
1965
|
+
*/
|
|
1966
|
+
function evaluate(value, ctx) {
|
|
1967
|
+
if (value === undefined || value === null) return undefined;
|
|
1968
|
+
if (typeof value === 'function') {
|
|
1969
|
+
return value(ctx);
|
|
1970
|
+
}
|
|
1971
|
+
return value;
|
|
1972
|
+
}
|
|
1973
|
+
/**
|
|
1974
|
+
* Resolve a MetadataConfig (which may contain evaluator functions)
|
|
1975
|
+
* into a plain ResolvedMetadata object.
|
|
1976
|
+
*
|
|
1977
|
+
* @param meta - The metadata configuration (static or with dynamic functions)
|
|
1978
|
+
* @param ctx - The context providing get/set accessors for queries, form, state
|
|
1979
|
+
* @returns Fully resolved metadata with all functions evaluated
|
|
1980
|
+
*/
|
|
1981
|
+
function resolveMetadata(meta, ctx) {
|
|
1982
|
+
var _a;
|
|
1983
|
+
const resolved = {};
|
|
1984
|
+
// ── Basic fields ────────────────────────────────────────────
|
|
1985
|
+
resolved.title = evaluate(meta.title, ctx);
|
|
1986
|
+
resolved.description = evaluate(meta.description, ctx);
|
|
1987
|
+
resolved.canonical = evaluate(meta.canonical, ctx);
|
|
1988
|
+
// Unify lang / documentLang: prefer `lang`, fall back to deprecated `documentLang`
|
|
1989
|
+
resolved.lang = (_a = meta.lang) !== null && _a !== void 0 ? _a : meta.documentLang;
|
|
1990
|
+
resolved.keywords = evaluate(meta.keywords, ctx);
|
|
1991
|
+
resolved.author = meta.author;
|
|
1992
|
+
resolved.viewport = meta.viewport;
|
|
1993
|
+
resolved.themeColor = meta.themeColor;
|
|
1994
|
+
resolved.disableIndexing = meta.disableIndexing;
|
|
1995
|
+
// ── Open Graph ──────────────────────────────────────────────
|
|
1996
|
+
if (meta.openGraph) {
|
|
1997
|
+
const og = meta.openGraph;
|
|
1998
|
+
const resolvedImage = evaluate(og.image, ctx);
|
|
1999
|
+
const resolvedImages = evaluate(og.images, ctx);
|
|
2000
|
+
resolved.openGraph = {
|
|
2001
|
+
type: og.type,
|
|
2002
|
+
title: evaluate(og.title, ctx),
|
|
2003
|
+
description: evaluate(og.description, ctx),
|
|
2004
|
+
image: resolvedImage,
|
|
2005
|
+
images: resolvedImages,
|
|
2006
|
+
url: evaluate(og.url, ctx),
|
|
2007
|
+
siteName: og.siteName,
|
|
2008
|
+
locale: og.locale,
|
|
2009
|
+
article: og.article
|
|
2010
|
+
};
|
|
2011
|
+
// Normalize: if single image string, also put it in images array
|
|
2012
|
+
if (resolvedImage && !resolvedImages) {
|
|
2013
|
+
const imgObj = typeof resolvedImage === 'string' ? {
|
|
2014
|
+
url: resolvedImage
|
|
2015
|
+
} : resolvedImage;
|
|
2016
|
+
resolved.openGraph.images = [imgObj];
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2019
|
+
// ── Twitter Card ────────────────────────────────────────────
|
|
2020
|
+
if (meta.twitter) {
|
|
2021
|
+
const tw = meta.twitter;
|
|
2022
|
+
resolved.twitter = {
|
|
2023
|
+
card: tw.card,
|
|
2024
|
+
site: tw.site,
|
|
2025
|
+
creator: tw.creator,
|
|
2026
|
+
title: evaluate(tw.title, ctx),
|
|
2027
|
+
description: evaluate(tw.description, ctx),
|
|
2028
|
+
image: evaluate(tw.image, ctx),
|
|
2029
|
+
imageAlt: evaluate(tw.imageAlt, ctx)
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
// ── Alternates / hreflang ───────────────────────────────────
|
|
2033
|
+
if (meta.alternates) {
|
|
2034
|
+
resolved.alternates = Object.assign({}, meta.alternates);
|
|
2035
|
+
}
|
|
2036
|
+
// ── Icons / PWA ─────────────────────────────────────────────
|
|
2037
|
+
if (meta.icons) {
|
|
2038
|
+
resolved.icons = Object.assign({}, meta.icons);
|
|
2039
|
+
}
|
|
2040
|
+
if (meta.manifest) {
|
|
2041
|
+
resolved.manifest = meta.manifest;
|
|
2042
|
+
}
|
|
2043
|
+
// ── Structured Data ─────────────────────────────────────────
|
|
2044
|
+
if (meta.structuredData) {
|
|
2045
|
+
const sd = meta.structuredData;
|
|
2046
|
+
resolved.structuredData = {
|
|
2047
|
+
type: sd.type,
|
|
2048
|
+
schema: typeof sd.schema === 'function' ? sd.schema(ctx) : sd.schema
|
|
2049
|
+
};
|
|
2050
|
+
}
|
|
2051
|
+
// ── AI Hints ────────────────────────────────────────────────
|
|
2052
|
+
if (meta.aiHints) {
|
|
2053
|
+
const hints = meta.aiHints;
|
|
2054
|
+
resolved.aiHints = {
|
|
2055
|
+
contentClassification: evaluate(hints.contentClassification, ctx),
|
|
2056
|
+
modelHints: evaluate(hints.modelHints, ctx),
|
|
2057
|
+
contextualInfo: evaluate(hints.contextualInfo, ctx),
|
|
2058
|
+
excludeFromIndexing: hints.excludeFromIndexing
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
// ── Robots ──────────────────────────────────────────────────
|
|
2062
|
+
if (meta.robots) {
|
|
2063
|
+
resolved.robots = Object.assign({}, meta.robots);
|
|
2064
|
+
}
|
|
2065
|
+
// ── Custom Meta Tags ───────────────────────────────────────
|
|
2066
|
+
const customMeta = evaluate(meta.customMeta, ctx);
|
|
2067
|
+
if (customMeta) {
|
|
2068
|
+
resolved.customMeta = customMeta;
|
|
2069
|
+
}
|
|
2070
|
+
return resolved;
|
|
2071
|
+
}const MetadataStoreContext = React.createContext(null);
|
|
2072
|
+
/**
|
|
2073
|
+
* Provides a request-scoped MetadataStore via React Context.
|
|
2074
|
+
*
|
|
2075
|
+
* @example SSR (one per request)
|
|
2076
|
+
* ```tsx
|
|
2077
|
+
* import { createMetadataStore, MetadataStoreProvider } from '@/core/pages';
|
|
2078
|
+
*
|
|
2079
|
+
* function handleRequest(req, res) {
|
|
2080
|
+
* const store = createMetadataStore();
|
|
2081
|
+
* const html = renderToString(
|
|
2082
|
+
* <MetadataStoreProvider store={store}>
|
|
2083
|
+
* <App />
|
|
2084
|
+
* </MetadataStoreProvider>
|
|
2085
|
+
* );
|
|
2086
|
+
* const headHtml = collectMetadataToHtml(store.getMetadata());
|
|
2087
|
+
* // inject headHtml into <head>
|
|
2088
|
+
* }
|
|
2089
|
+
* ```
|
|
2090
|
+
*/
|
|
2091
|
+
function MetadataStoreProvider(t0) {
|
|
2092
|
+
const $ = compilerRuntime.c(5);
|
|
2093
|
+
const {
|
|
2094
|
+
store,
|
|
2095
|
+
children
|
|
2096
|
+
} = t0;
|
|
2097
|
+
let t1;
|
|
2098
|
+
if ($[0] !== store) {
|
|
2099
|
+
t1 = store !== null && store !== void 0 ? store : createMetadataStore();
|
|
2100
|
+
$[0] = store;
|
|
2101
|
+
$[1] = t1;
|
|
2102
|
+
} else {
|
|
2103
|
+
t1 = $[1];
|
|
2104
|
+
}
|
|
2105
|
+
const value = t1;
|
|
2106
|
+
let t2;
|
|
2107
|
+
if ($[2] !== children || $[3] !== value) {
|
|
2108
|
+
t2 = jsxRuntime.jsx(MetadataStoreContext.Provider, {
|
|
2109
|
+
value,
|
|
2110
|
+
children
|
|
2111
|
+
});
|
|
2112
|
+
$[2] = children;
|
|
2113
|
+
$[3] = value;
|
|
2114
|
+
$[4] = t2;
|
|
2115
|
+
} else {
|
|
2116
|
+
t2 = $[4];
|
|
2117
|
+
}
|
|
2118
|
+
return t2;
|
|
2119
|
+
}
|
|
2120
|
+
/**
|
|
2121
|
+
* Access the nearest request-scoped MetadataStore.
|
|
2122
|
+
* Returns `null` if no provider is found (falls back to global store in consumers).
|
|
2123
|
+
*/
|
|
2124
|
+
function useMetadataStore() {
|
|
2125
|
+
return React.useContext(MetadataStoreContext);
|
|
2126
|
+
}/**
|
|
2127
|
+
* Optional dev-only metadata logging.
|
|
2128
|
+
*
|
|
2129
|
+
* Tracks what metadata was resolved and applied, useful for debugging
|
|
2130
|
+
* metadata issues during development.
|
|
2131
|
+
*
|
|
2132
|
+
* Logging is a no-op in production builds.
|
|
2133
|
+
*
|
|
2134
|
+
* @module config/metadataLogger
|
|
2135
|
+
*/
|
|
2136
|
+
const isDev = process.env.NODE_ENV === 'development';
|
|
2137
|
+
let logEnabled = false;
|
|
2138
|
+
const logEntries = [];
|
|
2139
|
+
/**
|
|
2140
|
+
* Enable or disable metadata logging.
|
|
2141
|
+
* Only effective in development mode.
|
|
2142
|
+
*/
|
|
2143
|
+
function setMetadataLogging(enabled) {
|
|
2144
|
+
logEnabled = isDev && enabled;
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Log a metadata action (resolve, apply, translate).
|
|
2148
|
+
* No-op in production or when logging is disabled.
|
|
2149
|
+
*/
|
|
2150
|
+
function logMetadata(pageId, action, metadata) {
|
|
2151
|
+
if (!logEnabled) return;
|
|
2152
|
+
const entry = {
|
|
2153
|
+
pageId,
|
|
2154
|
+
action,
|
|
2155
|
+
metadata,
|
|
2156
|
+
timestamp: Date.now()
|
|
2157
|
+
};
|
|
2158
|
+
logEntries.push(entry);
|
|
2159
|
+
// Keep only last 50 entries to avoid memory leaks
|
|
2160
|
+
if (logEntries.length > 50) {
|
|
2161
|
+
logEntries.splice(0, logEntries.length - 50);
|
|
2162
|
+
}
|
|
2163
|
+
console.log(`[Metadata:${action}] page="${pageId}"`, metadata.title ? `title="${metadata.title}"` : '', metadata.description ? `desc="${metadata.description.slice(0, 60)}..."` : '');
|
|
2164
|
+
}
|
|
2165
|
+
/**
|
|
2166
|
+
* Get all logged metadata entries (dev only).
|
|
2167
|
+
* Useful for inspecting metadata in browser devtools.
|
|
2168
|
+
*/
|
|
2169
|
+
function getMetadataLog() {
|
|
2170
|
+
return [...logEntries];
|
|
2171
|
+
}
|
|
2172
|
+
/**
|
|
2173
|
+
* Clear the metadata log.
|
|
2174
|
+
*/
|
|
2175
|
+
function clearMetadataLog() {
|
|
2176
|
+
logEntries.length = 0;
|
|
2177
|
+
}const DefaultContainer = ({
|
|
2178
|
+
children
|
|
2179
|
+
}) => {
|
|
2180
|
+
return children;
|
|
2181
|
+
};
|
|
2182
|
+
// Lazy initialization to avoid side effects at module load time
|
|
2183
|
+
// This ensures tree-shaking works correctly by deferring singleton creation
|
|
2184
|
+
let _pageConfig = {
|
|
2185
|
+
HeaderContainer: DefaultContainer,
|
|
2186
|
+
FooterContainer: DefaultContainer,
|
|
2187
|
+
BodyContainer: DefaultContainer,
|
|
2188
|
+
authPageImage: '',
|
|
2189
|
+
authPageProps: {
|
|
2190
|
+
id: 'auth-page'
|
|
2191
|
+
},
|
|
2192
|
+
isLogged: val => !!(val === null || val === void 0 ? void 0 : val.id) && !!val.isLogged,
|
|
2193
|
+
ItemsContainer: ({
|
|
2194
|
+
children
|
|
2195
|
+
}) => children,
|
|
2196
|
+
PageContainer: ({
|
|
2197
|
+
children
|
|
2198
|
+
}) => children,
|
|
2199
|
+
meta: {
|
|
2200
|
+
title: '',
|
|
2201
|
+
description: ''
|
|
2202
|
+
},
|
|
2203
|
+
// Metadata configuration
|
|
2204
|
+
defaultMetadata: {},
|
|
2205
|
+
setMetadata,
|
|
2206
|
+
getMetadata,
|
|
2207
|
+
resetMetadata,
|
|
2208
|
+
// Lazy loading configuration
|
|
2209
|
+
lazyLoading: {
|
|
2210
|
+
enabled: true,
|
|
2211
|
+
preloadOnHover: false,
|
|
2212
|
+
preloadOnFocus: false,
|
|
2213
|
+
timeout: 30000,
|
|
2214
|
+
logMetrics: process.env.NODE_ENV === 'development'
|
|
2215
|
+
}
|
|
2216
|
+
};
|
|
2217
|
+
/**
|
|
2218
|
+
* Get or initialize the page configuration singleton
|
|
2219
|
+
* Uses lazy initialization to avoid module-level side effects for better tree-shaking
|
|
2220
|
+
*/
|
|
2221
|
+
function initializePageConfig() {
|
|
2222
|
+
_pageConfig = {
|
|
2223
|
+
HeaderContainer: DefaultContainer,
|
|
2224
|
+
FooterContainer: DefaultContainer,
|
|
2225
|
+
BodyContainer: DefaultContainer,
|
|
2226
|
+
authPageImage: '',
|
|
2227
|
+
authPageProps: {
|
|
2228
|
+
id: 'auth-page'
|
|
2229
|
+
},
|
|
2230
|
+
isLogged: val => !!(val === null || val === void 0 ? void 0 : val.id) && !!val.isLogged,
|
|
2231
|
+
ItemsContainer: ({
|
|
2232
|
+
children
|
|
2233
|
+
}) => children,
|
|
2234
|
+
PageContainer: ({
|
|
2235
|
+
children
|
|
2236
|
+
}) => children,
|
|
2237
|
+
meta: {
|
|
2238
|
+
title: '',
|
|
2239
|
+
description: ''
|
|
2240
|
+
},
|
|
2241
|
+
// Metadata configuration
|
|
2242
|
+
defaultMetadata: {},
|
|
2243
|
+
setMetadata,
|
|
2244
|
+
getMetadata,
|
|
2245
|
+
resetMetadata,
|
|
2246
|
+
// Lazy loading configuration
|
|
2247
|
+
lazyLoading: {
|
|
2248
|
+
enabled: true,
|
|
2249
|
+
preloadOnHover: false,
|
|
2250
|
+
preloadOnFocus: false,
|
|
2251
|
+
timeout: 30000,
|
|
2252
|
+
logMetrics: process.env.NODE_ENV === 'development'
|
|
2253
|
+
}
|
|
2254
|
+
};
|
|
2255
|
+
return _pageConfig;
|
|
2256
|
+
}
|
|
2257
|
+
// Getter for pageConfig - initializes on first access
|
|
2258
|
+
function getPageConfig() {
|
|
2259
|
+
return initializePageConfig();
|
|
2260
|
+
}
|
|
2261
|
+
const {
|
|
2262
|
+
atom: pageConfigAtom,
|
|
2263
|
+
useValue: usePageConfigValue,
|
|
2264
|
+
useState: usePageConfigState,
|
|
2265
|
+
useReset: usePageConfigReset
|
|
2266
|
+
} = reactState.atomStateGenerator({
|
|
2267
|
+
key: 'pageConfig',
|
|
2268
|
+
defaultValue: _pageConfig,
|
|
2269
|
+
persist: false
|
|
2270
|
+
});/**
|
|
2271
|
+
* Specialized hook for managing view settings
|
|
2272
|
+
* Optimized to prevent unnecessary re-renders
|
|
2273
|
+
* @param viewSettings - View settings configuration (static or function)
|
|
2274
|
+
* @param allQuery - All query results
|
|
2275
|
+
* @param allMutation - All mutation handlers
|
|
2276
|
+
* @param formValues - Current form values
|
|
2277
|
+
* @param setValue - Form setValue function
|
|
2278
|
+
* @returns Processed view settings
|
|
2279
|
+
*/
|
|
2280
|
+
function useViewSettings(t0) {
|
|
2281
|
+
const $ = compilerRuntime.c(2);
|
|
2282
|
+
const {
|
|
2283
|
+
viewSettings: t1,
|
|
2284
|
+
pageId
|
|
2285
|
+
} = t0;
|
|
2286
|
+
const viewSettings = t1 === undefined ? {} : t1;
|
|
2287
|
+
let t2;
|
|
2288
|
+
if ($[0] !== pageId) {
|
|
2289
|
+
t2 = {
|
|
2290
|
+
pageId
|
|
2291
|
+
};
|
|
2292
|
+
$[0] = pageId;
|
|
2293
|
+
$[1] = t2;
|
|
2294
|
+
} else {
|
|
2295
|
+
t2 = $[1];
|
|
2296
|
+
}
|
|
2297
|
+
const {
|
|
2298
|
+
get,
|
|
2299
|
+
set
|
|
2300
|
+
} = usePageValues(t2);
|
|
2301
|
+
if (typeof viewSettings === "function") {
|
|
2302
|
+
return viewSettings({
|
|
2303
|
+
get,
|
|
2304
|
+
set
|
|
2305
|
+
});
|
|
2306
|
+
} else {
|
|
2307
|
+
return viewSettings;
|
|
2308
|
+
}
|
|
2309
|
+
}/**
|
|
2310
|
+
* Specialized hook for managing form data processing
|
|
2311
|
+
* Uses useMemo to prevent unnecessary re-computation
|
|
2312
|
+
* @param form - Form configuration
|
|
2313
|
+
* @param isAllQueryMapped - Whether all queries are mapped
|
|
2314
|
+
* @param formValues - Current form values
|
|
2315
|
+
* @param extractMutationsHandle - Extracted mutations
|
|
2316
|
+
* @param extractQueryHandle - Extracted queries
|
|
2317
|
+
* @param setValue - Form setValue function
|
|
2318
|
+
* @returns Processed form data and submit handlers
|
|
2319
|
+
*/
|
|
2320
|
+
function useFormData({
|
|
2321
|
+
form,
|
|
2322
|
+
pageId
|
|
2323
|
+
}) {
|
|
2324
|
+
const {
|
|
2325
|
+
get,
|
|
2326
|
+
set
|
|
2327
|
+
} = usePageValues({
|
|
2328
|
+
pageId
|
|
2329
|
+
});
|
|
2330
|
+
const hiddenMapped = React.useCallback(() => {
|
|
2331
|
+
const isHidden = form === null || form === void 0 ? void 0 : form.hidden;
|
|
2332
|
+
if (!isHidden) return false;
|
|
2333
|
+
if (typeof isHidden === 'function') {
|
|
2334
|
+
return isHidden({
|
|
2335
|
+
get,
|
|
2336
|
+
set
|
|
2337
|
+
});
|
|
2338
|
+
} else {
|
|
2339
|
+
return !!isHidden;
|
|
2340
|
+
}
|
|
2341
|
+
}, [form === null || form === void 0 ? void 0 : form.hidden, get, set]);
|
|
2342
|
+
const mappedFormData = React.useMemo(() => {
|
|
2343
|
+
if (!(form === null || form === void 0 ? void 0 : form.data) || hiddenMapped()) return [];
|
|
2344
|
+
return form.data.map(el => {
|
|
2345
|
+
if (typeof el === 'function') {
|
|
2346
|
+
return el({
|
|
2347
|
+
get,
|
|
2348
|
+
set
|
|
2349
|
+
});
|
|
2350
|
+
}
|
|
2351
|
+
return el;
|
|
2352
|
+
})
|
|
2353
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
2354
|
+
.filter(el_0 => !!el_0).map((el_1, i) => {
|
|
2355
|
+
var _a;
|
|
2356
|
+
return Object.assign(Object.assign({}, el_1), {
|
|
2357
|
+
key: (_a = el_1.key) !== null && _a !== void 0 ? _a : `${i}`
|
|
2358
|
+
});
|
|
2359
|
+
});
|
|
2360
|
+
}, [form, get, hiddenMapped, set]);
|
|
2361
|
+
const formSubmit = React.useMemo(() => {
|
|
2362
|
+
if (!(form === null || form === void 0 ? void 0 : form.submit) || hiddenMapped()) return [];
|
|
2363
|
+
const submitFn = form.submit;
|
|
2364
|
+
return (typeof submitFn === 'function' ? submitFn({
|
|
2365
|
+
get,
|
|
2366
|
+
set
|
|
2367
|
+
}) : submitFn).map((el_2, i_0) => {
|
|
2368
|
+
var _a_0;
|
|
2369
|
+
return Object.assign(Object.assign({}, el_2), {
|
|
2370
|
+
key: (_a_0 = el_2.key) !== null && _a_0 !== void 0 ? _a_0 : `${i_0}`
|
|
2371
|
+
});
|
|
2372
|
+
});
|
|
2373
|
+
}, [form, hiddenMapped, get, set]);
|
|
2374
|
+
return {
|
|
2375
|
+
mappedFormData,
|
|
2376
|
+
formSubmit
|
|
2377
|
+
};
|
|
2378
|
+
}// src/subscribable.ts
|
|
2379
|
+
var Subscribable = class {
|
|
2380
|
+
constructor() {
|
|
2381
|
+
this.listeners = /* @__PURE__ */new Set();
|
|
2382
|
+
this.subscribe = this.subscribe.bind(this);
|
|
2383
|
+
}
|
|
2384
|
+
subscribe(listener) {
|
|
2385
|
+
this.listeners.add(listener);
|
|
2386
|
+
this.onSubscribe();
|
|
2387
|
+
return () => {
|
|
2388
|
+
this.listeners.delete(listener);
|
|
2389
|
+
this.onUnsubscribe();
|
|
2390
|
+
};
|
|
2391
|
+
}
|
|
2392
|
+
hasListeners() {
|
|
2393
|
+
return this.listeners.size > 0;
|
|
2394
|
+
}
|
|
2395
|
+
onSubscribe() {}
|
|
2396
|
+
onUnsubscribe() {}
|
|
2397
|
+
};// src/timeoutManager.ts
|
|
2398
|
+
var defaultTimeoutProvider = {
|
|
2399
|
+
// We need the wrapper function syntax below instead of direct references to
|
|
2400
|
+
// global setTimeout etc.
|
|
2401
|
+
//
|
|
2402
|
+
// BAD: `setTimeout: setTimeout`
|
|
2403
|
+
// GOOD: `setTimeout: (cb, delay) => setTimeout(cb, delay)`
|
|
2404
|
+
//
|
|
2405
|
+
// If we use direct references here, then anything that wants to spy on or
|
|
2406
|
+
// replace the global setTimeout (like tests) won't work since we'll already
|
|
2407
|
+
// have a hard reference to the original implementation at the time when this
|
|
2408
|
+
// file was imported.
|
|
2409
|
+
setTimeout: (callback, delay) => setTimeout(callback, delay),
|
|
2410
|
+
clearTimeout: timeoutId => clearTimeout(timeoutId),
|
|
2411
|
+
setInterval: (callback, delay) => setInterval(callback, delay),
|
|
2412
|
+
clearInterval: intervalId => clearInterval(intervalId)
|
|
2413
|
+
};
|
|
2414
|
+
var TimeoutManager = class {
|
|
2415
|
+
// We cannot have TimeoutManager<T> as we must instantiate it with a concrete
|
|
2416
|
+
// type at app boot; and if we leave that type, then any new timer provider
|
|
2417
|
+
// would need to support ReturnType<typeof setTimeout>, which is infeasible.
|
|
2418
|
+
//
|
|
2419
|
+
// We settle for type safety for the TimeoutProvider type, and accept that
|
|
2420
|
+
// this class is unsafe internally to allow for extension.
|
|
2421
|
+
#provider = defaultTimeoutProvider;
|
|
2422
|
+
#providerCalled = false;
|
|
2423
|
+
setTimeoutProvider(provider) {
|
|
2424
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2425
|
+
if (this.#providerCalled && provider !== this.#provider) {
|
|
2426
|
+
console.error(`[timeoutManager]: Switching provider after calls to previous provider might result in unexpected behavior.`, {
|
|
2427
|
+
previous: this.#provider,
|
|
2428
|
+
provider
|
|
2429
|
+
});
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
this.#provider = provider;
|
|
2433
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2434
|
+
this.#providerCalled = false;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
setTimeout(callback, delay) {
|
|
2438
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2439
|
+
this.#providerCalled = true;
|
|
2440
|
+
}
|
|
2441
|
+
return this.#provider.setTimeout(callback, delay);
|
|
2442
|
+
}
|
|
2443
|
+
clearTimeout(timeoutId) {
|
|
2444
|
+
this.#provider.clearTimeout(timeoutId);
|
|
2445
|
+
}
|
|
2446
|
+
setInterval(callback, delay) {
|
|
2447
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2448
|
+
this.#providerCalled = true;
|
|
2449
|
+
}
|
|
2450
|
+
return this.#provider.setInterval(callback, delay);
|
|
2451
|
+
}
|
|
2452
|
+
clearInterval(intervalId) {
|
|
2453
|
+
this.#provider.clearInterval(intervalId);
|
|
2454
|
+
}
|
|
2455
|
+
};
|
|
2456
|
+
var timeoutManager = new TimeoutManager();
|
|
2457
|
+
function systemSetTimeoutZero(callback) {
|
|
2458
|
+
setTimeout(callback, 0);
|
|
2459
|
+
}// src/utils.ts
|
|
2460
|
+
var isServer = typeof window === "undefined" || "Deno" in globalThis;
|
|
2461
|
+
function noop() {}
|
|
2462
|
+
function isValidTimeout(value) {
|
|
2463
|
+
return typeof value === "number" && value >= 0 && value !== Infinity;
|
|
2464
|
+
}
|
|
2465
|
+
function timeUntilStale(updatedAt, staleTime) {
|
|
2466
|
+
return Math.max(updatedAt + (staleTime || 0) - Date.now(), 0);
|
|
2467
|
+
}
|
|
2468
|
+
function resolveStaleTime(staleTime, query) {
|
|
2469
|
+
return typeof staleTime === "function" ? staleTime(query) : staleTime;
|
|
2470
|
+
}
|
|
2471
|
+
function resolveEnabled(enabled, query) {
|
|
2472
|
+
return typeof enabled === "function" ? enabled(query) : enabled;
|
|
2473
|
+
}
|
|
2474
|
+
var hasOwn = Object.prototype.hasOwnProperty;
|
|
2475
|
+
function replaceEqualDeep(a, b) {
|
|
2476
|
+
if (a === b) {
|
|
2477
|
+
return a;
|
|
2478
|
+
}
|
|
2479
|
+
const array = isPlainArray(a) && isPlainArray(b);
|
|
2480
|
+
if (!array && !(isPlainObject(a) && isPlainObject(b))) return b;
|
|
2481
|
+
const aItems = array ? a : Object.keys(a);
|
|
2482
|
+
const aSize = aItems.length;
|
|
2483
|
+
const bItems = array ? b : Object.keys(b);
|
|
2484
|
+
const bSize = bItems.length;
|
|
2485
|
+
const copy = array ? new Array(bSize) : {};
|
|
2486
|
+
let equalItems = 0;
|
|
2487
|
+
for (let i = 0; i < bSize; i++) {
|
|
2488
|
+
const key = array ? i : bItems[i];
|
|
2489
|
+
const aItem = a[key];
|
|
2490
|
+
const bItem = b[key];
|
|
2491
|
+
if (aItem === bItem) {
|
|
2492
|
+
copy[key] = aItem;
|
|
2493
|
+
if (array ? i < aSize : hasOwn.call(a, key)) equalItems++;
|
|
2494
|
+
continue;
|
|
2495
|
+
}
|
|
2496
|
+
if (aItem === null || bItem === null || typeof aItem !== "object" || typeof bItem !== "object") {
|
|
2497
|
+
copy[key] = bItem;
|
|
2498
|
+
continue;
|
|
2499
|
+
}
|
|
2500
|
+
const v = replaceEqualDeep(aItem, bItem);
|
|
2501
|
+
copy[key] = v;
|
|
2502
|
+
if (v === aItem) equalItems++;
|
|
2503
|
+
}
|
|
2504
|
+
return aSize === bSize && equalItems === aSize ? a : copy;
|
|
2505
|
+
}
|
|
2506
|
+
function shallowEqualObjects(a, b) {
|
|
2507
|
+
if (!b || Object.keys(a).length !== Object.keys(b).length) {
|
|
2508
|
+
return false;
|
|
2509
|
+
}
|
|
2510
|
+
for (const key in a) {
|
|
2511
|
+
if (a[key] !== b[key]) {
|
|
2512
|
+
return false;
|
|
2513
|
+
}
|
|
2514
|
+
}
|
|
2515
|
+
return true;
|
|
2516
|
+
}
|
|
2517
|
+
function isPlainArray(value) {
|
|
2518
|
+
return Array.isArray(value) && value.length === Object.keys(value).length;
|
|
2519
|
+
}
|
|
2520
|
+
function isPlainObject(o) {
|
|
2521
|
+
if (!hasObjectPrototype(o)) {
|
|
2522
|
+
return false;
|
|
2523
|
+
}
|
|
2524
|
+
const ctor = o.constructor;
|
|
2525
|
+
if (ctor === void 0) {
|
|
2526
|
+
return true;
|
|
2527
|
+
}
|
|
2528
|
+
const prot = ctor.prototype;
|
|
2529
|
+
if (!hasObjectPrototype(prot)) {
|
|
2530
|
+
return false;
|
|
2531
|
+
}
|
|
2532
|
+
if (!prot.hasOwnProperty("isPrototypeOf")) {
|
|
2533
|
+
return false;
|
|
2534
|
+
}
|
|
2535
|
+
if (Object.getPrototypeOf(o) !== Object.prototype) {
|
|
2536
|
+
return false;
|
|
2537
|
+
}
|
|
2538
|
+
return true;
|
|
2539
|
+
}
|
|
2540
|
+
function hasObjectPrototype(o) {
|
|
2541
|
+
return Object.prototype.toString.call(o) === "[object Object]";
|
|
2542
|
+
}
|
|
2543
|
+
function replaceData(prevData, data, options) {
|
|
2544
|
+
if (typeof options.structuralSharing === "function") {
|
|
2545
|
+
return options.structuralSharing(prevData, data);
|
|
2546
|
+
} else if (options.structuralSharing !== false) {
|
|
2547
|
+
if (process.env.NODE_ENV !== "production") {
|
|
2548
|
+
try {
|
|
2549
|
+
return replaceEqualDeep(prevData, data);
|
|
2550
|
+
} catch (error) {
|
|
2551
|
+
console.error(`Structural sharing requires data to be JSON serializable. To fix this, turn off structuralSharing or return JSON-serializable data from your queryFn. [${options.queryHash}]: ${error}`);
|
|
2552
|
+
throw error;
|
|
2553
|
+
}
|
|
2554
|
+
}
|
|
2555
|
+
return replaceEqualDeep(prevData, data);
|
|
2556
|
+
}
|
|
2557
|
+
return data;
|
|
2558
|
+
}// src/focusManager.ts
|
|
2559
|
+
var FocusManager = class extends Subscribable {
|
|
2560
|
+
#focused;
|
|
2561
|
+
#cleanup;
|
|
2562
|
+
#setup;
|
|
2563
|
+
constructor() {
|
|
2564
|
+
super();
|
|
2565
|
+
this.#setup = onFocus => {
|
|
2566
|
+
if (!isServer && window.addEventListener) {
|
|
2567
|
+
const listener = () => onFocus();
|
|
2568
|
+
window.addEventListener("visibilitychange", listener, false);
|
|
2569
|
+
return () => {
|
|
2570
|
+
window.removeEventListener("visibilitychange", listener);
|
|
2571
|
+
};
|
|
2572
|
+
}
|
|
2573
|
+
return;
|
|
2574
|
+
};
|
|
2575
|
+
}
|
|
2576
|
+
onSubscribe() {
|
|
2577
|
+
if (!this.#cleanup) {
|
|
2578
|
+
this.setEventListener(this.#setup);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
onUnsubscribe() {
|
|
2582
|
+
if (!this.hasListeners()) {
|
|
2583
|
+
this.#cleanup?.();
|
|
2584
|
+
this.#cleanup = void 0;
|
|
2585
|
+
}
|
|
2586
|
+
}
|
|
2587
|
+
setEventListener(setup) {
|
|
2588
|
+
this.#setup = setup;
|
|
2589
|
+
this.#cleanup?.();
|
|
2590
|
+
this.#cleanup = setup(focused => {
|
|
2591
|
+
if (typeof focused === "boolean") {
|
|
2592
|
+
this.setFocused(focused);
|
|
2593
|
+
} else {
|
|
2594
|
+
this.onFocus();
|
|
2595
|
+
}
|
|
2596
|
+
});
|
|
2597
|
+
}
|
|
2598
|
+
setFocused(focused) {
|
|
2599
|
+
const changed = this.#focused !== focused;
|
|
2600
|
+
if (changed) {
|
|
2601
|
+
this.#focused = focused;
|
|
2602
|
+
this.onFocus();
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
onFocus() {
|
|
2606
|
+
const isFocused = this.isFocused();
|
|
2607
|
+
this.listeners.forEach(listener => {
|
|
2608
|
+
listener(isFocused);
|
|
2609
|
+
});
|
|
2610
|
+
}
|
|
2611
|
+
isFocused() {
|
|
2612
|
+
if (typeof this.#focused === "boolean") {
|
|
2613
|
+
return this.#focused;
|
|
2614
|
+
}
|
|
2615
|
+
return globalThis.document?.visibilityState !== "hidden";
|
|
2616
|
+
}
|
|
2617
|
+
};
|
|
2618
|
+
var focusManager = new FocusManager();// src/thenable.ts
|
|
2619
|
+
function pendingThenable() {
|
|
2620
|
+
let resolve;
|
|
2621
|
+
let reject;
|
|
2622
|
+
const thenable = new Promise((_resolve, _reject) => {
|
|
2623
|
+
resolve = _resolve;
|
|
2624
|
+
reject = _reject;
|
|
2625
|
+
});
|
|
2626
|
+
thenable.status = "pending";
|
|
2627
|
+
thenable.catch(() => {});
|
|
2628
|
+
function finalize(data) {
|
|
2629
|
+
Object.assign(thenable, data);
|
|
2630
|
+
delete thenable.resolve;
|
|
2631
|
+
delete thenable.reject;
|
|
2632
|
+
}
|
|
2633
|
+
thenable.resolve = value => {
|
|
2634
|
+
finalize({
|
|
2635
|
+
status: "fulfilled",
|
|
2636
|
+
value
|
|
2637
|
+
});
|
|
2638
|
+
resolve(value);
|
|
2639
|
+
};
|
|
2640
|
+
thenable.reject = reason => {
|
|
2641
|
+
finalize({
|
|
2642
|
+
status: "rejected",
|
|
2643
|
+
reason
|
|
2644
|
+
});
|
|
2645
|
+
reject(reason);
|
|
2646
|
+
};
|
|
2647
|
+
return thenable;
|
|
2648
|
+
}// src/notifyManager.ts
|
|
2649
|
+
var defaultScheduler = systemSetTimeoutZero;
|
|
2650
|
+
function createNotifyManager() {
|
|
2651
|
+
let queue = [];
|
|
2652
|
+
let transactions = 0;
|
|
2653
|
+
let notifyFn = callback => {
|
|
2654
|
+
callback();
|
|
2655
|
+
};
|
|
2656
|
+
let batchNotifyFn = callback => {
|
|
2657
|
+
callback();
|
|
2658
|
+
};
|
|
2659
|
+
let scheduleFn = defaultScheduler;
|
|
2660
|
+
const schedule = callback => {
|
|
2661
|
+
if (transactions) {
|
|
2662
|
+
queue.push(callback);
|
|
2663
|
+
} else {
|
|
2664
|
+
scheduleFn(() => {
|
|
2665
|
+
notifyFn(callback);
|
|
2666
|
+
});
|
|
2667
|
+
}
|
|
2668
|
+
};
|
|
2669
|
+
const flush = () => {
|
|
2670
|
+
const originalQueue = queue;
|
|
2671
|
+
queue = [];
|
|
2672
|
+
if (originalQueue.length) {
|
|
2673
|
+
scheduleFn(() => {
|
|
2674
|
+
batchNotifyFn(() => {
|
|
2675
|
+
originalQueue.forEach(callback => {
|
|
2676
|
+
notifyFn(callback);
|
|
2677
|
+
});
|
|
2678
|
+
});
|
|
2679
|
+
});
|
|
2680
|
+
}
|
|
2681
|
+
};
|
|
2682
|
+
return {
|
|
2683
|
+
batch: callback => {
|
|
2684
|
+
let result;
|
|
2685
|
+
transactions++;
|
|
2686
|
+
try {
|
|
2687
|
+
result = callback();
|
|
2688
|
+
} finally {
|
|
2689
|
+
transactions--;
|
|
2690
|
+
if (!transactions) {
|
|
2691
|
+
flush();
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
return result;
|
|
2695
|
+
},
|
|
2696
|
+
/**
|
|
2697
|
+
* All calls to the wrapped function will be batched.
|
|
2698
|
+
*/
|
|
2699
|
+
batchCalls: callback => {
|
|
2700
|
+
return (...args) => {
|
|
2701
|
+
schedule(() => {
|
|
2702
|
+
callback(...args);
|
|
2703
|
+
});
|
|
2704
|
+
};
|
|
2705
|
+
},
|
|
2706
|
+
schedule,
|
|
2707
|
+
/**
|
|
2708
|
+
* Use this method to set a custom notify function.
|
|
2709
|
+
* This can be used to for example wrap notifications with `React.act` while running tests.
|
|
2710
|
+
*/
|
|
2711
|
+
setNotifyFunction: fn => {
|
|
2712
|
+
notifyFn = fn;
|
|
2713
|
+
},
|
|
2714
|
+
/**
|
|
2715
|
+
* Use this method to set a custom function to batch notifications together into a single tick.
|
|
2716
|
+
* By default React Query will use the batch function provided by ReactDOM or React Native.
|
|
2717
|
+
*/
|
|
2718
|
+
setBatchNotifyFunction: fn => {
|
|
2719
|
+
batchNotifyFn = fn;
|
|
2720
|
+
},
|
|
2721
|
+
setScheduler: fn => {
|
|
2722
|
+
scheduleFn = fn;
|
|
2723
|
+
}
|
|
2724
|
+
};
|
|
2725
|
+
}
|
|
2726
|
+
var notifyManager = createNotifyManager();// src/onlineManager.ts
|
|
2727
|
+
var OnlineManager = class extends Subscribable {
|
|
2728
|
+
#online = true;
|
|
2729
|
+
#cleanup;
|
|
2730
|
+
#setup;
|
|
2731
|
+
constructor() {
|
|
2732
|
+
super();
|
|
2733
|
+
this.#setup = onOnline => {
|
|
2734
|
+
if (!isServer && window.addEventListener) {
|
|
2735
|
+
const onlineListener = () => onOnline(true);
|
|
2736
|
+
const offlineListener = () => onOnline(false);
|
|
2737
|
+
window.addEventListener("online", onlineListener, false);
|
|
2738
|
+
window.addEventListener("offline", offlineListener, false);
|
|
2739
|
+
return () => {
|
|
2740
|
+
window.removeEventListener("online", onlineListener);
|
|
2741
|
+
window.removeEventListener("offline", offlineListener);
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
return;
|
|
2745
|
+
};
|
|
2746
|
+
}
|
|
2747
|
+
onSubscribe() {
|
|
2748
|
+
if (!this.#cleanup) {
|
|
2749
|
+
this.setEventListener(this.#setup);
|
|
2750
|
+
}
|
|
2751
|
+
}
|
|
2752
|
+
onUnsubscribe() {
|
|
2753
|
+
if (!this.hasListeners()) {
|
|
2754
|
+
this.#cleanup?.();
|
|
2755
|
+
this.#cleanup = void 0;
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
setEventListener(setup) {
|
|
2759
|
+
this.#setup = setup;
|
|
2760
|
+
this.#cleanup?.();
|
|
2761
|
+
this.#cleanup = setup(this.setOnline.bind(this));
|
|
2762
|
+
}
|
|
2763
|
+
setOnline(online) {
|
|
2764
|
+
const changed = this.#online !== online;
|
|
2765
|
+
if (changed) {
|
|
2766
|
+
this.#online = online;
|
|
2767
|
+
this.listeners.forEach(listener => {
|
|
2768
|
+
listener(online);
|
|
2769
|
+
});
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
isOnline() {
|
|
2773
|
+
return this.#online;
|
|
2774
|
+
}
|
|
2775
|
+
};
|
|
2776
|
+
var onlineManager = new OnlineManager();// src/retryer.ts
|
|
2777
|
+
function canFetch(networkMode) {
|
|
2778
|
+
return (networkMode ?? "online") === "online" ? onlineManager.isOnline() : true;
|
|
2779
|
+
}// src/query.ts
|
|
2780
|
+
function fetchState(data, options) {
|
|
2781
|
+
return {
|
|
2782
|
+
fetchFailureCount: 0,
|
|
2783
|
+
fetchFailureReason: null,
|
|
2784
|
+
fetchStatus: canFetch(options.networkMode) ? "fetching" : "paused",
|
|
2785
|
+
...(data === void 0 && {
|
|
2786
|
+
error: null,
|
|
2787
|
+
status: "pending"
|
|
2788
|
+
})
|
|
2789
|
+
};
|
|
2790
|
+
}// src/queryObserver.ts
|
|
2791
|
+
var QueryObserver = class extends Subscribable {
|
|
2792
|
+
constructor(client, options) {
|
|
2793
|
+
super();
|
|
2794
|
+
this.options = options;
|
|
2795
|
+
this.#client = client;
|
|
2796
|
+
this.#selectError = null;
|
|
2797
|
+
this.#currentThenable = pendingThenable();
|
|
2798
|
+
this.bindMethods();
|
|
2799
|
+
this.setOptions(options);
|
|
2800
|
+
}
|
|
2801
|
+
#client;
|
|
2802
|
+
#currentQuery = void 0;
|
|
2803
|
+
#currentQueryInitialState = void 0;
|
|
2804
|
+
#currentResult = void 0;
|
|
2805
|
+
#currentResultState;
|
|
2806
|
+
#currentResultOptions;
|
|
2807
|
+
#currentThenable;
|
|
2808
|
+
#selectError;
|
|
2809
|
+
#selectFn;
|
|
2810
|
+
#selectResult;
|
|
2811
|
+
// This property keeps track of the last query with defined data.
|
|
2812
|
+
// It will be used to pass the previous data and query to the placeholder function between renders.
|
|
2813
|
+
#lastQueryWithDefinedData;
|
|
2814
|
+
#staleTimeoutId;
|
|
2815
|
+
#refetchIntervalId;
|
|
2816
|
+
#currentRefetchInterval;
|
|
2817
|
+
#trackedProps = /* @__PURE__ */new Set();
|
|
2818
|
+
bindMethods() {
|
|
2819
|
+
this.refetch = this.refetch.bind(this);
|
|
2820
|
+
}
|
|
2821
|
+
onSubscribe() {
|
|
2822
|
+
if (this.listeners.size === 1) {
|
|
2823
|
+
this.#currentQuery.addObserver(this);
|
|
2824
|
+
if (shouldFetchOnMount(this.#currentQuery, this.options)) {
|
|
2825
|
+
this.#executeFetch();
|
|
2826
|
+
} else {
|
|
2827
|
+
this.updateResult();
|
|
2828
|
+
}
|
|
2829
|
+
this.#updateTimers();
|
|
2830
|
+
}
|
|
2831
|
+
}
|
|
2832
|
+
onUnsubscribe() {
|
|
2833
|
+
if (!this.hasListeners()) {
|
|
2834
|
+
this.destroy();
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
shouldFetchOnReconnect() {
|
|
2838
|
+
return shouldFetchOn(this.#currentQuery, this.options, this.options.refetchOnReconnect);
|
|
2839
|
+
}
|
|
2840
|
+
shouldFetchOnWindowFocus() {
|
|
2841
|
+
return shouldFetchOn(this.#currentQuery, this.options, this.options.refetchOnWindowFocus);
|
|
2842
|
+
}
|
|
2843
|
+
destroy() {
|
|
2844
|
+
this.listeners = /* @__PURE__ */new Set();
|
|
2845
|
+
this.#clearStaleTimeout();
|
|
2846
|
+
this.#clearRefetchInterval();
|
|
2847
|
+
this.#currentQuery.removeObserver(this);
|
|
2848
|
+
}
|
|
2849
|
+
setOptions(options) {
|
|
2850
|
+
const prevOptions = this.options;
|
|
2851
|
+
const prevQuery = this.#currentQuery;
|
|
2852
|
+
this.options = this.#client.defaultQueryOptions(options);
|
|
2853
|
+
if (this.options.enabled !== void 0 && typeof this.options.enabled !== "boolean" && typeof this.options.enabled !== "function" && typeof resolveEnabled(this.options.enabled, this.#currentQuery) !== "boolean") {
|
|
2854
|
+
throw new Error("Expected enabled to be a boolean or a callback that returns a boolean");
|
|
2855
|
+
}
|
|
2856
|
+
this.#updateQuery();
|
|
2857
|
+
this.#currentQuery.setOptions(this.options);
|
|
2858
|
+
if (prevOptions._defaulted && !shallowEqualObjects(this.options, prevOptions)) {
|
|
2859
|
+
this.#client.getQueryCache().notify({
|
|
2860
|
+
type: "observerOptionsUpdated",
|
|
2861
|
+
query: this.#currentQuery,
|
|
2862
|
+
observer: this
|
|
2863
|
+
});
|
|
2864
|
+
}
|
|
2865
|
+
const mounted = this.hasListeners();
|
|
2866
|
+
if (mounted && shouldFetchOptionally(this.#currentQuery, prevQuery, this.options, prevOptions)) {
|
|
2867
|
+
this.#executeFetch();
|
|
2868
|
+
}
|
|
2869
|
+
this.updateResult();
|
|
2870
|
+
if (mounted && (this.#currentQuery !== prevQuery || resolveEnabled(this.options.enabled, this.#currentQuery) !== resolveEnabled(prevOptions.enabled, this.#currentQuery) || resolveStaleTime(this.options.staleTime, this.#currentQuery) !== resolveStaleTime(prevOptions.staleTime, this.#currentQuery))) {
|
|
2871
|
+
this.#updateStaleTimeout();
|
|
2872
|
+
}
|
|
2873
|
+
const nextRefetchInterval = this.#computeRefetchInterval();
|
|
2874
|
+
if (mounted && (this.#currentQuery !== prevQuery || resolveEnabled(this.options.enabled, this.#currentQuery) !== resolveEnabled(prevOptions.enabled, this.#currentQuery) || nextRefetchInterval !== this.#currentRefetchInterval)) {
|
|
2875
|
+
this.#updateRefetchInterval(nextRefetchInterval);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
getOptimisticResult(options) {
|
|
2879
|
+
const query = this.#client.getQueryCache().build(this.#client, options);
|
|
2880
|
+
const result = this.createResult(query, options);
|
|
2881
|
+
if (shouldAssignObserverCurrentProperties(this, result)) {
|
|
2882
|
+
this.#currentResult = result;
|
|
2883
|
+
this.#currentResultOptions = this.options;
|
|
2884
|
+
this.#currentResultState = this.#currentQuery.state;
|
|
2885
|
+
}
|
|
2886
|
+
return result;
|
|
2887
|
+
}
|
|
2888
|
+
getCurrentResult() {
|
|
2889
|
+
return this.#currentResult;
|
|
2890
|
+
}
|
|
2891
|
+
trackResult(result, onPropTracked) {
|
|
2892
|
+
return new Proxy(result, {
|
|
2893
|
+
get: (target, key) => {
|
|
2894
|
+
this.trackProp(key);
|
|
2895
|
+
onPropTracked?.(key);
|
|
2896
|
+
if (key === "promise") {
|
|
2897
|
+
this.trackProp("data");
|
|
2898
|
+
if (!this.options.experimental_prefetchInRender && this.#currentThenable.status === "pending") {
|
|
2899
|
+
this.#currentThenable.reject(new Error("experimental_prefetchInRender feature flag is not enabled"));
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
return Reflect.get(target, key);
|
|
2903
|
+
}
|
|
2904
|
+
});
|
|
2905
|
+
}
|
|
2906
|
+
trackProp(key) {
|
|
2907
|
+
this.#trackedProps.add(key);
|
|
2908
|
+
}
|
|
2909
|
+
getCurrentQuery() {
|
|
2910
|
+
return this.#currentQuery;
|
|
2911
|
+
}
|
|
2912
|
+
refetch({
|
|
2913
|
+
...options
|
|
2914
|
+
} = {}) {
|
|
2915
|
+
return this.fetch({
|
|
2916
|
+
...options
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2919
|
+
fetchOptimistic(options) {
|
|
2920
|
+
const defaultedOptions = this.#client.defaultQueryOptions(options);
|
|
2921
|
+
const query = this.#client.getQueryCache().build(this.#client, defaultedOptions);
|
|
2922
|
+
return query.fetch().then(() => this.createResult(query, defaultedOptions));
|
|
2923
|
+
}
|
|
2924
|
+
fetch(fetchOptions) {
|
|
2925
|
+
return this.#executeFetch({
|
|
2926
|
+
...fetchOptions,
|
|
2927
|
+
cancelRefetch: fetchOptions.cancelRefetch ?? true
|
|
2928
|
+
}).then(() => {
|
|
2929
|
+
this.updateResult();
|
|
2930
|
+
return this.#currentResult;
|
|
2931
|
+
});
|
|
2932
|
+
}
|
|
2933
|
+
#executeFetch(fetchOptions) {
|
|
2934
|
+
this.#updateQuery();
|
|
2935
|
+
let promise = this.#currentQuery.fetch(this.options, fetchOptions);
|
|
2936
|
+
if (!fetchOptions?.throwOnError) {
|
|
2937
|
+
promise = promise.catch(noop);
|
|
2938
|
+
}
|
|
2939
|
+
return promise;
|
|
2940
|
+
}
|
|
2941
|
+
#updateStaleTimeout() {
|
|
2942
|
+
this.#clearStaleTimeout();
|
|
2943
|
+
const staleTime = resolveStaleTime(this.options.staleTime, this.#currentQuery);
|
|
2944
|
+
if (isServer || this.#currentResult.isStale || !isValidTimeout(staleTime)) {
|
|
2945
|
+
return;
|
|
2946
|
+
}
|
|
2947
|
+
const time = timeUntilStale(this.#currentResult.dataUpdatedAt, staleTime);
|
|
2948
|
+
const timeout = time + 1;
|
|
2949
|
+
this.#staleTimeoutId = timeoutManager.setTimeout(() => {
|
|
2950
|
+
if (!this.#currentResult.isStale) {
|
|
2951
|
+
this.updateResult();
|
|
2952
|
+
}
|
|
2953
|
+
}, timeout);
|
|
2954
|
+
}
|
|
2955
|
+
#computeRefetchInterval() {
|
|
2956
|
+
return (typeof this.options.refetchInterval === "function" ? this.options.refetchInterval(this.#currentQuery) : this.options.refetchInterval) ?? false;
|
|
2957
|
+
}
|
|
2958
|
+
#updateRefetchInterval(nextInterval) {
|
|
2959
|
+
this.#clearRefetchInterval();
|
|
2960
|
+
this.#currentRefetchInterval = nextInterval;
|
|
2961
|
+
if (isServer || resolveEnabled(this.options.enabled, this.#currentQuery) === false || !isValidTimeout(this.#currentRefetchInterval) || this.#currentRefetchInterval === 0) {
|
|
2962
|
+
return;
|
|
2963
|
+
}
|
|
2964
|
+
this.#refetchIntervalId = timeoutManager.setInterval(() => {
|
|
2965
|
+
if (this.options.refetchIntervalInBackground || focusManager.isFocused()) {
|
|
2966
|
+
this.#executeFetch();
|
|
2967
|
+
}
|
|
2968
|
+
}, this.#currentRefetchInterval);
|
|
2969
|
+
}
|
|
2970
|
+
#updateTimers() {
|
|
2971
|
+
this.#updateStaleTimeout();
|
|
2972
|
+
this.#updateRefetchInterval(this.#computeRefetchInterval());
|
|
2973
|
+
}
|
|
2974
|
+
#clearStaleTimeout() {
|
|
2975
|
+
if (this.#staleTimeoutId) {
|
|
2976
|
+
timeoutManager.clearTimeout(this.#staleTimeoutId);
|
|
2977
|
+
this.#staleTimeoutId = void 0;
|
|
2978
|
+
}
|
|
2979
|
+
}
|
|
2980
|
+
#clearRefetchInterval() {
|
|
2981
|
+
if (this.#refetchIntervalId) {
|
|
2982
|
+
timeoutManager.clearInterval(this.#refetchIntervalId);
|
|
2983
|
+
this.#refetchIntervalId = void 0;
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
createResult(query, options) {
|
|
2987
|
+
const prevQuery = this.#currentQuery;
|
|
2988
|
+
const prevOptions = this.options;
|
|
2989
|
+
const prevResult = this.#currentResult;
|
|
2990
|
+
const prevResultState = this.#currentResultState;
|
|
2991
|
+
const prevResultOptions = this.#currentResultOptions;
|
|
2992
|
+
const queryChange = query !== prevQuery;
|
|
2993
|
+
const queryInitialState = queryChange ? query.state : this.#currentQueryInitialState;
|
|
2994
|
+
const {
|
|
2995
|
+
state
|
|
2996
|
+
} = query;
|
|
2997
|
+
let newState = {
|
|
2998
|
+
...state
|
|
2999
|
+
};
|
|
3000
|
+
let isPlaceholderData = false;
|
|
3001
|
+
let data;
|
|
3002
|
+
if (options._optimisticResults) {
|
|
3003
|
+
const mounted = this.hasListeners();
|
|
3004
|
+
const fetchOnMount = !mounted && shouldFetchOnMount(query, options);
|
|
3005
|
+
const fetchOptionally = mounted && shouldFetchOptionally(query, prevQuery, options, prevOptions);
|
|
3006
|
+
if (fetchOnMount || fetchOptionally) {
|
|
3007
|
+
newState = {
|
|
3008
|
+
...newState,
|
|
3009
|
+
...fetchState(state.data, query.options)
|
|
3010
|
+
};
|
|
3011
|
+
}
|
|
3012
|
+
if (options._optimisticResults === "isRestoring") {
|
|
3013
|
+
newState.fetchStatus = "idle";
|
|
3014
|
+
}
|
|
3015
|
+
}
|
|
3016
|
+
let {
|
|
3017
|
+
error,
|
|
3018
|
+
errorUpdatedAt,
|
|
3019
|
+
status
|
|
3020
|
+
} = newState;
|
|
3021
|
+
data = newState.data;
|
|
3022
|
+
let skipSelect = false;
|
|
3023
|
+
if (options.placeholderData !== void 0 && data === void 0 && status === "pending") {
|
|
3024
|
+
let placeholderData;
|
|
3025
|
+
if (prevResult?.isPlaceholderData && options.placeholderData === prevResultOptions?.placeholderData) {
|
|
3026
|
+
placeholderData = prevResult.data;
|
|
3027
|
+
skipSelect = true;
|
|
3028
|
+
} else {
|
|
3029
|
+
placeholderData = typeof options.placeholderData === "function" ? options.placeholderData(this.#lastQueryWithDefinedData?.state.data, this.#lastQueryWithDefinedData) : options.placeholderData;
|
|
3030
|
+
}
|
|
3031
|
+
if (placeholderData !== void 0) {
|
|
3032
|
+
status = "success";
|
|
3033
|
+
data = replaceData(prevResult?.data, placeholderData, options);
|
|
3034
|
+
isPlaceholderData = true;
|
|
3035
|
+
}
|
|
3036
|
+
}
|
|
3037
|
+
if (options.select && data !== void 0 && !skipSelect) {
|
|
3038
|
+
if (prevResult && data === prevResultState?.data && options.select === this.#selectFn) {
|
|
3039
|
+
data = this.#selectResult;
|
|
3040
|
+
} else {
|
|
3041
|
+
try {
|
|
3042
|
+
this.#selectFn = options.select;
|
|
3043
|
+
data = options.select(data);
|
|
3044
|
+
data = replaceData(prevResult?.data, data, options);
|
|
3045
|
+
this.#selectResult = data;
|
|
3046
|
+
this.#selectError = null;
|
|
3047
|
+
} catch (selectError) {
|
|
3048
|
+
this.#selectError = selectError;
|
|
3049
|
+
}
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
if (this.#selectError) {
|
|
3053
|
+
error = this.#selectError;
|
|
3054
|
+
data = this.#selectResult;
|
|
3055
|
+
errorUpdatedAt = Date.now();
|
|
3056
|
+
status = "error";
|
|
3057
|
+
}
|
|
3058
|
+
const isFetching = newState.fetchStatus === "fetching";
|
|
3059
|
+
const isPending = status === "pending";
|
|
3060
|
+
const isError = status === "error";
|
|
3061
|
+
const isLoading = isPending && isFetching;
|
|
3062
|
+
const hasData = data !== void 0;
|
|
3063
|
+
const result = {
|
|
3064
|
+
status,
|
|
3065
|
+
fetchStatus: newState.fetchStatus,
|
|
3066
|
+
isPending,
|
|
3067
|
+
isSuccess: status === "success",
|
|
3068
|
+
isError,
|
|
3069
|
+
isInitialLoading: isLoading,
|
|
3070
|
+
isLoading,
|
|
3071
|
+
data,
|
|
3072
|
+
dataUpdatedAt: newState.dataUpdatedAt,
|
|
3073
|
+
error,
|
|
3074
|
+
errorUpdatedAt,
|
|
3075
|
+
failureCount: newState.fetchFailureCount,
|
|
3076
|
+
failureReason: newState.fetchFailureReason,
|
|
3077
|
+
errorUpdateCount: newState.errorUpdateCount,
|
|
3078
|
+
isFetched: newState.dataUpdateCount > 0 || newState.errorUpdateCount > 0,
|
|
3079
|
+
isFetchedAfterMount: newState.dataUpdateCount > queryInitialState.dataUpdateCount || newState.errorUpdateCount > queryInitialState.errorUpdateCount,
|
|
3080
|
+
isFetching,
|
|
3081
|
+
isRefetching: isFetching && !isPending,
|
|
3082
|
+
isLoadingError: isError && !hasData,
|
|
3083
|
+
isPaused: newState.fetchStatus === "paused",
|
|
3084
|
+
isPlaceholderData,
|
|
3085
|
+
isRefetchError: isError && hasData,
|
|
3086
|
+
isStale: isStale(query, options),
|
|
3087
|
+
refetch: this.refetch,
|
|
3088
|
+
promise: this.#currentThenable,
|
|
3089
|
+
isEnabled: resolveEnabled(options.enabled, query) !== false
|
|
3090
|
+
};
|
|
3091
|
+
const nextResult = result;
|
|
3092
|
+
if (this.options.experimental_prefetchInRender) {
|
|
3093
|
+
const finalizeThenableIfPossible = thenable => {
|
|
3094
|
+
if (nextResult.status === "error") {
|
|
3095
|
+
thenable.reject(nextResult.error);
|
|
3096
|
+
} else if (nextResult.data !== void 0) {
|
|
3097
|
+
thenable.resolve(nextResult.data);
|
|
3098
|
+
}
|
|
3099
|
+
};
|
|
3100
|
+
const recreateThenable = () => {
|
|
3101
|
+
const pending = this.#currentThenable = nextResult.promise = pendingThenable();
|
|
3102
|
+
finalizeThenableIfPossible(pending);
|
|
3103
|
+
};
|
|
3104
|
+
const prevThenable = this.#currentThenable;
|
|
3105
|
+
switch (prevThenable.status) {
|
|
3106
|
+
case "pending":
|
|
3107
|
+
if (query.queryHash === prevQuery.queryHash) {
|
|
3108
|
+
finalizeThenableIfPossible(prevThenable);
|
|
3109
|
+
}
|
|
3110
|
+
break;
|
|
3111
|
+
case "fulfilled":
|
|
3112
|
+
if (nextResult.status === "error" || nextResult.data !== prevThenable.value) {
|
|
3113
|
+
recreateThenable();
|
|
3114
|
+
}
|
|
3115
|
+
break;
|
|
3116
|
+
case "rejected":
|
|
3117
|
+
if (nextResult.status !== "error" || nextResult.error !== prevThenable.reason) {
|
|
3118
|
+
recreateThenable();
|
|
3119
|
+
}
|
|
3120
|
+
break;
|
|
3121
|
+
}
|
|
3122
|
+
}
|
|
3123
|
+
return nextResult;
|
|
3124
|
+
}
|
|
3125
|
+
updateResult() {
|
|
3126
|
+
const prevResult = this.#currentResult;
|
|
3127
|
+
const nextResult = this.createResult(this.#currentQuery, this.options);
|
|
3128
|
+
this.#currentResultState = this.#currentQuery.state;
|
|
3129
|
+
this.#currentResultOptions = this.options;
|
|
3130
|
+
if (this.#currentResultState.data !== void 0) {
|
|
3131
|
+
this.#lastQueryWithDefinedData = this.#currentQuery;
|
|
3132
|
+
}
|
|
3133
|
+
if (shallowEqualObjects(nextResult, prevResult)) {
|
|
3134
|
+
return;
|
|
3135
|
+
}
|
|
3136
|
+
this.#currentResult = nextResult;
|
|
3137
|
+
const shouldNotifyListeners = () => {
|
|
3138
|
+
if (!prevResult) {
|
|
3139
|
+
return true;
|
|
3140
|
+
}
|
|
3141
|
+
const {
|
|
3142
|
+
notifyOnChangeProps
|
|
3143
|
+
} = this.options;
|
|
3144
|
+
const notifyOnChangePropsValue = typeof notifyOnChangeProps === "function" ? notifyOnChangeProps() : notifyOnChangeProps;
|
|
3145
|
+
if (notifyOnChangePropsValue === "all" || !notifyOnChangePropsValue && !this.#trackedProps.size) {
|
|
3146
|
+
return true;
|
|
3147
|
+
}
|
|
3148
|
+
const includedProps = new Set(notifyOnChangePropsValue ?? this.#trackedProps);
|
|
3149
|
+
if (this.options.throwOnError) {
|
|
3150
|
+
includedProps.add("error");
|
|
3151
|
+
}
|
|
3152
|
+
return Object.keys(this.#currentResult).some(key => {
|
|
3153
|
+
const typedKey = key;
|
|
3154
|
+
const changed = this.#currentResult[typedKey] !== prevResult[typedKey];
|
|
3155
|
+
return changed && includedProps.has(typedKey);
|
|
3156
|
+
});
|
|
3157
|
+
};
|
|
3158
|
+
this.#notify({
|
|
3159
|
+
listeners: shouldNotifyListeners()
|
|
3160
|
+
});
|
|
3161
|
+
}
|
|
3162
|
+
#updateQuery() {
|
|
3163
|
+
const query = this.#client.getQueryCache().build(this.#client, this.options);
|
|
3164
|
+
if (query === this.#currentQuery) {
|
|
3165
|
+
return;
|
|
3166
|
+
}
|
|
3167
|
+
const prevQuery = this.#currentQuery;
|
|
3168
|
+
this.#currentQuery = query;
|
|
3169
|
+
this.#currentQueryInitialState = query.state;
|
|
3170
|
+
if (this.hasListeners()) {
|
|
3171
|
+
prevQuery?.removeObserver(this);
|
|
3172
|
+
query.addObserver(this);
|
|
3173
|
+
}
|
|
3174
|
+
}
|
|
3175
|
+
onQueryUpdate() {
|
|
3176
|
+
this.updateResult();
|
|
3177
|
+
if (this.hasListeners()) {
|
|
3178
|
+
this.#updateTimers();
|
|
3179
|
+
}
|
|
3180
|
+
}
|
|
3181
|
+
#notify(notifyOptions) {
|
|
3182
|
+
notifyManager.batch(() => {
|
|
3183
|
+
if (notifyOptions.listeners) {
|
|
3184
|
+
this.listeners.forEach(listener => {
|
|
3185
|
+
listener(this.#currentResult);
|
|
3186
|
+
});
|
|
3187
|
+
}
|
|
3188
|
+
this.#client.getQueryCache().notify({
|
|
3189
|
+
query: this.#currentQuery,
|
|
3190
|
+
type: "observerResultsUpdated"
|
|
3191
|
+
});
|
|
3192
|
+
});
|
|
3193
|
+
}
|
|
3194
|
+
};
|
|
3195
|
+
function shouldLoadOnMount(query, options) {
|
|
3196
|
+
return resolveEnabled(options.enabled, query) !== false && query.state.data === void 0 && !(query.state.status === "error" && options.retryOnMount === false);
|
|
3197
|
+
}
|
|
3198
|
+
function shouldFetchOnMount(query, options) {
|
|
3199
|
+
return shouldLoadOnMount(query, options) || query.state.data !== void 0 && shouldFetchOn(query, options, options.refetchOnMount);
|
|
3200
|
+
}
|
|
3201
|
+
function shouldFetchOn(query, options, field) {
|
|
3202
|
+
if (resolveEnabled(options.enabled, query) !== false && resolveStaleTime(options.staleTime, query) !== "static") {
|
|
3203
|
+
const value = typeof field === "function" ? field(query) : field;
|
|
3204
|
+
return value === "always" || value !== false && isStale(query, options);
|
|
3205
|
+
}
|
|
3206
|
+
return false;
|
|
3207
|
+
}
|
|
3208
|
+
function shouldFetchOptionally(query, prevQuery, options, prevOptions) {
|
|
3209
|
+
return (query !== prevQuery || resolveEnabled(prevOptions.enabled, query) === false) && (!options.suspense || query.state.status !== "error") && isStale(query, options);
|
|
3210
|
+
}
|
|
3211
|
+
function isStale(query, options) {
|
|
3212
|
+
return resolveEnabled(options.enabled, query) !== false && query.isStaleByTime(resolveStaleTime(options.staleTime, query));
|
|
3213
|
+
}
|
|
3214
|
+
function shouldAssignObserverCurrentProperties(observer, optimisticResult) {
|
|
3215
|
+
if (!shallowEqualObjects(observer.getCurrentResult(), optimisticResult)) {
|
|
3216
|
+
return true;
|
|
3217
|
+
}
|
|
3218
|
+
return false;
|
|
3219
|
+
}const usePageFormManager = ({
|
|
3220
|
+
form,
|
|
3221
|
+
pageId,
|
|
3222
|
+
ns
|
|
3223
|
+
}) => {
|
|
3224
|
+
var _a_0;
|
|
3225
|
+
const {
|
|
3226
|
+
queryClient
|
|
3227
|
+
} = reactQueries.useApiConfigValue();
|
|
3228
|
+
const [defaultValueQuery, setDefaultValueQuery] = React.useState(form === null || form === void 0 ? void 0 : form.defaultValues);
|
|
3229
|
+
React.useEffect(() => {
|
|
3230
|
+
if (!(form === null || form === void 0 ? void 0 : form.defaultValueQueryKey)) {
|
|
3231
|
+
// setDefaultValueQuery(form?.defaultValues)
|
|
3232
|
+
return;
|
|
3233
|
+
}
|
|
3234
|
+
queryClient.getQueryData(form.defaultValueQueryKey);
|
|
3235
|
+
const observer = new QueryObserver(queryClient, {
|
|
3236
|
+
queryKey: form.defaultValueQueryKey,
|
|
3237
|
+
enabled: true,
|
|
3238
|
+
notifyOnChangeProps: ["data"],
|
|
3239
|
+
refetchOnWindowFocus: false
|
|
3240
|
+
});
|
|
3241
|
+
const unsubscribe = observer.subscribe(result => {
|
|
3242
|
+
if (result.data !== undefined) {
|
|
3243
|
+
setDefaultValueQuery(result.data);
|
|
3244
|
+
}
|
|
3245
|
+
});
|
|
3246
|
+
return () => unsubscribe();
|
|
3247
|
+
}, [form === null || form === void 0 ? void 0 : form.defaultValueQueryKey, form === null || form === void 0 ? void 0 : form.defaultValues, queryClient]);
|
|
3248
|
+
const defaultValues = React.useMemo(() => {
|
|
3249
|
+
var _a, _b;
|
|
3250
|
+
return Object.assign(Object.assign({}, defaultValueQuery !== null && defaultValueQuery !== void 0 ? defaultValueQuery : {}), (_b = (_a = form === null || form === void 0 ? void 0 : form.defaultValueQueryMap) === null || _a === void 0 ? void 0 : _a.call(form, defaultValueQuery)) !== null && _b !== void 0 ? _b : {});
|
|
3251
|
+
}, [defaultValueQuery, form]);
|
|
3252
|
+
const {
|
|
3253
|
+
mappedFormData,
|
|
3254
|
+
formSubmit
|
|
3255
|
+
} = useFormData({
|
|
3256
|
+
form,
|
|
3257
|
+
pageId
|
|
3258
|
+
});
|
|
3259
|
+
// Call useFormManager hook at top level (maintains hook order)
|
|
3260
|
+
const rawFormData = reactForm.useFormManager(Object.assign(Object.assign({}, form), {
|
|
3261
|
+
data: mappedFormData,
|
|
3262
|
+
ns,
|
|
3263
|
+
submit: formSubmit,
|
|
3264
|
+
id: pageId,
|
|
3265
|
+
formOptions: Object.assign(Object.assign({
|
|
3266
|
+
defaultValues: defaultValues
|
|
3267
|
+
}, (_a_0 = form === null || form === void 0 ? void 0 : form.formSettings) !== null && _a_0 !== void 0 ? _a_0 : {}), {
|
|
3268
|
+
formId: pageId
|
|
3269
|
+
})
|
|
3270
|
+
}));
|
|
3271
|
+
const formData = React.useMemo(() => Object.assign(Object.assign({}, rawFormData), {
|
|
3272
|
+
formContents: rawFormData.formContents
|
|
3273
|
+
}), [rawFormData]);
|
|
3274
|
+
return {
|
|
3275
|
+
formData
|
|
3276
|
+
};
|
|
3277
|
+
};const EMPTY_ARRAY = [];
|
|
3278
|
+
const usePageConfig = t0 => {
|
|
3279
|
+
const $ = compilerRuntime.c(28);
|
|
3280
|
+
const {
|
|
3281
|
+
queries: t1,
|
|
3282
|
+
form,
|
|
3283
|
+
ns,
|
|
3284
|
+
viewSettings: t2,
|
|
3285
|
+
meta,
|
|
3286
|
+
lazyLoading,
|
|
3287
|
+
variables,
|
|
3288
|
+
pageId
|
|
3289
|
+
} = t0;
|
|
3290
|
+
const queries = t1 === undefined ? EMPTY_ARRAY : t1;
|
|
3291
|
+
let t3;
|
|
3292
|
+
if ($[0] !== t2) {
|
|
3293
|
+
t3 = t2 === undefined ? {} : t2;
|
|
3294
|
+
$[0] = t2;
|
|
3295
|
+
$[1] = t3;
|
|
3296
|
+
} else {
|
|
3297
|
+
t3 = $[1];
|
|
3298
|
+
}
|
|
3299
|
+
const viewSettings = t3;
|
|
3300
|
+
const globalConfig = usePageConfigValue();
|
|
3301
|
+
let t4;
|
|
3302
|
+
if ($[2] !== form || $[3] !== ns || $[4] !== pageId) {
|
|
3303
|
+
t4 = {
|
|
3304
|
+
form,
|
|
3305
|
+
pageId,
|
|
3306
|
+
ns
|
|
3307
|
+
};
|
|
3308
|
+
$[2] = form;
|
|
3309
|
+
$[3] = ns;
|
|
3310
|
+
$[4] = pageId;
|
|
3311
|
+
$[5] = t4;
|
|
3312
|
+
} else {
|
|
3313
|
+
t4 = $[5];
|
|
3314
|
+
}
|
|
3315
|
+
const {
|
|
3316
|
+
formData
|
|
3317
|
+
} = usePageFormManager(t4);
|
|
3318
|
+
let t5;
|
|
3319
|
+
if ($[6] !== pageId || $[7] !== variables) {
|
|
3320
|
+
t5 = {
|
|
3321
|
+
pageId,
|
|
3322
|
+
initialValues: variables
|
|
3323
|
+
};
|
|
3324
|
+
$[6] = pageId;
|
|
3325
|
+
$[7] = variables;
|
|
3326
|
+
$[8] = t5;
|
|
3327
|
+
} else {
|
|
3328
|
+
t5 = $[8];
|
|
3329
|
+
}
|
|
3330
|
+
const {
|
|
3331
|
+
get,
|
|
3332
|
+
set
|
|
3333
|
+
} = usePageValues(t5);
|
|
3334
|
+
let t6;
|
|
3335
|
+
if ($[9] !== get || $[10] !== queries || $[11] !== set) {
|
|
3336
|
+
let t7;
|
|
3337
|
+
if ($[13] !== get || $[14] !== set) {
|
|
3338
|
+
t7 = q => {
|
|
3339
|
+
if (q.type === "mutation") {
|
|
3340
|
+
const mutationConfig = typeof q.mutationConfig === "function" ? q.mutationConfig({
|
|
3341
|
+
get,
|
|
3342
|
+
set
|
|
3343
|
+
}) : q.mutationConfig;
|
|
3344
|
+
return Object.assign(Object.assign({}, q), {
|
|
3345
|
+
mutationConfig
|
|
3346
|
+
});
|
|
3347
|
+
} else {
|
|
3348
|
+
if (q.type === "query") {
|
|
3349
|
+
const queryConfig = typeof q.queryConfig === "function" ? q.queryConfig({
|
|
3350
|
+
get,
|
|
3351
|
+
set
|
|
3352
|
+
}) : q.queryConfig;
|
|
3353
|
+
return Object.assign(Object.assign({}, q), {
|
|
3354
|
+
queryConfig
|
|
3355
|
+
});
|
|
3356
|
+
}
|
|
3357
|
+
}
|
|
3358
|
+
return q;
|
|
3359
|
+
};
|
|
3360
|
+
$[13] = get;
|
|
3361
|
+
$[14] = set;
|
|
3362
|
+
$[15] = t7;
|
|
3363
|
+
} else {
|
|
3364
|
+
t7 = $[15];
|
|
3365
|
+
}
|
|
3366
|
+
t6 = queries.map(t7);
|
|
3367
|
+
$[9] = get;
|
|
3368
|
+
$[10] = queries;
|
|
3369
|
+
$[11] = set;
|
|
3370
|
+
$[12] = t6;
|
|
3371
|
+
} else {
|
|
3372
|
+
t6 = $[12];
|
|
3373
|
+
}
|
|
3374
|
+
const processedQueries = t6;
|
|
3375
|
+
let t7;
|
|
3376
|
+
if ($[16] !== pageId) {
|
|
3377
|
+
t7 = {
|
|
3378
|
+
persistToAtoms: true,
|
|
3379
|
+
scopeId: pageId
|
|
3380
|
+
};
|
|
3381
|
+
$[16] = pageId;
|
|
3382
|
+
$[17] = t7;
|
|
3383
|
+
} else {
|
|
3384
|
+
t7 = $[17];
|
|
3385
|
+
}
|
|
3386
|
+
reactQueries.useApi(processedQueries, t7);
|
|
3387
|
+
let t8;
|
|
3388
|
+
if ($[18] !== pageId || $[19] !== viewSettings) {
|
|
3389
|
+
t8 = {
|
|
3390
|
+
viewSettings,
|
|
3391
|
+
pageId
|
|
3392
|
+
};
|
|
3393
|
+
$[18] = pageId;
|
|
3394
|
+
$[19] = viewSettings;
|
|
3395
|
+
$[20] = t8;
|
|
3396
|
+
} else {
|
|
3397
|
+
t8 = $[20];
|
|
3398
|
+
}
|
|
3399
|
+
const mappedViewSettings = useViewSettings(t8);
|
|
3400
|
+
let t9;
|
|
3401
|
+
if ($[21] !== form || $[22] !== formData || $[23] !== globalConfig || $[24] !== lazyLoading || $[25] !== mappedViewSettings || $[26] !== meta) {
|
|
3402
|
+
t9 = {
|
|
3403
|
+
formData,
|
|
3404
|
+
form,
|
|
3405
|
+
mappedViewSettings,
|
|
3406
|
+
meta,
|
|
3407
|
+
lazyLoading,
|
|
3408
|
+
globalConfig
|
|
3409
|
+
};
|
|
3410
|
+
$[21] = form;
|
|
3411
|
+
$[22] = formData;
|
|
3412
|
+
$[23] = globalConfig;
|
|
3413
|
+
$[24] = lazyLoading;
|
|
3414
|
+
$[25] = mappedViewSettings;
|
|
3415
|
+
$[26] = meta;
|
|
3416
|
+
$[27] = t9;
|
|
3417
|
+
} else {
|
|
3418
|
+
t9 = $[27];
|
|
3419
|
+
}
|
|
3420
|
+
const mergedConfig = t9;
|
|
3421
|
+
return mergedConfig;
|
|
3422
|
+
};/**
|
|
3423
|
+
* Hook for evaluating and managing dynamic metadata.
|
|
3424
|
+
*
|
|
3425
|
+
* Pipeline:
|
|
3426
|
+
* 1. Evaluate `meta` (if it's a MappedItemsFunction, call it with get/set)
|
|
3427
|
+
* 2. Resolve all dynamic functions via `resolveMetadata()`
|
|
3428
|
+
* 3. Translate strings via i18n
|
|
3429
|
+
* 4. Auto-apply to DOM (client) or store (SSR) via `applyMetadataToDom` / MetadataStore
|
|
3430
|
+
*
|
|
3431
|
+
* @returns Resolved and translated metadata
|
|
3432
|
+
*/
|
|
3433
|
+
function useMetadata({
|
|
3434
|
+
meta,
|
|
3435
|
+
autoApply = true,
|
|
3436
|
+
pageId
|
|
3437
|
+
}) {
|
|
3438
|
+
const {
|
|
3439
|
+
translateText,
|
|
3440
|
+
locale
|
|
3441
|
+
} = usePageConfigValue();
|
|
3442
|
+
const t = React.useMemo(() => translateText !== null && translateText !== void 0 ? translateText : key => key, [translateText]);
|
|
3443
|
+
const {
|
|
3444
|
+
get,
|
|
3445
|
+
set
|
|
3446
|
+
} = usePageValues({
|
|
3447
|
+
pageId
|
|
3448
|
+
});
|
|
3449
|
+
const metadataStore = useMetadataStore();
|
|
3450
|
+
// Step 1: Evaluate metadata (if function)
|
|
3451
|
+
const evaluatedMeta = React.useMemo(() => {
|
|
3452
|
+
if (!meta) return {};
|
|
3453
|
+
if (typeof meta === 'function') {
|
|
3454
|
+
return meta({
|
|
3455
|
+
get,
|
|
3456
|
+
set
|
|
3457
|
+
});
|
|
3458
|
+
}
|
|
3459
|
+
return meta;
|
|
3460
|
+
}, [meta, get, set]);
|
|
3461
|
+
// Step 2: Resolve all dynamic evaluator functions into plain values
|
|
3462
|
+
const resolved = React.useMemo(() => resolveMetadata(evaluatedMeta, {
|
|
3463
|
+
get,
|
|
3464
|
+
set
|
|
3465
|
+
}), [evaluatedMeta, get, set]);
|
|
3466
|
+
// Step 3: Translate metadata strings (i18n)
|
|
3467
|
+
const translated = React.useMemo(() => {
|
|
3468
|
+
var _a;
|
|
3469
|
+
const result = Object.assign({}, resolved);
|
|
3470
|
+
// Translate basic fields
|
|
3471
|
+
if (result.title) {
|
|
3472
|
+
result.title = t(result.title, {
|
|
3473
|
+
ns: 'meta',
|
|
3474
|
+
defaultValue: result.title
|
|
3475
|
+
});
|
|
3476
|
+
}
|
|
3477
|
+
if (result.description) {
|
|
3478
|
+
result.description = t(result.description, {
|
|
3479
|
+
ns: 'meta',
|
|
3480
|
+
defaultValue: result.description
|
|
3481
|
+
});
|
|
3482
|
+
}
|
|
3483
|
+
if (result.keywords) {
|
|
3484
|
+
result.keywords = result.keywords.map(kw => t(kw, {
|
|
3485
|
+
ns: 'meta',
|
|
3486
|
+
defaultValue: kw
|
|
3487
|
+
}));
|
|
3488
|
+
}
|
|
3489
|
+
if (result.author) {
|
|
3490
|
+
result.author = t(result.author, {
|
|
3491
|
+
ns: 'meta',
|
|
3492
|
+
defaultValue: result.author
|
|
3493
|
+
});
|
|
3494
|
+
}
|
|
3495
|
+
// Translate Open Graph
|
|
3496
|
+
if (result.openGraph) {
|
|
3497
|
+
result.openGraph = Object.assign({}, result.openGraph);
|
|
3498
|
+
if (result.openGraph.title) {
|
|
3499
|
+
result.openGraph.title = t(result.openGraph.title, {
|
|
3500
|
+
ns: 'meta',
|
|
3501
|
+
defaultValue: result.openGraph.title
|
|
3502
|
+
});
|
|
3503
|
+
}
|
|
3504
|
+
if (result.openGraph.description) {
|
|
3505
|
+
result.openGraph.description = t(result.openGraph.description, {
|
|
3506
|
+
ns: 'meta',
|
|
3507
|
+
defaultValue: result.openGraph.description
|
|
3508
|
+
});
|
|
3509
|
+
}
|
|
3510
|
+
if (result.openGraph.siteName) {
|
|
3511
|
+
result.openGraph.siteName = t(result.openGraph.siteName, {
|
|
3512
|
+
ns: 'meta',
|
|
3513
|
+
defaultValue: result.openGraph.siteName
|
|
3514
|
+
});
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
// Translate Twitter Card
|
|
3518
|
+
if (result.twitter) {
|
|
3519
|
+
result.twitter = Object.assign({}, result.twitter);
|
|
3520
|
+
if (result.twitter.title) {
|
|
3521
|
+
result.twitter.title = t(result.twitter.title, {
|
|
3522
|
+
ns: 'meta',
|
|
3523
|
+
defaultValue: result.twitter.title
|
|
3524
|
+
});
|
|
3525
|
+
}
|
|
3526
|
+
if (result.twitter.description) {
|
|
3527
|
+
result.twitter.description = t(result.twitter.description, {
|
|
3528
|
+
ns: 'meta',
|
|
3529
|
+
defaultValue: result.twitter.description
|
|
3530
|
+
});
|
|
3531
|
+
}
|
|
3532
|
+
}
|
|
3533
|
+
// Set language from locale
|
|
3534
|
+
result.lang = (_a = result.lang) !== null && _a !== void 0 ? _a : locale;
|
|
3535
|
+
return result;
|
|
3536
|
+
}, [resolved, t, locale]);
|
|
3537
|
+
// Step 4: Apply metadata
|
|
3538
|
+
React.useEffect(() => {
|
|
3539
|
+
if (!autoApply) return;
|
|
3540
|
+
// If we have a request-scoped store (SSR), write to it
|
|
3541
|
+
if (metadataStore) {
|
|
3542
|
+
metadataStore.setMetadata(translated);
|
|
3543
|
+
}
|
|
3544
|
+
// On the client, also apply to DOM
|
|
3545
|
+
if (typeof document !== 'undefined') {
|
|
3546
|
+
applyMetadataToDom(translated);
|
|
3547
|
+
}
|
|
3548
|
+
}, [translated, autoApply, metadataStore]);
|
|
3549
|
+
return translated;
|
|
3550
|
+
}
|
|
3551
|
+
/**
|
|
3552
|
+
* Hook to manually apply metadata (when autoApply is false)
|
|
3553
|
+
* @returns Function to apply resolved metadata to the DOM
|
|
3554
|
+
*/
|
|
3555
|
+
function useApplyMetadata() {
|
|
3556
|
+
const $ = compilerRuntime.c(2);
|
|
3557
|
+
const metadataStore = useMetadataStore();
|
|
3558
|
+
let t0;
|
|
3559
|
+
if ($[0] !== metadataStore) {
|
|
3560
|
+
t0 = meta => {
|
|
3561
|
+
if (metadataStore) {
|
|
3562
|
+
metadataStore.setMetadata(meta);
|
|
3563
|
+
}
|
|
3564
|
+
if (typeof document !== "undefined") {
|
|
3565
|
+
applyMetadataToDom(meta);
|
|
3566
|
+
}
|
|
3567
|
+
};
|
|
3568
|
+
$[0] = metadataStore;
|
|
3569
|
+
$[1] = t0;
|
|
3570
|
+
} else {
|
|
3571
|
+
t0 = $[1];
|
|
3572
|
+
}
|
|
3573
|
+
return t0;
|
|
3574
|
+
}/**
|
|
3575
|
+
* Headless component that manages metadata injection.
|
|
3576
|
+
* On web: injects metadata into `<head>`.
|
|
3577
|
+
* On SSR: stores metadata in the request-scoped MetadataStore (via context).
|
|
3578
|
+
* On React Native: metadata is resolved but not applied to DOM.
|
|
3579
|
+
*
|
|
3580
|
+
* @example
|
|
3581
|
+
* ```tsx
|
|
3582
|
+
* <MetadataManager
|
|
3583
|
+
* meta={{
|
|
3584
|
+
* title: 'My Page',
|
|
3585
|
+
* description: 'Page description',
|
|
3586
|
+
* openGraph: { type: 'website', image: '/og.png' },
|
|
3587
|
+
* twitter: { card: 'summary_large_image' },
|
|
3588
|
+
* }}
|
|
3589
|
+
* pageId="my-page"
|
|
3590
|
+
* />
|
|
3591
|
+
* ```
|
|
3592
|
+
*/
|
|
3593
|
+
const MetadataManagerImpl = t0 => {
|
|
3594
|
+
const $ = compilerRuntime.c(4);
|
|
3595
|
+
const {
|
|
3596
|
+
meta,
|
|
3597
|
+
ns: t1,
|
|
3598
|
+
pageId
|
|
3599
|
+
} = t0;
|
|
3600
|
+
const ns = t1 === undefined ? "common" : t1;
|
|
3601
|
+
let t2;
|
|
3602
|
+
if ($[0] !== meta || $[1] !== ns || $[2] !== pageId) {
|
|
3603
|
+
t2 = {
|
|
3604
|
+
meta,
|
|
3605
|
+
ns,
|
|
3606
|
+
pageId
|
|
3607
|
+
};
|
|
3608
|
+
$[0] = meta;
|
|
3609
|
+
$[1] = ns;
|
|
3610
|
+
$[2] = pageId;
|
|
3611
|
+
$[3] = t2;
|
|
3612
|
+
} else {
|
|
3613
|
+
t2 = $[3];
|
|
3614
|
+
}
|
|
3615
|
+
useMetadata(t2);
|
|
3616
|
+
return null;
|
|
3617
|
+
};
|
|
3618
|
+
MetadataManagerImpl.displayName = 'MetadataManager';
|
|
3619
|
+
const MetadataManager = MetadataManagerImpl;const PageGenerator = _a => {
|
|
3620
|
+
var {
|
|
3621
|
+
enableAuthControl = true,
|
|
3622
|
+
meta,
|
|
3623
|
+
variables
|
|
3624
|
+
} = _a,
|
|
3625
|
+
props = __rest(_a, ["enableAuthControl", "meta", "variables"]);
|
|
3626
|
+
const {
|
|
3627
|
+
BodyContainer,
|
|
3628
|
+
FooterContainer,
|
|
3629
|
+
HeaderContainer,
|
|
3630
|
+
PageContainer,
|
|
3631
|
+
isLogged,
|
|
3632
|
+
authValues,
|
|
3633
|
+
authPageProps
|
|
3634
|
+
} = usePageConfigValue();
|
|
3635
|
+
const isUnlogged = React.useMemo(() => enableAuthControl && !isLogged(authValues ? authValues : null), [enableAuthControl, authValues, isLogged]);
|
|
3636
|
+
const selectedProps = React.useMemo(() => {
|
|
3637
|
+
return enableAuthControl && isUnlogged ? authPageProps : props;
|
|
3638
|
+
}, [enableAuthControl, isUnlogged, authPageProps, props]);
|
|
3639
|
+
const {
|
|
3640
|
+
contents = [],
|
|
3641
|
+
queries = [],
|
|
3642
|
+
form,
|
|
3643
|
+
id = 'default-page-id',
|
|
3644
|
+
viewSettings,
|
|
3645
|
+
ns
|
|
3646
|
+
} = React.useMemo(() => selectedProps, [selectedProps]);
|
|
3647
|
+
const config = usePageConfig({
|
|
3648
|
+
queries,
|
|
3649
|
+
form,
|
|
3650
|
+
ns: ns !== null && ns !== void 0 ? ns : '',
|
|
3651
|
+
viewSettings,
|
|
3652
|
+
pageId: id,
|
|
3653
|
+
variables
|
|
3654
|
+
});
|
|
3655
|
+
const {
|
|
3656
|
+
mappedViewSettings
|
|
3657
|
+
} = config;
|
|
3658
|
+
const {
|
|
3659
|
+
allContents,
|
|
3660
|
+
body,
|
|
3661
|
+
footer,
|
|
3662
|
+
header
|
|
3663
|
+
} = useGenerateContent({
|
|
3664
|
+
contents,
|
|
3665
|
+
pageId: id,
|
|
3666
|
+
ns,
|
|
3667
|
+
pageConfig: config
|
|
3668
|
+
});
|
|
3669
|
+
const LayoutComponent = React.useMemo(() => {
|
|
3670
|
+
var _a_0;
|
|
3671
|
+
return (_a_0 = mappedViewSettings.layoutComponent) !== null && _a_0 !== void 0 ? _a_0 : BodyContainer;
|
|
3672
|
+
}, [mappedViewSettings.layoutComponent, BodyContainer]);
|
|
3673
|
+
const layoutProps = React.useMemo(() => {
|
|
3674
|
+
var _a_1;
|
|
3675
|
+
return (_a_1 = mappedViewSettings.layoutProps) !== null && _a_1 !== void 0 ? _a_1 : {};
|
|
3676
|
+
}, [mappedViewSettings.layoutProps]);
|
|
3677
|
+
const PageContainerComponent = React.useMemo(() => {
|
|
3678
|
+
var _a_2;
|
|
3679
|
+
return (_a_2 = mappedViewSettings.pageContainerComponent) !== null && _a_2 !== void 0 ? _a_2 : PageContainer;
|
|
3680
|
+
}, [mappedViewSettings.pageContainerComponent, PageContainer]);
|
|
3681
|
+
const pageContainerProps = React.useMemo(() => {
|
|
3682
|
+
var _a_3;
|
|
3683
|
+
return (_a_3 = mappedViewSettings.pageContainerProps) !== null && _a_3 !== void 0 ? _a_3 : {};
|
|
3684
|
+
}, [mappedViewSettings.pageContainerProps]);
|
|
3685
|
+
const layoutBody = React.useMemo(() => body, [body]);
|
|
3686
|
+
const store = useStore();
|
|
3687
|
+
const refreshQueries = React.useCallback(() => {
|
|
3688
|
+
const val = store.get(reactQueries.queriesAtom);
|
|
3689
|
+
Object.values(val).forEach(query => {
|
|
3690
|
+
query.refetch();
|
|
3691
|
+
});
|
|
3692
|
+
}, [store]);
|
|
3693
|
+
return jsxRuntime.jsxs(PageContainerComponent, Object.assign({
|
|
3694
|
+
id: id
|
|
3695
|
+
}, pageContainerProps, {
|
|
3696
|
+
children: [jsxRuntime.jsx(MetadataManager, {
|
|
3697
|
+
meta: meta,
|
|
3698
|
+
ns: ns,
|
|
3699
|
+
pageId: id
|
|
3700
|
+
}), jsxRuntime.jsx(HeaderContainer, Object.assign({
|
|
3701
|
+
allContents: allContents,
|
|
3702
|
+
handleRefresh: refreshQueries
|
|
3703
|
+
}, mappedViewSettings.header, {
|
|
3704
|
+
pageId: id,
|
|
3705
|
+
children: header
|
|
3706
|
+
})), jsxRuntime.jsx(LayoutComponent, Object.assign({
|
|
3707
|
+
allContents: allContents,
|
|
3708
|
+
handleRefresh: refreshQueries,
|
|
3709
|
+
viewSettings: mappedViewSettings,
|
|
3710
|
+
pageId: id
|
|
3711
|
+
}, layoutProps, {
|
|
3712
|
+
children: layoutBody
|
|
3713
|
+
}), id), jsxRuntime.jsx(FooterContainer, Object.assign({
|
|
3714
|
+
allContents: allContents,
|
|
3715
|
+
handleRefresh: refreshQueries
|
|
3716
|
+
}, mappedViewSettings.footer, {
|
|
3717
|
+
pageId: id,
|
|
3718
|
+
children: footer
|
|
3719
|
+
}))]
|
|
3720
|
+
}), id);
|
|
3721
|
+
};const ContainerImpl = t0 => {
|
|
3722
|
+
const $ = compilerRuntime.c(13);
|
|
3723
|
+
const {
|
|
3724
|
+
content,
|
|
3725
|
+
ns,
|
|
3726
|
+
pageId
|
|
3727
|
+
} = t0;
|
|
3728
|
+
const {
|
|
3729
|
+
ItemsContainer
|
|
3730
|
+
} = usePageConfigValue();
|
|
3731
|
+
let t1;
|
|
3732
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
3733
|
+
t1 = {
|
|
3734
|
+
elements: [],
|
|
3735
|
+
formContents: [],
|
|
3736
|
+
errors: [],
|
|
3737
|
+
formValues: {},
|
|
3738
|
+
setValue: _temp
|
|
3739
|
+
};
|
|
3740
|
+
$[0] = t1;
|
|
3741
|
+
} else {
|
|
3742
|
+
t1 = $[0];
|
|
3743
|
+
}
|
|
3744
|
+
let t2;
|
|
3745
|
+
if ($[1] !== content.items || $[2] !== ns || $[3] !== pageId) {
|
|
3746
|
+
t2 = {
|
|
3747
|
+
pageId,
|
|
3748
|
+
contents: content.items,
|
|
3749
|
+
ns,
|
|
3750
|
+
formData: t1
|
|
3751
|
+
};
|
|
3752
|
+
$[1] = content.items;
|
|
3753
|
+
$[2] = ns;
|
|
3754
|
+
$[3] = pageId;
|
|
3755
|
+
$[4] = t2;
|
|
3756
|
+
} else {
|
|
3757
|
+
t2 = $[4];
|
|
3758
|
+
}
|
|
3759
|
+
const {
|
|
3760
|
+
components
|
|
3761
|
+
} = useGenerateContentRender(t2);
|
|
3762
|
+
const CustomContainer = content.component;
|
|
3763
|
+
let t3;
|
|
3764
|
+
if ($[5] !== components) {
|
|
3765
|
+
t3 = components.map(_temp2);
|
|
3766
|
+
$[5] = components;
|
|
3767
|
+
$[6] = t3;
|
|
3768
|
+
} else {
|
|
3769
|
+
t3 = $[6];
|
|
3770
|
+
}
|
|
3771
|
+
const children = t3;
|
|
3772
|
+
if (!CustomContainer) {
|
|
3773
|
+
let t4;
|
|
3774
|
+
if ($[7] !== ItemsContainer || $[8] !== children) {
|
|
3775
|
+
t4 = jsxRuntime.jsx(ItemsContainer, {
|
|
3776
|
+
children
|
|
3777
|
+
});
|
|
3778
|
+
$[7] = ItemsContainer;
|
|
3779
|
+
$[8] = children;
|
|
3780
|
+
$[9] = t4;
|
|
3781
|
+
} else {
|
|
3782
|
+
t4 = $[9];
|
|
3783
|
+
}
|
|
3784
|
+
return t4;
|
|
3785
|
+
}
|
|
3786
|
+
let t4;
|
|
3787
|
+
if ($[10] !== CustomContainer || $[11] !== children) {
|
|
3788
|
+
t4 = jsxRuntime.jsx(CustomContainer, {
|
|
3789
|
+
children
|
|
3790
|
+
});
|
|
3791
|
+
$[10] = CustomContainer;
|
|
3792
|
+
$[11] = children;
|
|
3793
|
+
$[12] = t4;
|
|
3794
|
+
} else {
|
|
3795
|
+
t4 = $[12];
|
|
3796
|
+
}
|
|
3797
|
+
return t4;
|
|
3798
|
+
};
|
|
3799
|
+
// Export with React.memo and fast-deep-equal comparator for optimal performance
|
|
3800
|
+
const Container = React.memo(ContainerImpl, (prevProps, nextProps) => {
|
|
3801
|
+
// Return true if props are equal (component should NOT re-render)
|
|
3802
|
+
return deepEqual(prevProps, nextProps);
|
|
3803
|
+
});
|
|
3804
|
+
function _temp() {}
|
|
3805
|
+
function _temp2(el) {
|
|
3806
|
+
return el.element;
|
|
3807
|
+
}const ComponentFunctionMap = t0 => {
|
|
3808
|
+
const $ = compilerRuntime.c(6);
|
|
3809
|
+
const {
|
|
3810
|
+
Component,
|
|
3811
|
+
pageId
|
|
3812
|
+
} = t0;
|
|
3813
|
+
let t1;
|
|
3814
|
+
if ($[0] !== pageId) {
|
|
3815
|
+
t1 = {
|
|
3816
|
+
pageId
|
|
3817
|
+
};
|
|
3818
|
+
$[0] = pageId;
|
|
3819
|
+
$[1] = t1;
|
|
3820
|
+
} else {
|
|
3821
|
+
t1 = $[1];
|
|
3822
|
+
}
|
|
3823
|
+
const {
|
|
3824
|
+
get,
|
|
3825
|
+
set
|
|
3826
|
+
} = usePageValues(t1);
|
|
3827
|
+
let t2;
|
|
3828
|
+
if ($[2] !== Component || $[3] !== get || $[4] !== set) {
|
|
3829
|
+
t2 = jsxRuntime.jsx(Component, {
|
|
3830
|
+
get,
|
|
3831
|
+
set
|
|
3832
|
+
});
|
|
3833
|
+
$[2] = Component;
|
|
3834
|
+
$[3] = get;
|
|
3835
|
+
$[4] = set;
|
|
3836
|
+
$[5] = t2;
|
|
3837
|
+
} else {
|
|
3838
|
+
t2 = $[5];
|
|
3839
|
+
}
|
|
3840
|
+
return t2;
|
|
3841
|
+
};
|
|
3842
|
+
// Internal component implementation
|
|
3843
|
+
const RenderComponentImpl = ({
|
|
3844
|
+
content,
|
|
3845
|
+
pageId
|
|
3846
|
+
}) => {
|
|
3847
|
+
const {
|
|
3848
|
+
component: Component
|
|
3849
|
+
} = content;
|
|
3850
|
+
if (typeof Component === 'function') {
|
|
3851
|
+
return jsxRuntime.jsx(ComponentFunctionMap, {
|
|
3852
|
+
Component: Component,
|
|
3853
|
+
pageId: pageId
|
|
3854
|
+
});
|
|
3855
|
+
} else {
|
|
3856
|
+
return Component;
|
|
3857
|
+
}
|
|
3858
|
+
};
|
|
3859
|
+
// Export with React.memo and fast-deep-equal comparator for optimal performance
|
|
3860
|
+
const RenderComponent = React.memo(RenderComponentImpl, (prevProps, nextProps) => {
|
|
3861
|
+
// Return true if props are equal (component should NOT re-render)
|
|
3862
|
+
return deepEqual(prevProps, nextProps);
|
|
3863
|
+
});const RenderComponents = props => {
|
|
3864
|
+
if (props.content.type === 'container') {
|
|
3865
|
+
return jsxRuntime.jsx(Container, {
|
|
3866
|
+
content: props.content,
|
|
3867
|
+
ns: props.ns,
|
|
3868
|
+
pageId: props.pageId
|
|
3869
|
+
}, props.key);
|
|
3870
|
+
}
|
|
3871
|
+
return jsxRuntime.jsx(RenderComponent, {
|
|
3872
|
+
content: props.content,
|
|
3873
|
+
ns: props.ns,
|
|
3874
|
+
pageId: props.pageId
|
|
3875
|
+
}, props.key);
|
|
3876
|
+
};/**
|
|
3877
|
+
* Next.js Integration Helpers
|
|
3878
|
+
*
|
|
3879
|
+
* Provides helpers for using the pages metadata system with Next.js:
|
|
3880
|
+
* - `toNextMetadata()` — App Router (`generateMetadata`)
|
|
3881
|
+
* - `NextHeadFromMetadata` — Pages Router (`next/head`)
|
|
3882
|
+
*
|
|
3883
|
+
* @module integrations/next
|
|
3884
|
+
*/
|
|
3885
|
+
// ─── toNextMetadata (App Router) ─────────────────────────────
|
|
3886
|
+
/**
|
|
3887
|
+
* Convert ResolvedMetadata into a Next.js Metadata object
|
|
3888
|
+
* for use with App Router's `generateMetadata` or `metadata` export.
|
|
3889
|
+
*
|
|
3890
|
+
* @example
|
|
3891
|
+
* ```ts
|
|
3892
|
+
* // app/page.tsx
|
|
3893
|
+
* import { resolveMetadata, toNextMetadata } from '@/core/pages';
|
|
3894
|
+
*
|
|
3895
|
+
* export async function generateMetadata() {
|
|
3896
|
+
* const resolved = resolveMetadata(pageConfig.meta, context);
|
|
3897
|
+
* return toNextMetadata(resolved);
|
|
3898
|
+
* }
|
|
3899
|
+
* ```
|
|
3900
|
+
*/
|
|
3901
|
+
function toNextMetadata(resolved) {
|
|
3902
|
+
var _a, _b, _c, _d, _e, _f;
|
|
3903
|
+
const result = {};
|
|
3904
|
+
// Basic
|
|
3905
|
+
if (resolved.title) result.title = resolved.title;
|
|
3906
|
+
if (resolved.description) result.description = resolved.description;
|
|
3907
|
+
if ((_a = resolved.keywords) === null || _a === void 0 ? void 0 : _a.length) result.keywords = resolved.keywords;
|
|
3908
|
+
if (resolved.author) result.authors = [{
|
|
3909
|
+
name: resolved.author
|
|
3910
|
+
}];
|
|
3911
|
+
if (resolved.viewport) result.viewport = resolved.viewport;
|
|
3912
|
+
if (resolved.themeColor) result.themeColor = resolved.themeColor;
|
|
3913
|
+
// Robots
|
|
3914
|
+
if (resolved.robots || resolved.disableIndexing) {
|
|
3915
|
+
const r = (_b = resolved.robots) !== null && _b !== void 0 ? _b : {};
|
|
3916
|
+
result.robots = {
|
|
3917
|
+
index: !(resolved.disableIndexing || r.noindex),
|
|
3918
|
+
follow: !(resolved.disableIndexing || r.nofollow),
|
|
3919
|
+
noarchive: r.noarchive,
|
|
3920
|
+
nosnippet: r.nosnippet,
|
|
3921
|
+
'max-image-preview': r.maxImagePreview,
|
|
3922
|
+
'max-snippet': r.maxSnippet
|
|
3923
|
+
};
|
|
3924
|
+
}
|
|
3925
|
+
// Alternates
|
|
3926
|
+
if (resolved.canonical || resolved.alternates) {
|
|
3927
|
+
result.alternates = {
|
|
3928
|
+
canonical: (_d = (_c = resolved.alternates) === null || _c === void 0 ? void 0 : _c.canonical) !== null && _d !== void 0 ? _d : resolved.canonical,
|
|
3929
|
+
languages: (_e = resolved.alternates) === null || _e === void 0 ? void 0 : _e.languages,
|
|
3930
|
+
media: (_f = resolved.alternates) === null || _f === void 0 ? void 0 : _f.media
|
|
3931
|
+
};
|
|
3932
|
+
}
|
|
3933
|
+
// Open Graph
|
|
3934
|
+
if (resolved.openGraph) {
|
|
3935
|
+
const og = resolved.openGraph;
|
|
3936
|
+
const nextOg = {};
|
|
3937
|
+
if (og.title) nextOg.title = og.title;
|
|
3938
|
+
if (og.description) nextOg.description = og.description;
|
|
3939
|
+
if (og.url) nextOg.url = og.url;
|
|
3940
|
+
if (og.siteName) nextOg.siteName = og.siteName;
|
|
3941
|
+
if (og.locale) nextOg.locale = og.locale;
|
|
3942
|
+
if (og.type) nextOg.type = og.type;
|
|
3943
|
+
// Images
|
|
3944
|
+
const images = normalizeOgImages(og.images, og.image);
|
|
3945
|
+
if (images.length) {
|
|
3946
|
+
nextOg.images = images.map(img => ({
|
|
3947
|
+
url: img.url,
|
|
3948
|
+
alt: img.alt,
|
|
3949
|
+
width: img.width,
|
|
3950
|
+
height: img.height,
|
|
3951
|
+
type: img.type
|
|
3952
|
+
}));
|
|
3953
|
+
}
|
|
3954
|
+
// Article metadata
|
|
3955
|
+
if (og.article) {
|
|
3956
|
+
if (og.article.publishedTime) nextOg.publishedTime = og.article.publishedTime;
|
|
3957
|
+
if (og.article.modifiedTime) nextOg.modifiedTime = og.article.modifiedTime;
|
|
3958
|
+
if (og.article.section) nextOg.section = og.article.section;
|
|
3959
|
+
if (og.article.tags) nextOg.tags = og.article.tags;
|
|
3960
|
+
if (og.article.author) {
|
|
3961
|
+
nextOg.authors = Array.isArray(og.article.author) ? og.article.author : [og.article.author];
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
result.openGraph = nextOg;
|
|
3965
|
+
}
|
|
3966
|
+
// Twitter
|
|
3967
|
+
if (resolved.twitter) {
|
|
3968
|
+
const tw = resolved.twitter;
|
|
3969
|
+
const nextTw = {};
|
|
3970
|
+
if (tw.card) nextTw.card = tw.card;
|
|
3971
|
+
if (tw.site) nextTw.site = tw.site;
|
|
3972
|
+
if (tw.creator) nextTw.creator = tw.creator;
|
|
3973
|
+
if (tw.title) nextTw.title = tw.title;
|
|
3974
|
+
if (tw.description) nextTw.description = tw.description;
|
|
3975
|
+
if (tw.image) {
|
|
3976
|
+
nextTw.images = tw.imageAlt ? [{
|
|
3977
|
+
url: tw.image,
|
|
3978
|
+
alt: tw.imageAlt
|
|
3979
|
+
}] : [tw.image];
|
|
3980
|
+
}
|
|
3981
|
+
result.twitter = nextTw;
|
|
3982
|
+
}
|
|
3983
|
+
// Icons
|
|
3984
|
+
if (resolved.icons) {
|
|
3985
|
+
const icons = resolved.icons;
|
|
3986
|
+
const nextIcons = {};
|
|
3987
|
+
if (icons.icon) {
|
|
3988
|
+
const list = typeof icons.icon === 'string' ? [{
|
|
3989
|
+
url: icons.icon
|
|
3990
|
+
}] : Array.isArray(icons.icon) ? icons.icon : [icons.icon];
|
|
3991
|
+
nextIcons.icon = list.map(i => ({
|
|
3992
|
+
url: i.url,
|
|
3993
|
+
type: i.type,
|
|
3994
|
+
sizes: i.sizes
|
|
3995
|
+
}));
|
|
3996
|
+
}
|
|
3997
|
+
if (icons.apple) {
|
|
3998
|
+
const list = typeof icons.apple === 'string' ? [{
|
|
3999
|
+
url: icons.apple
|
|
4000
|
+
}] : Array.isArray(icons.apple) ? icons.apple : [icons.apple];
|
|
4001
|
+
nextIcons.apple = list.map(i => ({
|
|
4002
|
+
url: i.url,
|
|
4003
|
+
type: i.type,
|
|
4004
|
+
sizes: i.sizes
|
|
4005
|
+
}));
|
|
4006
|
+
}
|
|
4007
|
+
if (icons.shortcut) nextIcons.shortcut = icons.shortcut;
|
|
4008
|
+
result.icons = nextIcons;
|
|
4009
|
+
}
|
|
4010
|
+
// Manifest
|
|
4011
|
+
if (resolved.manifest) result.manifest = resolved.manifest;
|
|
4012
|
+
return result;
|
|
4013
|
+
}
|
|
4014
|
+
function toNextHeadTags(resolved) {
|
|
4015
|
+
var _a, _b;
|
|
4016
|
+
const tags = [];
|
|
4017
|
+
if (resolved.title) {
|
|
4018
|
+
tags.push({
|
|
4019
|
+
key: 'title',
|
|
4020
|
+
tag: 'title',
|
|
4021
|
+
attributes: {},
|
|
4022
|
+
content: resolved.title
|
|
4023
|
+
});
|
|
4024
|
+
}
|
|
4025
|
+
if (resolved.description) {
|
|
4026
|
+
tags.push({
|
|
4027
|
+
key: 'desc',
|
|
4028
|
+
tag: 'meta',
|
|
4029
|
+
attributes: {
|
|
4030
|
+
name: 'description',
|
|
4031
|
+
content: resolved.description
|
|
4032
|
+
}
|
|
4033
|
+
});
|
|
4034
|
+
}
|
|
4035
|
+
if (resolved.canonical) {
|
|
4036
|
+
tags.push({
|
|
4037
|
+
key: 'canonical',
|
|
4038
|
+
tag: 'link',
|
|
4039
|
+
attributes: {
|
|
4040
|
+
rel: 'canonical',
|
|
4041
|
+
href: resolved.canonical
|
|
4042
|
+
}
|
|
4043
|
+
});
|
|
4044
|
+
}
|
|
4045
|
+
if ((_a = resolved.keywords) === null || _a === void 0 ? void 0 : _a.length) {
|
|
4046
|
+
tags.push({
|
|
4047
|
+
key: 'keywords',
|
|
4048
|
+
tag: 'meta',
|
|
4049
|
+
attributes: {
|
|
4050
|
+
name: 'keywords',
|
|
4051
|
+
content: resolved.keywords.join(', ')
|
|
4052
|
+
}
|
|
4053
|
+
});
|
|
4054
|
+
}
|
|
4055
|
+
if (resolved.author) {
|
|
4056
|
+
tags.push({
|
|
4057
|
+
key: 'author',
|
|
4058
|
+
tag: 'meta',
|
|
4059
|
+
attributes: {
|
|
4060
|
+
name: 'author',
|
|
4061
|
+
content: resolved.author
|
|
4062
|
+
}
|
|
4063
|
+
});
|
|
4064
|
+
}
|
|
4065
|
+
if (resolved.viewport) {
|
|
4066
|
+
tags.push({
|
|
4067
|
+
key: 'viewport',
|
|
4068
|
+
tag: 'meta',
|
|
4069
|
+
attributes: {
|
|
4070
|
+
name: 'viewport',
|
|
4071
|
+
content: resolved.viewport
|
|
4072
|
+
}
|
|
4073
|
+
});
|
|
4074
|
+
}
|
|
4075
|
+
if (resolved.themeColor) {
|
|
4076
|
+
tags.push({
|
|
4077
|
+
key: 'theme-color',
|
|
4078
|
+
tag: 'meta',
|
|
4079
|
+
attributes: {
|
|
4080
|
+
name: 'theme-color',
|
|
4081
|
+
content: resolved.themeColor
|
|
4082
|
+
}
|
|
4083
|
+
});
|
|
4084
|
+
}
|
|
4085
|
+
// OG
|
|
4086
|
+
if (resolved.openGraph) {
|
|
4087
|
+
const og = resolved.openGraph;
|
|
4088
|
+
if (og.type) tags.push({
|
|
4089
|
+
key: 'og:type',
|
|
4090
|
+
tag: 'meta',
|
|
4091
|
+
attributes: {
|
|
4092
|
+
property: 'og:type',
|
|
4093
|
+
content: og.type
|
|
4094
|
+
}
|
|
4095
|
+
});
|
|
4096
|
+
if (og.title) tags.push({
|
|
4097
|
+
key: 'og:title',
|
|
4098
|
+
tag: 'meta',
|
|
4099
|
+
attributes: {
|
|
4100
|
+
property: 'og:title',
|
|
4101
|
+
content: og.title
|
|
4102
|
+
}
|
|
4103
|
+
});
|
|
4104
|
+
if (og.description) tags.push({
|
|
4105
|
+
key: 'og:desc',
|
|
4106
|
+
tag: 'meta',
|
|
4107
|
+
attributes: {
|
|
4108
|
+
property: 'og:description',
|
|
4109
|
+
content: og.description
|
|
4110
|
+
}
|
|
4111
|
+
});
|
|
4112
|
+
if (og.url) tags.push({
|
|
4113
|
+
key: 'og:url',
|
|
4114
|
+
tag: 'meta',
|
|
4115
|
+
attributes: {
|
|
4116
|
+
property: 'og:url',
|
|
4117
|
+
content: og.url
|
|
4118
|
+
}
|
|
4119
|
+
});
|
|
4120
|
+
if (og.siteName) tags.push({
|
|
4121
|
+
key: 'og:site',
|
|
4122
|
+
tag: 'meta',
|
|
4123
|
+
attributes: {
|
|
4124
|
+
property: 'og:site_name',
|
|
4125
|
+
content: og.siteName
|
|
4126
|
+
}
|
|
4127
|
+
});
|
|
4128
|
+
if (og.locale) tags.push({
|
|
4129
|
+
key: 'og:locale',
|
|
4130
|
+
tag: 'meta',
|
|
4131
|
+
attributes: {
|
|
4132
|
+
property: 'og:locale',
|
|
4133
|
+
content: og.locale
|
|
4134
|
+
}
|
|
4135
|
+
});
|
|
4136
|
+
const images = normalizeOgImages(og.images, og.image);
|
|
4137
|
+
images.forEach((img, i) => {
|
|
4138
|
+
tags.push({
|
|
4139
|
+
key: `og:img:${i}`,
|
|
4140
|
+
tag: 'meta',
|
|
4141
|
+
attributes: {
|
|
4142
|
+
property: 'og:image',
|
|
4143
|
+
content: img.url
|
|
4144
|
+
}
|
|
4145
|
+
});
|
|
4146
|
+
if (img.alt) tags.push({
|
|
4147
|
+
key: `og:img:alt:${i}`,
|
|
4148
|
+
tag: 'meta',
|
|
4149
|
+
attributes: {
|
|
4150
|
+
property: 'og:image:alt',
|
|
4151
|
+
content: img.alt
|
|
4152
|
+
}
|
|
4153
|
+
});
|
|
4154
|
+
if (img.width) tags.push({
|
|
4155
|
+
key: `og:img:w:${i}`,
|
|
4156
|
+
tag: 'meta',
|
|
4157
|
+
attributes: {
|
|
4158
|
+
property: 'og:image:width',
|
|
4159
|
+
content: String(img.width)
|
|
4160
|
+
}
|
|
4161
|
+
});
|
|
4162
|
+
if (img.height) tags.push({
|
|
4163
|
+
key: `og:img:h:${i}`,
|
|
4164
|
+
tag: 'meta',
|
|
4165
|
+
attributes: {
|
|
4166
|
+
property: 'og:image:height',
|
|
4167
|
+
content: String(img.height)
|
|
4168
|
+
}
|
|
4169
|
+
});
|
|
4170
|
+
});
|
|
4171
|
+
}
|
|
4172
|
+
// Twitter
|
|
4173
|
+
if (resolved.twitter) {
|
|
4174
|
+
const tw = resolved.twitter;
|
|
4175
|
+
if (tw.card) tags.push({
|
|
4176
|
+
key: 'tw:card',
|
|
4177
|
+
tag: 'meta',
|
|
4178
|
+
attributes: {
|
|
4179
|
+
name: 'twitter:card',
|
|
4180
|
+
content: tw.card
|
|
4181
|
+
}
|
|
4182
|
+
});
|
|
4183
|
+
if (tw.site) tags.push({
|
|
4184
|
+
key: 'tw:site',
|
|
4185
|
+
tag: 'meta',
|
|
4186
|
+
attributes: {
|
|
4187
|
+
name: 'twitter:site',
|
|
4188
|
+
content: tw.site
|
|
4189
|
+
}
|
|
4190
|
+
});
|
|
4191
|
+
if (tw.creator) tags.push({
|
|
4192
|
+
key: 'tw:creator',
|
|
4193
|
+
tag: 'meta',
|
|
4194
|
+
attributes: {
|
|
4195
|
+
name: 'twitter:creator',
|
|
4196
|
+
content: tw.creator
|
|
4197
|
+
}
|
|
4198
|
+
});
|
|
4199
|
+
if (tw.title) tags.push({
|
|
4200
|
+
key: 'tw:title',
|
|
4201
|
+
tag: 'meta',
|
|
4202
|
+
attributes: {
|
|
4203
|
+
name: 'twitter:title',
|
|
4204
|
+
content: tw.title
|
|
4205
|
+
}
|
|
4206
|
+
});
|
|
4207
|
+
if (tw.description) tags.push({
|
|
4208
|
+
key: 'tw:desc',
|
|
4209
|
+
tag: 'meta',
|
|
4210
|
+
attributes: {
|
|
4211
|
+
name: 'twitter:description',
|
|
4212
|
+
content: tw.description
|
|
4213
|
+
}
|
|
4214
|
+
});
|
|
4215
|
+
if (tw.image) tags.push({
|
|
4216
|
+
key: 'tw:img',
|
|
4217
|
+
tag: 'meta',
|
|
4218
|
+
attributes: {
|
|
4219
|
+
name: 'twitter:image',
|
|
4220
|
+
content: tw.image
|
|
4221
|
+
}
|
|
4222
|
+
});
|
|
4223
|
+
if (tw.imageAlt) tags.push({
|
|
4224
|
+
key: 'tw:img:alt',
|
|
4225
|
+
tag: 'meta',
|
|
4226
|
+
attributes: {
|
|
4227
|
+
name: 'twitter:image:alt',
|
|
4228
|
+
content: tw.imageAlt
|
|
4229
|
+
}
|
|
4230
|
+
});
|
|
4231
|
+
}
|
|
4232
|
+
// Hreflang
|
|
4233
|
+
if ((_b = resolved.alternates) === null || _b === void 0 ? void 0 : _b.languages) {
|
|
4234
|
+
Object.entries(resolved.alternates.languages).forEach(([locale, url]) => {
|
|
4235
|
+
tags.push({
|
|
4236
|
+
key: `hreflang:${locale}`,
|
|
4237
|
+
tag: 'link',
|
|
4238
|
+
attributes: {
|
|
4239
|
+
rel: 'alternate',
|
|
4240
|
+
hreflang: locale,
|
|
4241
|
+
href: url
|
|
4242
|
+
}
|
|
4243
|
+
});
|
|
4244
|
+
});
|
|
4245
|
+
}
|
|
4246
|
+
// Manifest
|
|
4247
|
+
if (resolved.manifest) {
|
|
4248
|
+
tags.push({
|
|
4249
|
+
key: 'manifest',
|
|
4250
|
+
tag: 'link',
|
|
4251
|
+
attributes: {
|
|
4252
|
+
rel: 'manifest',
|
|
4253
|
+
href: resolved.manifest
|
|
4254
|
+
}
|
|
4255
|
+
});
|
|
4256
|
+
}
|
|
4257
|
+
return tags;
|
|
4258
|
+
}
|
|
4259
|
+
// ─── Helpers ─────────────────────────────────────────────────
|
|
4260
|
+
function normalizeOgImages(images, singleImage) {
|
|
4261
|
+
if (images === null || images === void 0 ? void 0 : images.length) return images;
|
|
4262
|
+
if (!singleImage) return [];
|
|
4263
|
+
return [typeof singleImage === 'string' ? {
|
|
4264
|
+
url: singleImage
|
|
4265
|
+
} : singleImage];
|
|
4266
|
+
}/**
|
|
4267
|
+
* Sitemap & Robots.txt Generation Helpers
|
|
4268
|
+
*
|
|
4269
|
+
* Provides functions for generating sitemap.xml and robots.txt content
|
|
4270
|
+
* from page metadata. Useful for:
|
|
4271
|
+
* - Next.js App Router `app/sitemap.ts` and `app/robots.ts`
|
|
4272
|
+
* - Any SSR/SSG framework that needs sitemap generation
|
|
4273
|
+
*
|
|
4274
|
+
* @module integrations/sitemap
|
|
4275
|
+
*/
|
|
4276
|
+
/**
|
|
4277
|
+
* Generate a sitemap.xml string from a list of entries.
|
|
4278
|
+
*
|
|
4279
|
+
* @example
|
|
4280
|
+
* ```ts
|
|
4281
|
+
* // app/sitemap.ts (Next.js App Router)
|
|
4282
|
+
* import { generateSitemapXml } from '@/core/pages/integrations/sitemap';
|
|
4283
|
+
*
|
|
4284
|
+
* export default function sitemap() {
|
|
4285
|
+
* return generateSitemapEntries([
|
|
4286
|
+
* { url: 'https://example.com', changeFrequency: 'daily', priority: 1.0 },
|
|
4287
|
+
* { url: 'https://example.com/about', changeFrequency: 'monthly', priority: 0.8 },
|
|
4288
|
+
* ]);
|
|
4289
|
+
* }
|
|
4290
|
+
* ```
|
|
4291
|
+
*/
|
|
4292
|
+
function generateSitemapXml(entries) {
|
|
4293
|
+
const urls = entries.map(entry => {
|
|
4294
|
+
const parts = [` <loc>${escapeXml(entry.url)}</loc>`];
|
|
4295
|
+
if (entry.lastModified) {
|
|
4296
|
+
const dateStr = entry.lastModified instanceof Date ? entry.lastModified.toISOString() : entry.lastModified;
|
|
4297
|
+
parts.push(` <lastmod>${escapeXml(dateStr)}</lastmod>`);
|
|
4298
|
+
}
|
|
4299
|
+
if (entry.changeFrequency) {
|
|
4300
|
+
parts.push(` <changefreq>${entry.changeFrequency}</changefreq>`);
|
|
4301
|
+
}
|
|
4302
|
+
if (entry.priority != null) {
|
|
4303
|
+
parts.push(` <priority>${entry.priority.toFixed(1)}</priority>`);
|
|
4304
|
+
}
|
|
4305
|
+
// xhtml:link for alternates
|
|
4306
|
+
if (entry.alternates) {
|
|
4307
|
+
Object.entries(entry.alternates).forEach(([lang, href]) => {
|
|
4308
|
+
parts.push(` <xhtml:link rel="alternate" hreflang="${escapeXml(lang)}" href="${escapeXml(href)}" />`);
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4311
|
+
return ` <url>\n${parts.join('\n')}\n </url>`;
|
|
4312
|
+
});
|
|
4313
|
+
return ['<?xml version="1.0" encoding="UTF-8"?>', '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml">', ...urls, '</urlset>'].join('\n');
|
|
4314
|
+
}
|
|
4315
|
+
/**
|
|
4316
|
+
* Generate structured sitemap entries compatible with Next.js App Router `sitemap()`.
|
|
4317
|
+
* Returns plain objects that Next.js can serialize.
|
|
4318
|
+
*/
|
|
4319
|
+
function generateSitemapEntries(entries) {
|
|
4320
|
+
return entries.map(entry => ({
|
|
4321
|
+
url: entry.url,
|
|
4322
|
+
lastModified: entry.lastModified ? entry.lastModified instanceof Date ? entry.lastModified : new Date(entry.lastModified) : undefined,
|
|
4323
|
+
changeFrequency: entry.changeFrequency,
|
|
4324
|
+
priority: entry.priority
|
|
4325
|
+
}));
|
|
4326
|
+
}
|
|
4327
|
+
/**
|
|
4328
|
+
* Generate a robots.txt string from configuration.
|
|
4329
|
+
*
|
|
4330
|
+
* @example
|
|
4331
|
+
* ```ts
|
|
4332
|
+
* // app/robots.ts (Next.js App Router)
|
|
4333
|
+
* import { generateRobotsTxt } from '@/core/pages/integrations/sitemap';
|
|
4334
|
+
*
|
|
4335
|
+
* export default function robots() {
|
|
4336
|
+
* return generateRobotsTxt({
|
|
4337
|
+
* rules: [
|
|
4338
|
+
* { userAgent: '*', allow: ['/'], disallow: ['/admin'] },
|
|
4339
|
+
* { userAgent: 'Googlebot', allow: ['/'] },
|
|
4340
|
+
* ],
|
|
4341
|
+
* sitemap: 'https://example.com/sitemap.xml',
|
|
4342
|
+
* });
|
|
4343
|
+
* }
|
|
4344
|
+
* ```
|
|
4345
|
+
*/
|
|
4346
|
+
function generateRobotsTxt(config) {
|
|
4347
|
+
const lines = [];
|
|
4348
|
+
config.rules.forEach(rule => {
|
|
4349
|
+
var _a, _b;
|
|
4350
|
+
const agents = Array.isArray(rule.userAgent) ? rule.userAgent : [rule.userAgent];
|
|
4351
|
+
agents.forEach(agent => {
|
|
4352
|
+
lines.push(`User-agent: ${agent}`);
|
|
4353
|
+
});
|
|
4354
|
+
(_a = rule.allow) === null || _a === void 0 ? void 0 : _a.forEach(path => {
|
|
4355
|
+
lines.push(`Allow: ${path}`);
|
|
4356
|
+
});
|
|
4357
|
+
(_b = rule.disallow) === null || _b === void 0 ? void 0 : _b.forEach(path => {
|
|
4358
|
+
lines.push(`Disallow: ${path}`);
|
|
4359
|
+
});
|
|
4360
|
+
if (rule.crawlDelay != null) {
|
|
4361
|
+
lines.push(`Crawl-delay: ${rule.crawlDelay}`);
|
|
4362
|
+
}
|
|
4363
|
+
lines.push('');
|
|
4364
|
+
});
|
|
4365
|
+
// Sitemap
|
|
4366
|
+
const sitemaps = config.sitemap ? Array.isArray(config.sitemap) ? config.sitemap : [config.sitemap] : [];
|
|
4367
|
+
sitemaps.forEach(url => {
|
|
4368
|
+
lines.push(`Sitemap: ${url}`);
|
|
4369
|
+
});
|
|
4370
|
+
// Host
|
|
4371
|
+
if (config.host) {
|
|
4372
|
+
lines.push(`Host: ${config.host}`);
|
|
4373
|
+
}
|
|
4374
|
+
return lines.join('\n');
|
|
4375
|
+
}
|
|
4376
|
+
// ─── Helpers ─────────────────────────────────────────────────
|
|
4377
|
+
function escapeXml(str) {
|
|
4378
|
+
return str.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
|
|
4379
|
+
}/**
|
|
4380
|
+
* JSON-LD Structured Data Builders
|
|
4381
|
+
*
|
|
4382
|
+
* Helpers to build valid schema.org JSON-LD objects for common types.
|
|
4383
|
+
* These can be passed to MetadataConfig.structuredData.schema or used
|
|
4384
|
+
* directly in a <script type="application/ld+json"> tag.
|
|
4385
|
+
*
|
|
4386
|
+
* @module integrations/jsonld
|
|
4387
|
+
*/
|
|
4388
|
+
function buildOrganizationJsonLd(input) {
|
|
4389
|
+
var _a;
|
|
4390
|
+
const schema = {
|
|
4391
|
+
'@context': 'https://schema.org',
|
|
4392
|
+
'@type': 'Organization',
|
|
4393
|
+
name: input.name,
|
|
4394
|
+
url: input.url
|
|
4395
|
+
};
|
|
4396
|
+
if (input.logo) schema.logo = input.logo;
|
|
4397
|
+
if (input.description) schema.description = input.description;
|
|
4398
|
+
if ((_a = input.sameAs) === null || _a === void 0 ? void 0 : _a.length) schema.sameAs = input.sameAs;
|
|
4399
|
+
if (input.contactPoint) {
|
|
4400
|
+
const cp = {
|
|
4401
|
+
'@type': 'ContactPoint'
|
|
4402
|
+
};
|
|
4403
|
+
if (input.contactPoint.telephone) cp.telephone = input.contactPoint.telephone;
|
|
4404
|
+
if (input.contactPoint.contactType) cp.contactType = input.contactPoint.contactType;
|
|
4405
|
+
if (input.contactPoint.email) cp.email = input.contactPoint.email;
|
|
4406
|
+
if (input.contactPoint.areaServed) cp.areaServed = input.contactPoint.areaServed;
|
|
4407
|
+
if (input.contactPoint.availableLanguage) cp.availableLanguage = input.contactPoint.availableLanguage;
|
|
4408
|
+
schema.contactPoint = cp;
|
|
4409
|
+
}
|
|
4410
|
+
return schema;
|
|
4411
|
+
}
|
|
4412
|
+
function buildWebSiteJsonLd(input) {
|
|
4413
|
+
const schema = {
|
|
4414
|
+
'@context': 'https://schema.org',
|
|
4415
|
+
'@type': 'WebSite',
|
|
4416
|
+
name: input.name,
|
|
4417
|
+
url: input.url
|
|
4418
|
+
};
|
|
4419
|
+
if (input.description) schema.description = input.description;
|
|
4420
|
+
if (input.potentialAction) {
|
|
4421
|
+
schema.potentialAction = {
|
|
4422
|
+
'@type': 'SearchAction',
|
|
4423
|
+
target: input.potentialAction.target,
|
|
4424
|
+
'query-input': input.potentialAction.queryInput
|
|
4425
|
+
};
|
|
4426
|
+
}
|
|
4427
|
+
return schema;
|
|
4428
|
+
}
|
|
4429
|
+
function buildBreadcrumbListJsonLd(items) {
|
|
4430
|
+
return {
|
|
4431
|
+
'@context': 'https://schema.org',
|
|
4432
|
+
'@type': 'BreadcrumbList',
|
|
4433
|
+
itemListElement: items.map((item, index) => ({
|
|
4434
|
+
'@type': 'ListItem',
|
|
4435
|
+
position: index + 1,
|
|
4436
|
+
name: item.name,
|
|
4437
|
+
item: item.url
|
|
4438
|
+
}))
|
|
4439
|
+
};
|
|
4440
|
+
}
|
|
4441
|
+
function buildArticleJsonLd(input) {
|
|
4442
|
+
const schema = {
|
|
4443
|
+
'@context': 'https://schema.org',
|
|
4444
|
+
'@type': 'Article',
|
|
4445
|
+
headline: input.headline
|
|
4446
|
+
};
|
|
4447
|
+
if (input.description) schema.description = input.description;
|
|
4448
|
+
if (input.image) {
|
|
4449
|
+
schema.image = Array.isArray(input.image) ? input.image : [input.image];
|
|
4450
|
+
}
|
|
4451
|
+
if (input.datePublished) schema.datePublished = input.datePublished;
|
|
4452
|
+
if (input.dateModified) schema.dateModified = input.dateModified;
|
|
4453
|
+
if (input.author) {
|
|
4454
|
+
const authors = Array.isArray(input.author) ? input.author : [input.author];
|
|
4455
|
+
schema.author = authors.map(a => Object.assign({
|
|
4456
|
+
'@type': 'Person',
|
|
4457
|
+
name: a.name
|
|
4458
|
+
}, a.url ? {
|
|
4459
|
+
url: a.url
|
|
4460
|
+
} : {}));
|
|
4461
|
+
}
|
|
4462
|
+
if (input.publisher) {
|
|
4463
|
+
const pub = {
|
|
4464
|
+
'@type': 'Organization',
|
|
4465
|
+
name: input.publisher.name
|
|
4466
|
+
};
|
|
4467
|
+
if (input.publisher.logo) {
|
|
4468
|
+
pub.logo = {
|
|
4469
|
+
'@type': 'ImageObject',
|
|
4470
|
+
url: input.publisher.logo
|
|
4471
|
+
};
|
|
4472
|
+
}
|
|
4473
|
+
schema.publisher = pub;
|
|
4474
|
+
}
|
|
4475
|
+
if (input.url) schema.url = input.url;
|
|
4476
|
+
if (input.mainEntityOfPage) {
|
|
4477
|
+
schema.mainEntityOfPage = {
|
|
4478
|
+
'@type': 'WebPage',
|
|
4479
|
+
'@id': input.mainEntityOfPage
|
|
4480
|
+
};
|
|
4481
|
+
}
|
|
4482
|
+
return schema;
|
|
4483
|
+
}
|
|
4484
|
+
function buildFAQPageJsonLd(items) {
|
|
4485
|
+
return {
|
|
4486
|
+
'@context': 'https://schema.org',
|
|
4487
|
+
'@type': 'FAQPage',
|
|
4488
|
+
mainEntity: items.map(item => ({
|
|
4489
|
+
'@type': 'Question',
|
|
4490
|
+
name: item.question,
|
|
4491
|
+
acceptedAnswer: {
|
|
4492
|
+
'@type': 'Answer',
|
|
4493
|
+
text: item.answer
|
|
4494
|
+
}
|
|
4495
|
+
}))
|
|
4496
|
+
};
|
|
4497
|
+
}
|
|
4498
|
+
function buildProductJsonLd(input) {
|
|
4499
|
+
const schema = {
|
|
4500
|
+
'@context': 'https://schema.org',
|
|
4501
|
+
'@type': 'Product',
|
|
4502
|
+
name: input.name
|
|
4503
|
+
};
|
|
4504
|
+
if (input.description) schema.description = input.description;
|
|
4505
|
+
if (input.image) {
|
|
4506
|
+
schema.image = Array.isArray(input.image) ? input.image : [input.image];
|
|
4507
|
+
}
|
|
4508
|
+
if (input.brand) {
|
|
4509
|
+
schema.brand = {
|
|
4510
|
+
'@type': 'Brand',
|
|
4511
|
+
name: input.brand
|
|
4512
|
+
};
|
|
4513
|
+
}
|
|
4514
|
+
if (input.sku) schema.sku = input.sku;
|
|
4515
|
+
if (input.offers) {
|
|
4516
|
+
const offer = {
|
|
4517
|
+
'@type': 'Offer',
|
|
4518
|
+
price: input.offers.price,
|
|
4519
|
+
priceCurrency: input.offers.priceCurrency
|
|
4520
|
+
};
|
|
4521
|
+
if (input.offers.availability) {
|
|
4522
|
+
offer.availability = `https://schema.org/${input.offers.availability}`;
|
|
4523
|
+
}
|
|
4524
|
+
if (input.offers.url) offer.url = input.offers.url;
|
|
4525
|
+
if (input.offers.priceValidUntil) offer.priceValidUntil = input.offers.priceValidUntil;
|
|
4526
|
+
schema.offers = offer;
|
|
4527
|
+
}
|
|
4528
|
+
if (input.aggregateRating) {
|
|
4529
|
+
const rating = {
|
|
4530
|
+
'@type': 'AggregateRating',
|
|
4531
|
+
ratingValue: input.aggregateRating.ratingValue,
|
|
4532
|
+
reviewCount: input.aggregateRating.reviewCount
|
|
4533
|
+
};
|
|
4534
|
+
if (input.aggregateRating.bestRating != null) rating.bestRating = input.aggregateRating.bestRating;
|
|
4535
|
+
if (input.aggregateRating.worstRating != null) rating.worstRating = input.aggregateRating.worstRating;
|
|
4536
|
+
schema.aggregateRating = rating;
|
|
4537
|
+
}
|
|
4538
|
+
return schema;
|
|
4539
|
+
}/**
|
|
4540
|
+
* LLMs.txt Generation Support
|
|
4541
|
+
*
|
|
4542
|
+
* Generates `llms.txt` and `llms-full.txt` content following the
|
|
4543
|
+
* llms.txt specification (https://llmstxt.org/).
|
|
4544
|
+
*
|
|
4545
|
+
* The llms.txt file helps LLMs and AI agents discover what a site offers
|
|
4546
|
+
* and where to find key documentation/content.
|
|
4547
|
+
*
|
|
4548
|
+
* @module integrations/llms
|
|
4549
|
+
*/
|
|
4550
|
+
/**
|
|
4551
|
+
* Generate llms.txt content from configuration.
|
|
4552
|
+
*
|
|
4553
|
+
* Format (per spec):
|
|
4554
|
+
* ```
|
|
4555
|
+
* # Site Name
|
|
4556
|
+
*
|
|
4557
|
+
* > Brief description of the site
|
|
4558
|
+
*
|
|
4559
|
+
* ## Docs
|
|
4560
|
+
*
|
|
4561
|
+
* - [Title](url): Description
|
|
4562
|
+
* - [Title](url): Description
|
|
4563
|
+
* ```
|
|
4564
|
+
*
|
|
4565
|
+
* @example
|
|
4566
|
+
* ```ts
|
|
4567
|
+
* const content = generateLlmsTxt({
|
|
4568
|
+
* siteName: 'My App',
|
|
4569
|
+
* siteDescription: 'A great application for doing things.',
|
|
4570
|
+
* entries: [
|
|
4571
|
+
* { url: '/docs/getting-started', title: 'Getting Started', description: 'How to set up My App' },
|
|
4572
|
+
* { url: '/docs/api', title: 'API Reference', description: 'Complete API documentation' },
|
|
4573
|
+
* ],
|
|
4574
|
+
* });
|
|
4575
|
+
* // Write `content` to /llms.txt
|
|
4576
|
+
* ```
|
|
4577
|
+
*/
|
|
4578
|
+
function generateLlmsTxt(config) {
|
|
4579
|
+
const lines = [];
|
|
4580
|
+
// Header
|
|
4581
|
+
lines.push(`# ${config.siteName}`);
|
|
4582
|
+
lines.push('');
|
|
4583
|
+
// Description
|
|
4584
|
+
if (config.siteDescription) {
|
|
4585
|
+
lines.push(`> ${config.siteDescription}`);
|
|
4586
|
+
lines.push('');
|
|
4587
|
+
}
|
|
4588
|
+
// Entries grouped under "Docs"
|
|
4589
|
+
if (config.entries.length > 0) {
|
|
4590
|
+
lines.push('## Docs');
|
|
4591
|
+
lines.push('');
|
|
4592
|
+
config.entries.forEach(entry => {
|
|
4593
|
+
const desc = entry.description ? `: ${entry.description}` : '';
|
|
4594
|
+
lines.push(`- [${entry.title}](${entry.url})${desc}`);
|
|
4595
|
+
});
|
|
4596
|
+
lines.push('');
|
|
4597
|
+
}
|
|
4598
|
+
return lines.join('\n');
|
|
4599
|
+
}
|
|
4600
|
+
/**
|
|
4601
|
+
* Generate a full markdown version (llms-full.txt) that includes
|
|
4602
|
+
* more detailed content for each entry.
|
|
4603
|
+
*
|
|
4604
|
+
* This is useful for providing LLMs with the complete documentation
|
|
4605
|
+
* in a single file.
|
|
4606
|
+
*/
|
|
4607
|
+
function generateLlmsFullTxt(config, pageContents) {
|
|
4608
|
+
const lines = [];
|
|
4609
|
+
lines.push(`# ${config.siteName}`);
|
|
4610
|
+
lines.push('');
|
|
4611
|
+
if (config.siteDescription) {
|
|
4612
|
+
lines.push(`> ${config.siteDescription}`);
|
|
4613
|
+
lines.push('');
|
|
4614
|
+
}
|
|
4615
|
+
pageContents.forEach(({
|
|
4616
|
+
entry,
|
|
4617
|
+
markdown
|
|
4618
|
+
}) => {
|
|
4619
|
+
lines.push(`## ${entry.title}`);
|
|
4620
|
+
lines.push('');
|
|
4621
|
+
if (entry.description) {
|
|
4622
|
+
lines.push(`> ${entry.description}`);
|
|
4623
|
+
lines.push('');
|
|
4624
|
+
}
|
|
4625
|
+
lines.push(`Source: ${entry.url}`);
|
|
4626
|
+
lines.push('');
|
|
4627
|
+
lines.push(markdown);
|
|
4628
|
+
lines.push('');
|
|
4629
|
+
lines.push('---');
|
|
4630
|
+
lines.push('');
|
|
4631
|
+
});
|
|
4632
|
+
return lines.join('\n');
|
|
4633
|
+
}
|
|
4634
|
+
/**
|
|
4635
|
+
* Helper to convert a ResolvedMetadata + page text into a clean markdown
|
|
4636
|
+
* representation suitable for llms-full.txt or standalone .md endpoints.
|
|
4637
|
+
*
|
|
4638
|
+
* Strips HTML chrome, keeps headings coherent, and prepends metadata summary.
|
|
4639
|
+
*/
|
|
4640
|
+
function pageToMarkdown(options) {
|
|
4641
|
+
const lines = [];
|
|
4642
|
+
lines.push(`# ${options.title}`);
|
|
4643
|
+
lines.push('');
|
|
4644
|
+
if (options.description) {
|
|
4645
|
+
lines.push(options.description);
|
|
4646
|
+
lines.push('');
|
|
4647
|
+
}
|
|
4648
|
+
lines.push(`URL: ${options.url}`);
|
|
4649
|
+
lines.push('');
|
|
4650
|
+
lines.push(options.content);
|
|
4651
|
+
return lines.join('\n');
|
|
4652
|
+
}exports.MemoizationCache=MemoizationCache;exports.MetadataStoreProvider=MetadataStoreProvider;exports.PageGenerator=PageGenerator;exports.RenderComponents=RenderComponents;exports.applyMetadataToDom=applyMetadataToDom;exports.buildArticleJsonLd=buildArticleJsonLd;exports.buildBreadcrumbListJsonLd=buildBreadcrumbListJsonLd;exports.buildFAQPageJsonLd=buildFAQPageJsonLd;exports.buildOrganizationJsonLd=buildOrganizationJsonLd;exports.buildProductJsonLd=buildProductJsonLd;exports.buildWebSiteJsonLd=buildWebSiteJsonLd;exports.clearMetadataLog=clearMetadataLog;exports.collectMetadataToHtml=collectMetadataToHtml;exports.createMetadataStore=createMetadataStore;exports.createScopePageVariablesAtom=createScopePageVariablesAtom;exports.deepEqual=deepEqual;exports.generateLlmsFullTxt=generateLlmsFullTxt;exports.generateLlmsTxt=generateLlmsTxt;exports.generateRobotsTxt=generateRobotsTxt;exports.generateSitemapEntries=generateSitemapEntries;exports.generateSitemapXml=generateSitemapXml;exports.getMetadata=getMetadata;exports.getMetadataLog=getMetadataLog;exports.getPageConfig=getPageConfig;exports.getPageVariablesCompositeKey=getPageVariablesCompositeKey;exports.isStableValue=isStableValue;exports.logMetadata=logMetadata;exports.memoPropsComparator=memoPropsComparator;exports.memoize=memoize;exports.optimizeDeps=optimizeDeps;exports.pageConfigAtom=pageConfigAtom;exports.pageToMarkdown=pageToMarkdown;exports.pageVariablesAtom=pageVariablesAtom;exports.pageVariablesAtomFamily=pageVariablesAtomFamily;exports.resetMetadata=resetMetadata;exports.resolveMetadata=resolveMetadata;exports.setMetadata=setMetadata;exports.setMetadataLogging=setMetadataLogging;exports.shallowEqual=shallowEqual;exports.toNextHeadTags=toNextHeadTags;exports.toNextMetadata=toNextMetadata;exports.useApplyMetadata=useApplyMetadata;exports.useFormData=useFormData;exports.useGenerateContent=useGenerateContent;exports.useGenerateContentRender=useGenerateContentRender;exports.useMetadata=useMetadata;exports.useMetadataStore=useMetadataStore;exports.usePageConfig=usePageConfig;exports.usePageConfigReset=usePageConfigReset;exports.usePageConfigState=usePageConfigState;exports.usePageConfigValue=usePageConfigValue;exports.useViewSettings=useViewSettings;//# sourceMappingURL=index.js.map
|