@askrjs/askr 0.0.36 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +17 -9
  2. package/dist/bench/components/benchmark-table.js +1 -1
  3. package/dist/bench/components/benchmark-table.js.map +1 -1
  4. package/dist/benchmark.js +3 -3
  5. package/dist/boot/index.d.ts +1 -7
  6. package/dist/boot/index.d.ts.map +1 -1
  7. package/dist/boot/index.js +22 -13
  8. package/dist/boot/index.js.map +1 -1
  9. package/dist/components/index.d.ts +2 -0
  10. package/dist/components/index.js +2 -0
  11. package/dist/components/link.d.ts +4 -5
  12. package/dist/components/link.d.ts.map +1 -1
  13. package/dist/components/link.js +2 -1
  14. package/dist/components/link.js.map +1 -1
  15. package/dist/foundations/icon/icon.d.ts.map +1 -1
  16. package/dist/foundations/icon/icon.js.map +1 -1
  17. package/dist/foundations/icon/icon.types.d.ts +2 -1
  18. package/dist/foundations/icon/icon.types.d.ts.map +1 -1
  19. package/dist/foundations/icon/index.d.ts +3 -0
  20. package/dist/foundations/icon/index.js +2 -0
  21. package/dist/foundations/index.d.ts +1 -18
  22. package/dist/foundations/index.js +2 -18
  23. package/dist/foundations/interactions/index.d.ts +7 -0
  24. package/dist/foundations/interactions/index.js +7 -0
  25. package/dist/foundations/interactions/interaction-policy.js +2 -2
  26. package/dist/foundations/state/index.d.ts +2 -0
  27. package/dist/foundations/state/index.js +2 -0
  28. package/dist/foundations/structures/index.d.ts +8 -0
  29. package/dist/foundations/structures/index.js +7 -0
  30. package/dist/foundations/utilities/index.d.ts +7 -0
  31. package/dist/foundations/utilities/index.js +6 -0
  32. package/dist/index.d.ts +2 -16
  33. package/dist/index.js +1 -17
  34. package/dist/index.js.map +1 -1
  35. package/dist/jsx-dev-runtime.d.ts +1 -1
  36. package/dist/jsx-dev-runtime.js.map +1 -1
  37. package/dist/jsx-runtime.d.ts +1 -1
  38. package/dist/jsx-runtime.js.map +1 -1
  39. package/dist/renderer/dom.js +26 -366
  40. package/dist/renderer/dom.js.map +1 -1
  41. package/dist/renderer/evaluate.js.map +1 -1
  42. package/dist/renderer/fastpath.js +20 -18
  43. package/dist/renderer/fastpath.js.map +1 -1
  44. package/dist/renderer/for-commit.js +486 -0
  45. package/dist/renderer/for-commit.js.map +1 -0
  46. package/dist/renderer/index.js.map +1 -1
  47. package/dist/renderer/keyed.js +84 -23
  48. package/dist/renderer/keyed.js.map +1 -1
  49. package/dist/renderer/reconcile.js +11 -18
  50. package/dist/renderer/reconcile.js.map +1 -1
  51. package/dist/renderer/utils.js +5 -1
  52. package/dist/renderer/utils.js.map +1 -1
  53. package/dist/resources/index.d.ts +1 -2
  54. package/dist/resources/index.js +1 -2
  55. package/dist/router/route.js +1 -1
  56. package/dist/runtime/for.d.ts.map +1 -1
  57. package/dist/runtime/for.js +33 -21
  58. package/dist/runtime/for.js.map +1 -1
  59. package/dist/runtime/operations.js +1 -1
  60. package/dist/runtime/selector.d.ts.map +1 -1
  61. package/dist/runtime/selector.js +180 -103
  62. package/dist/runtime/selector.js.map +1 -1
  63. package/dist/ssg/index.d.ts +1 -6
  64. package/dist/ssg/index.js +1 -6
  65. package/dist/ssr/context.d.ts +2 -1
  66. package/dist/ssr/context.d.ts.map +1 -1
  67. package/dist/ssr/context.js +28 -11
  68. package/dist/ssr/context.js.map +1 -1
  69. package/dist/ssr/index.d.ts +2 -31
  70. package/dist/ssr/index.d.ts.map +1 -1
  71. package/dist/ssr/index.js +4 -46
  72. package/dist/ssr/index.js.map +1 -1
  73. package/dist/ssr/render-keys.js +1 -12
  74. package/dist/ssr/render-keys.js.map +1 -1
  75. package/dist/ssr/verify-hydration.js +25 -0
  76. package/dist/ssr/verify-hydration.js.map +1 -0
  77. package/package.json +39 -16
  78. package/dist/_virtual/_rolldown/runtime.js +0 -7
  79. package/dist/foundations/core.d.ts +0 -15
  80. package/dist/foundations/core.js +0 -13
  81. package/dist/foundations/structures.d.ts +0 -7
  82. package/dist/foundations/structures.js +0 -6
  83. package/dist/ssg/batch-render.d.ts +0 -16
  84. package/dist/ssg/batch-render.d.ts.map +0 -1
  85. package/dist/ssg/generate-metadata.d.ts +0 -24
  86. package/dist/ssg/generate-metadata.d.ts.map +0 -1
  87. package/dist/ssg/resolve-ssg-data.d.ts +0 -23
  88. package/dist/ssg/resolve-ssg-data.d.ts.map +0 -1
  89. package/dist/ssg/route-utils.d.ts +0 -16
  90. package/dist/ssg/route-utils.d.ts.map +0 -1
  91. package/dist/ssg/write-static-files.d.ts +0 -15
  92. package/dist/ssg/write-static-files.d.ts.map +0 -1
  93. package/dist/ssr/render-keys.d.ts +0 -37
  94. package/dist/ssr/render-keys.d.ts.map +0 -1
  95. package/dist/ssr/stream-render.js +0 -88
  96. package/dist/ssr/stream-render.js.map +0 -1
@@ -4,7 +4,8 @@ import { clearDerivedDependencySubscriptions, markReactivePropsDirtySource, mark
4
4
  import { claimHookIndex, getCurrentInstance } from "./component.js";
5
5
  //#region src/runtime/selector.ts
6
6
  const selectorCells = /* @__PURE__ */ new WeakMap();
7
- const dirtySelectorCells = /* @__PURE__ */ new Set();
7
+ const selectorRecords = /* @__PURE__ */ new WeakMap();
8
+ const dirtySelectorRecords = /* @__PURE__ */ new Set();
8
9
  let hasPendingSelectorFlush = false;
9
10
  function getSelectorStore(instance) {
10
11
  let store = selectorCells.get(instance);
@@ -17,24 +18,24 @@ function getSelectorStore(instance) {
17
18
  function scheduleSelectorFlush() {
18
19
  if (hasPendingSelectorFlush) return;
19
20
  hasPendingSelectorFlush = true;
20
- globalScheduler.enqueueInLane("derived", flushDirtySelectorCells);
21
+ globalScheduler.enqueueInLane("derived", flushDirtySelectorRecords);
21
22
  }
22
- function markSelectorCellDirty(cell) {
23
- cell._dirty = true;
24
- if (cell._scheduled) return;
25
- cell._scheduled = true;
26
- dirtySelectorCells.add(cell);
23
+ function markSelectorRecordDirty(record) {
24
+ record._dirty = true;
25
+ if (record._scheduled) return;
26
+ record._scheduled = true;
27
+ dirtySelectorRecords.add(record);
27
28
  scheduleSelectorFlush();
28
29
  }
29
- function flushDirtySelectorCells() {
30
+ function flushDirtySelectorRecords() {
30
31
  hasPendingSelectorFlush = false;
31
- if (dirtySelectorCells.size === 0) return;
32
- const pending = Array.from(dirtySelectorCells);
33
- dirtySelectorCells.clear();
34
- for (const cell of pending) {
35
- cell._scheduled = false;
36
- if (!cell._dirty) continue;
37
- recomputeSelectorCell(cell, true);
32
+ if (dirtySelectorRecords.size === 0) return;
33
+ const pending = Array.from(dirtySelectorRecords);
34
+ dirtySelectorRecords.clear();
35
+ for (const record of pending) {
36
+ record._scheduled = false;
37
+ if (!record._dirty) continue;
38
+ recomputeSelectorSourceRecord(record, true);
38
39
  }
39
40
  }
40
41
  function isObjectCandidate(value) {
@@ -48,131 +49,206 @@ function createCandidateSource(candidate) {
48
49
  source._candidate = candidate;
49
50
  return source;
50
51
  }
51
- function getCandidateSource(cell, candidate) {
52
+ function getCandidateSource(lane, candidate) {
52
53
  if (isObjectCandidate(candidate)) {
53
- const cached = cell._objectCandidates.get(candidate);
54
+ const cached = lane._objectCandidates.get(candidate);
54
55
  if (cached) return cached;
55
56
  const created = createCandidateSource(candidate);
56
- created._candidate = candidate;
57
- cell._objectCandidates.set(candidate, created);
58
- cell._objectCandidateSources.add(created);
57
+ lane._objectCandidates.set(candidate, created);
58
+ lane._objectCandidateSources.add(created);
59
59
  return created;
60
60
  }
61
61
  const key = candidate;
62
- const cached = cell._primitiveCandidates.get(key);
62
+ const cached = lane._primitiveCandidates.get(key);
63
63
  if (cached) return cached;
64
64
  const created = createCandidateSource(candidate);
65
- created._candidate = candidate;
66
- cell._primitiveCandidates.set(key, created);
65
+ lane._primitiveCandidates.set(key, created);
67
66
  return created;
68
67
  }
68
+ function getSelectorSourceRecord(source) {
69
+ const cached = selectorRecords.get(source);
70
+ if (cached) return cached;
71
+ const record = createSelectorSourceRecord(source);
72
+ selectorRecords.set(source, record);
73
+ return record;
74
+ }
75
+ function createSelectorSourceRecord(source) {
76
+ let record;
77
+ record = {
78
+ _source: source,
79
+ _value: void 0,
80
+ _hasValue: false,
81
+ _dirty: true,
82
+ _scheduled: false,
83
+ _evaluating: false,
84
+ _sources: /* @__PURE__ */ new Set(),
85
+ _lanes: /* @__PURE__ */ new Map(),
86
+ _markDirty: () => {
87
+ markSelectorRecordDirty(record);
88
+ },
89
+ _cleanup: () => {
90
+ record._scheduled = false;
91
+ record._dirty = false;
92
+ record._hasValue = false;
93
+ record._evaluating = false;
94
+ record._pendingDependencySources = void 0;
95
+ clearDerivedDependencySubscriptions(record, record._sources);
96
+ record._lanes.clear();
97
+ selectorRecords.delete(source);
98
+ }
99
+ };
100
+ return record;
101
+ }
102
+ function getSelectorLane(record, equals) {
103
+ const cached = record._lanes.get(equals);
104
+ if (cached) return cached;
105
+ const lane = createSelectorLane(record, equals);
106
+ record._lanes.set(equals, lane);
107
+ return lane;
108
+ }
109
+ function createSelectorLane(record, equals) {
110
+ const lane = {
111
+ _record: record,
112
+ _equals: equals,
113
+ _bindingCount: 0,
114
+ _primitiveCandidates: /* @__PURE__ */ new Map(),
115
+ _objectCandidates: /* @__PURE__ */ new WeakMap(),
116
+ _objectCandidateSources: /* @__PURE__ */ new Set(),
117
+ _cleanup: () => {
118
+ for (const sourceRef of lane._primitiveCandidates.values()) {
119
+ sourceRef._readers?.clear();
120
+ sourceRef._derivedSubscribers?.clear();
121
+ }
122
+ for (const sourceRef of lane._objectCandidateSources) {
123
+ sourceRef._readers?.clear();
124
+ sourceRef._derivedSubscribers?.clear();
125
+ }
126
+ lane._primitiveCandidates.clear();
127
+ lane._objectCandidates = /* @__PURE__ */ new WeakMap();
128
+ lane._objectCandidateSources.clear();
129
+ }
130
+ };
131
+ return lane;
132
+ }
69
133
  function notifySelectorSource(source) {
70
134
  incrementPerfMetric("selectorInvalidations");
71
135
  markReadableDerivedSubscribersDirty(source);
72
136
  markReactivePropsDirtySource(source);
73
137
  notifyReadableReaders(source);
74
138
  }
75
- function notifyAllSelectorSources(cell) {
76
- for (const source of cell._primitiveCandidates.values()) notifySelectorSource(source);
77
- for (const source of cell._objectCandidateSources) notifySelectorSource(source);
139
+ function notifyAllSelectorSources(lane) {
140
+ for (const source of lane._primitiveCandidates.values()) notifySelectorSource(source);
141
+ for (const source of lane._objectCandidateSources) notifySelectorSource(source);
78
142
  }
79
- function notifySelectorValueChange(cell, prevValue, nextValue) {
80
- if (!isDefaultSelectorEquals(cell._equals)) {
81
- notifyAllSelectorSources(cell);
143
+ function notifySelectorLaneValueChange(lane, prevValue, nextValue) {
144
+ if (!lane._bindingCount) return;
145
+ if (!isDefaultSelectorEquals(lane._equals)) {
146
+ if (lane._equals(prevValue, nextValue)) return;
147
+ notifyAllSelectorSources(lane);
82
148
  return;
83
149
  }
84
150
  if (!Object.is(prevValue, nextValue)) {
85
- notifySelectorSource(getCandidateSource(cell, prevValue));
86
- notifySelectorSource(getCandidateSource(cell, nextValue));
151
+ notifySelectorSource(getCandidateSource(lane, prevValue));
152
+ notifySelectorSource(getCandidateSource(lane, nextValue));
87
153
  }
88
154
  }
89
- function recomputeSelectorCell(cell, notifyDownstream) {
90
- if (!cell._dirty && cell._hasValue) return cell._value;
91
- if (cell._evaluating) throw new Error("selector() cannot read itself recursively");
92
- cell._evaluating = true;
93
- cell._dirty = false;
94
- cell._pendingDependencySources = /* @__PURE__ */ new Set();
95
- const prevSources = cell._sources;
96
- const hadValue = cell._hasValue;
97
- const prevValue = cell._value;
155
+ function recomputeSelectorSourceRecord(record, notifyDownstream) {
156
+ if (!record._dirty && record._hasValue) return record._value;
157
+ if (record._evaluating) throw new Error("selector() cannot read itself recursively");
158
+ record._evaluating = true;
159
+ record._dirty = false;
160
+ record._pendingDependencySources = /* @__PURE__ */ new Set();
161
+ const prevSources = record._sources;
162
+ const hadValue = record._hasValue;
163
+ const prevValue = record._value;
98
164
  let nextValue;
99
165
  try {
100
- nextValue = withDerivedReadTracking(cell, cell._source);
166
+ nextValue = withDerivedReadTracking(record, record._source);
101
167
  } catch (error) {
102
- cell._dirty = true;
103
- cell._pendingDependencySources = void 0;
168
+ record._dirty = true;
169
+ record._pendingDependencySources = void 0;
104
170
  throw error;
105
171
  } finally {
106
- cell._evaluating = false;
172
+ record._evaluating = false;
107
173
  }
108
- const nextSources = cell._pendingDependencySources ?? /* @__PURE__ */ new Set();
109
- cell._pendingDependencySources = void 0;
110
- syncDerivedDependencySubscriptions(cell, prevSources, nextSources);
111
- cell._sources = nextSources;
112
- const valueChanged = !cell._hasValue || !cell._equals(prevValue, nextValue);
113
- cell._hasValue = true;
114
- cell._value = nextValue;
115
- if (valueChanged && notifyDownstream && hadValue) notifySelectorValueChange(cell, prevValue, nextValue);
116
- return cell._value;
117
- }
118
- function createSelectorCell(instance, hookIndex, source, equals) {
119
- const perfMetricsStore = getPerfMetricsStore();
120
- const cell = function selectorPredicate(candidate) {
121
- recordReadableRead(getCandidateSource(cell, candidate));
174
+ const nextSources = record._pendingDependencySources ?? /* @__PURE__ */ new Set();
175
+ record._pendingDependencySources = void 0;
176
+ syncDerivedDependencySubscriptions(record, prevSources, nextSources);
177
+ record._sources = nextSources;
178
+ const valueChanged = !record._hasValue || !Object.is(prevValue, nextValue);
179
+ record._hasValue = true;
180
+ record._value = nextValue;
181
+ if (valueChanged && notifyDownstream && hadValue) for (const lane of Array.from(record._lanes.values())) notifySelectorLaneValueChange(lane, prevValue, nextValue);
182
+ return record._value;
183
+ }
184
+ function attachSelectorHookBinding(hook, source, equals) {
185
+ const record = getSelectorSourceRecord(source);
186
+ const lane = getSelectorLane(record, equals);
187
+ hook._source = source;
188
+ hook._equals = equals;
189
+ hook._record = record;
190
+ hook._lane = lane;
191
+ lane._bindingCount += 1;
192
+ }
193
+ function detachSelectorHookBinding(hook) {
194
+ const record = hook._record;
195
+ const lane = hook._lane;
196
+ hook._record = null;
197
+ hook._lane = null;
198
+ if (!record || !lane) return;
199
+ if (lane._bindingCount > 0) lane._bindingCount -= 1;
200
+ if (lane._bindingCount > 0) return;
201
+ lane._cleanup();
202
+ record._lanes.delete(lane._equals);
203
+ if (record._lanes.size === 0) record._cleanup();
204
+ }
205
+ function ensureSelectorHookBinding(hook) {
206
+ const record = hook._record;
207
+ const lane = hook._lane;
208
+ if (record && lane && lane._bindingCount > 0 && record._lanes.get(hook._equals) === lane && record._source === hook._source) return record;
209
+ if (hook._record || hook._lane) detachSelectorHookBinding(hook);
210
+ attachSelectorHookBinding(hook, hook._source, hook._equals);
211
+ return hook._record;
212
+ }
213
+ function createSelectorHook(instance, hookIndex, source, equals) {
214
+ const hook = function selectorPredicate(candidate) {
215
+ const selectorHook = hook;
216
+ const record = ensureSelectorHookBinding(selectorHook);
217
+ const lane = selectorHook._lane;
218
+ if (!lane) throw new Error("selector() binding could not be established.");
219
+ recordReadableRead(getCandidateSource(lane, candidate));
220
+ const perfMetricsStore = getPerfMetricsStore();
122
221
  if (perfMetricsStore) perfMetricsStore.selectorCandidateReads += 1;
123
- const selectorCell = cell;
124
- const current = selectorCell._dirty || !selectorCell._hasValue ? recomputeSelectorCell(selectorCell, selectorCell._scheduled) : selectorCell._value;
125
- return selectorCell._equals(current, candidate);
126
- };
127
- cell._owner = instance;
128
- cell._hookIndex = hookIndex;
129
- cell._source = source;
130
- cell._equals = equals;
131
- cell._value = void 0;
132
- cell._hasValue = false;
133
- cell._dirty = true;
134
- cell._scheduled = false;
135
- cell._evaluating = false;
136
- cell._sources = /* @__PURE__ */ new Set();
137
- cell._primitiveCandidates = /* @__PURE__ */ new Map();
138
- cell._objectCandidates = /* @__PURE__ */ new WeakMap();
139
- cell._objectCandidateSources = /* @__PURE__ */ new Set();
140
- cell._markDirty = () => {
141
- markSelectorCellDirty(cell);
222
+ const current = record._dirty || !record._hasValue ? recomputeSelectorSourceRecord(record, record._scheduled) : record._value;
223
+ return lane._equals(current, candidate);
142
224
  };
143
- cell._cleanup = () => {
144
- cell._scheduled = false;
145
- cell._dirty = false;
146
- cell._hasValue = false;
147
- dirtySelectorCells.delete(cell);
148
- clearDerivedDependencySubscriptions(cell, cell._sources);
149
- for (const sourceRef of cell._primitiveCandidates.values()) {
150
- sourceRef._readers?.clear();
151
- sourceRef._derivedSubscribers?.clear();
152
- }
153
- for (const sourceRef of cell._objectCandidateSources) {
154
- sourceRef._readers?.clear();
155
- sourceRef._derivedSubscribers?.clear();
156
- }
157
- cell._primitiveCandidates.clear();
158
- cell._objectCandidateSources.clear();
225
+ hook._owner = instance;
226
+ hook._hookIndex = hookIndex;
227
+ hook._source = source;
228
+ hook._equals = equals;
229
+ hook._record = null;
230
+ hook._lane = null;
231
+ hook._cleanup = () => {
232
+ detachSelectorHookBinding(hook);
159
233
  };
234
+ attachSelectorHookBinding(hook, source, equals);
160
235
  (instance.cleanupFns ??= []).push(() => {
161
- cell._cleanup();
236
+ hook._cleanup();
162
237
  selectorCells.get(instance)?.delete(hookIndex);
163
238
  });
164
- return cell;
239
+ return hook;
165
240
  }
166
- function getOrCreateSelectorCell(instance, hookIndex, source, equals) {
241
+ function getOrCreateSelectorHook(instance, hookIndex, source, equals) {
167
242
  const store = getSelectorStore(instance);
168
243
  const existing = store.get(hookIndex);
169
244
  if (existing) {
170
- existing._source = source;
171
- existing._equals = equals;
172
- existing._dirty = true;
245
+ if (existing._source !== source || existing._equals !== equals) {
246
+ detachSelectorHookBinding(existing);
247
+ attachSelectorHookBinding(existing, source, equals);
248
+ } else ensureSelectorHookBinding(existing);
173
249
  return existing;
174
250
  }
175
- const created = createSelectorCell(instance, hookIndex, source, equals);
251
+ const created = createSelectorHook(instance, hookIndex, source, equals);
176
252
  store.set(hookIndex, created);
177
253
  return created;
178
254
  }
@@ -180,9 +256,10 @@ function selector(source, equals = Object.is) {
180
256
  markReadableUsage(source);
181
257
  const instance = getCurrentInstance();
182
258
  if (!instance) throw new Error("selector() can only be called during component render execution. Move selector() calls to the top level of your component function.");
183
- const cell = getOrCreateSelectorCell(instance, claimHookIndex(instance, "selector"), source, equals);
184
- recomputeSelectorCell(cell, false);
185
- return cell;
259
+ const hook = getOrCreateSelectorHook(instance, claimHookIndex(instance, "selector"), source, equals);
260
+ if (!hook._record) throw new Error("selector() record binding was not established.");
261
+ if (!hook._record._hasValue) recomputeSelectorSourceRecord(hook._record, false);
262
+ return hook;
186
263
  }
187
264
  //#endregion
188
265
  export { selector };
@@ -1 +1 @@
1
- {"version":3,"file":"selector.js","names":[],"sources":["../../src/runtime/selector.ts"],"sourcesContent":["import {\n claimHookIndex,\n getCurrentInstance,\n type ComponentInstance,\n} from './component';\nimport { globalScheduler } from './scheduler';\nimport {\n clearDerivedDependencySubscriptions,\n markReadableDerivedSubscribersDirty,\n markReadableUsage,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n recordReadableRead,\n syncDerivedDependencySubscriptions,\n withDerivedReadTracking,\n type DerivedSubscriber,\n type ReadableSource,\n} from './readable';\nimport { getPerfMetricsStore, incrementPerfMetric } from './perf-metrics';\n\ntype PrimitiveKey =\n | string\n | number\n | boolean\n | symbol\n | bigint\n | null\n | undefined;\n\nexport interface Selector<T> {\n (candidate: T): boolean;\n}\n\ninterface SelectorCandidateSource<T> extends ReadableSource<boolean> {\n _candidate: T;\n}\n\ntype SelectorEquals<T> = {\n bivarianceHack(a: T, b: T): boolean;\n}['bivarianceHack'];\n\ninterface SelectorCell<T> extends Selector<T>, DerivedSubscriber {\n _owner: ComponentInstance;\n _hookIndex: number;\n _source: () => T;\n _equals: SelectorEquals<T>;\n _value: T;\n _hasValue: boolean;\n _dirty: boolean;\n _scheduled: boolean;\n _evaluating: boolean;\n _sources: Set<ReadableSource<unknown>>;\n _pendingDependencySources?: Set<ReadableSource<unknown>>;\n _primitiveCandidates: Map<PrimitiveKey, SelectorCandidateSource<T>>;\n _objectCandidates: WeakMap<object, SelectorCandidateSource<T>>;\n _objectCandidateSources: Set<SelectorCandidateSource<T>>;\n _cleanup(): void;\n}\n\nconst selectorCells = new WeakMap<\n ComponentInstance,\n Map<number, SelectorCell<unknown>>\n>();\nconst dirtySelectorCells = new Set<SelectorCell<unknown>>();\nlet hasPendingSelectorFlush = false;\n\nfunction getSelectorStore(\n instance: ComponentInstance\n): Map<number, SelectorCell<unknown>> {\n let store = selectorCells.get(instance);\n if (!store) {\n store = new Map();\n selectorCells.set(instance, store);\n }\n return store;\n}\n\nfunction scheduleSelectorFlush(): void {\n if (hasPendingSelectorFlush) {\n return;\n }\n hasPendingSelectorFlush = true;\n globalScheduler.enqueueInLane('derived', flushDirtySelectorCells);\n}\n\nfunction markSelectorCellDirty(cell: SelectorCell<unknown>): void {\n cell._dirty = true;\n if (cell._scheduled) {\n return;\n }\n\n cell._scheduled = true;\n dirtySelectorCells.add(cell);\n scheduleSelectorFlush();\n}\n\nfunction flushDirtySelectorCells(): void {\n hasPendingSelectorFlush = false;\n\n if (dirtySelectorCells.size === 0) {\n return;\n }\n\n const pending = Array.from(dirtySelectorCells);\n dirtySelectorCells.clear();\n\n for (const cell of pending) {\n cell._scheduled = false;\n if (!cell._dirty) {\n continue;\n }\n recomputeSelectorCell(cell, true);\n }\n}\n\nfunction isObjectCandidate(value: unknown): value is object {\n return (\n (typeof value === 'object' && value !== null) || typeof value === 'function'\n );\n}\n\nfunction isDefaultSelectorEquals<T>(equals: SelectorEquals<T>): boolean {\n return equals === Object.is;\n}\n\nfunction createCandidateSource<T>(candidate: T): SelectorCandidateSource<T> {\n const source = (() => false) as SelectorCandidateSource<T>;\n source._candidate = candidate;\n return source;\n}\n\nfunction getCandidateSource<T>(\n cell: SelectorCell<T>,\n candidate: T\n): SelectorCandidateSource<T> {\n if (isObjectCandidate(candidate)) {\n const cached = cell._objectCandidates.get(candidate);\n if (cached) {\n return cached;\n }\n\n const created = createCandidateSource(candidate);\n created._candidate = candidate;\n cell._objectCandidates.set(candidate, created);\n cell._objectCandidateSources.add(created);\n return created;\n }\n\n const key = candidate as PrimitiveKey;\n const cached = cell._primitiveCandidates.get(key);\n if (cached) {\n return cached;\n }\n\n const created = createCandidateSource(candidate);\n created._candidate = candidate;\n cell._primitiveCandidates.set(key, created);\n return created;\n}\n\nfunction notifySelectorSource(source: SelectorCandidateSource<unknown>): void {\n incrementPerfMetric('selectorInvalidations');\n markReadableDerivedSubscribersDirty(source);\n markReactivePropsDirtySource(source);\n notifyReadableReaders(source);\n}\n\nfunction notifyAllSelectorSources<T>(cell: SelectorCell<T>): void {\n for (const source of cell._primitiveCandidates.values()) {\n notifySelectorSource(source);\n }\n for (const source of cell._objectCandidateSources) {\n notifySelectorSource(source);\n }\n}\n\nfunction notifySelectorValueChange<T>(\n cell: SelectorCell<T>,\n prevValue: T,\n nextValue: T\n): void {\n if (!isDefaultSelectorEquals(cell._equals)) {\n notifyAllSelectorSources(cell);\n return;\n }\n\n if (!Object.is(prevValue, nextValue)) {\n notifySelectorSource(getCandidateSource(cell, prevValue));\n notifySelectorSource(getCandidateSource(cell, nextValue));\n }\n}\n\nfunction recomputeSelectorCell<T>(\n cell: SelectorCell<T>,\n notifyDownstream: boolean\n): T {\n if (!cell._dirty && cell._hasValue) {\n return cell._value;\n }\n\n if (cell._evaluating) {\n throw new Error('selector() cannot read itself recursively');\n }\n\n cell._evaluating = true;\n cell._dirty = false;\n cell._pendingDependencySources = new Set();\n\n const prevSources = cell._sources;\n const hadValue = cell._hasValue;\n const prevValue = cell._value;\n let nextValue: T;\n\n try {\n nextValue = withDerivedReadTracking(cell, cell._source);\n } catch (error) {\n cell._dirty = true;\n cell._pendingDependencySources = undefined;\n throw error;\n } finally {\n cell._evaluating = false;\n }\n\n const nextSources = cell._pendingDependencySources ?? new Set();\n cell._pendingDependencySources = undefined;\n syncDerivedDependencySubscriptions(cell, prevSources, nextSources);\n cell._sources = nextSources;\n\n const valueChanged = !cell._hasValue || !cell._equals(prevValue, nextValue);\n cell._hasValue = true;\n cell._value = nextValue;\n\n if (valueChanged && notifyDownstream && hadValue) {\n notifySelectorValueChange(cell, prevValue, nextValue);\n }\n\n return cell._value;\n}\n\nfunction createSelectorCell<T>(\n instance: ComponentInstance,\n hookIndex: number,\n source: () => T,\n equals: SelectorEquals<T>\n): SelectorCell<T> {\n const perfMetricsStore = getPerfMetricsStore();\n const cell = function selectorPredicate(candidate: T): boolean {\n const sourceRef = getCandidateSource(cell as SelectorCell<T>, candidate);\n recordReadableRead(sourceRef);\n if (perfMetricsStore) {\n perfMetricsStore.selectorCandidateReads += 1;\n }\n const selectorCell = cell as SelectorCell<T>;\n const current =\n selectorCell._dirty || !selectorCell._hasValue\n ? recomputeSelectorCell(selectorCell, selectorCell._scheduled)\n : selectorCell._value;\n return selectorCell._equals(current, candidate);\n } as SelectorCell<T>;\n\n cell._owner = instance;\n cell._hookIndex = hookIndex;\n cell._source = source;\n cell._equals = equals;\n cell._value = undefined as T;\n cell._hasValue = false;\n cell._dirty = true;\n cell._scheduled = false;\n cell._evaluating = false;\n cell._sources = new Set();\n cell._primitiveCandidates = new Map();\n cell._objectCandidates = new WeakMap();\n cell._objectCandidateSources = new Set();\n cell._markDirty = () => {\n markSelectorCellDirty(cell as unknown as SelectorCell<unknown>);\n };\n cell._cleanup = () => {\n cell._scheduled = false;\n cell._dirty = false;\n cell._hasValue = false;\n dirtySelectorCells.delete(cell as unknown as SelectorCell<unknown>);\n clearDerivedDependencySubscriptions(cell, cell._sources);\n for (const sourceRef of cell._primitiveCandidates.values()) {\n sourceRef._readers?.clear();\n sourceRef._derivedSubscribers?.clear();\n }\n for (const sourceRef of cell._objectCandidateSources) {\n sourceRef._readers?.clear();\n sourceRef._derivedSubscribers?.clear();\n }\n cell._primitiveCandidates.clear();\n cell._objectCandidateSources.clear();\n };\n\n (instance.cleanupFns ??= []).push(() => {\n cell._cleanup();\n selectorCells.get(instance)?.delete(hookIndex);\n });\n\n return cell;\n}\n\nfunction getOrCreateSelectorCell<T>(\n instance: ComponentInstance,\n hookIndex: number,\n source: () => T,\n equals: SelectorEquals<T>\n): SelectorCell<T> {\n const store = getSelectorStore(instance);\n const existing = store.get(hookIndex) as SelectorCell<T> | undefined;\n if (existing) {\n existing._source = source;\n existing._equals = equals;\n existing._dirty = true;\n return existing;\n }\n\n const created = createSelectorCell(instance, hookIndex, source, equals);\n store.set(hookIndex, created as unknown as SelectorCell<unknown>);\n return created;\n}\n\nexport function selector<T>(\n source: () => T,\n equals: SelectorEquals<T> = Object.is\n): Selector<T> {\n markReadableUsage(source);\n\n const instance = getCurrentInstance();\n if (!instance) {\n throw new Error(\n 'selector() can only be called during component render execution. ' +\n 'Move selector() calls to the top level of your component function.'\n );\n }\n\n const hookIndex = claimHookIndex(instance, 'selector');\n const cell = getOrCreateSelectorCell(instance, hookIndex, source, equals);\n recomputeSelectorCell(cell, false);\n return cell;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"selector.js","names":[],"sources":["../../src/runtime/selector.ts"],"sourcesContent":["import {\n claimHookIndex,\n getCurrentInstance,\n type ComponentInstance,\n} from './component';\nimport { globalScheduler } from './scheduler';\nimport {\n clearDerivedDependencySubscriptions,\n markReadableDerivedSubscribersDirty,\n markReadableUsage,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n recordReadableRead,\n syncDerivedDependencySubscriptions,\n withDerivedReadTracking,\n type DerivedSubscriber,\n type ReadableSource,\n} from './readable';\nimport { getPerfMetricsStore, incrementPerfMetric } from './perf-metrics';\n\ntype PrimitiveKey =\n | string\n | number\n | boolean\n | symbol\n | bigint\n | null\n | undefined;\n\nexport interface Selector<T> {\n (candidate: T): boolean;\n}\n\ninterface SelectorCandidateSource<T> extends ReadableSource<boolean> {\n _candidate: T;\n}\n\ntype SelectorEquals<T> = {\n bivarianceHack(a: T, b: T): boolean;\n}['bivarianceHack'];\n\ninterface SelectorLane<T> {\n _record: SelectorSourceRecord<T>;\n _equals: SelectorEquals<T>;\n _bindingCount: number;\n _primitiveCandidates: Map<PrimitiveKey, SelectorCandidateSource<T>>;\n _objectCandidates: WeakMap<object, SelectorCandidateSource<T>>;\n _objectCandidateSources: Set<SelectorCandidateSource<T>>;\n _cleanup(): void;\n}\n\ninterface SelectorSourceRecord<T> extends DerivedSubscriber {\n _source: () => T;\n _value: T;\n _hasValue: boolean;\n _dirty: boolean;\n _scheduled: boolean;\n _evaluating: boolean;\n _sources: Set<ReadableSource<unknown>>;\n _pendingDependencySources?: Set<ReadableSource<unknown>>;\n _lanes: Map<SelectorEquals<T>, SelectorLane<T>>;\n _cleanup(): void;\n}\n\ninterface SelectorHook<T> extends Selector<T> {\n _owner: ComponentInstance;\n _hookIndex: number;\n _source: () => T;\n _equals: SelectorEquals<T>;\n _record: SelectorSourceRecord<T> | null;\n _lane: SelectorLane<T> | null;\n _cleanup(): void;\n}\n\nconst selectorCells = new WeakMap<\n ComponentInstance,\n Map<number, SelectorHook<unknown>>\n>();\nconst selectorRecords = new WeakMap<\n ReadableSource<unknown>,\n SelectorSourceRecord<unknown>\n>();\nconst dirtySelectorRecords = new Set<SelectorSourceRecord<unknown>>();\nlet hasPendingSelectorFlush = false;\n\nfunction getSelectorStore(\n instance: ComponentInstance\n): Map<number, SelectorHook<unknown>> {\n let store = selectorCells.get(instance);\n if (!store) {\n store = new Map();\n selectorCells.set(instance, store);\n }\n return store;\n}\n\nfunction scheduleSelectorFlush(): void {\n if (hasPendingSelectorFlush) {\n return;\n }\n\n hasPendingSelectorFlush = true;\n globalScheduler.enqueueInLane('derived', flushDirtySelectorRecords);\n}\n\nfunction markSelectorRecordDirty(record: SelectorSourceRecord<unknown>): void {\n record._dirty = true;\n if (record._scheduled) {\n return;\n }\n\n record._scheduled = true;\n dirtySelectorRecords.add(record);\n scheduleSelectorFlush();\n}\n\nfunction flushDirtySelectorRecords(): void {\n hasPendingSelectorFlush = false;\n\n if (dirtySelectorRecords.size === 0) {\n return;\n }\n\n const pending = Array.from(dirtySelectorRecords);\n dirtySelectorRecords.clear();\n\n for (const record of pending) {\n record._scheduled = false;\n if (!record._dirty) {\n continue;\n }\n recomputeSelectorSourceRecord(record, true);\n }\n}\n\nfunction isObjectCandidate(value: unknown): value is object {\n return (\n (typeof value === 'object' && value !== null) || typeof value === 'function'\n );\n}\n\nfunction isDefaultSelectorEquals<T>(equals: SelectorEquals<T>): boolean {\n return equals === Object.is;\n}\n\nfunction createCandidateSource<T>(candidate: T): SelectorCandidateSource<T> {\n const source = (() => false) as SelectorCandidateSource<T>;\n source._candidate = candidate;\n return source;\n}\n\nfunction getCandidateSource<T>(\n lane: SelectorLane<T>,\n candidate: T\n): SelectorCandidateSource<T> {\n if (isObjectCandidate(candidate)) {\n const cached = lane._objectCandidates.get(candidate);\n if (cached) {\n return cached;\n }\n\n const created = createCandidateSource(candidate);\n lane._objectCandidates.set(candidate, created);\n lane._objectCandidateSources.add(created);\n return created;\n }\n\n const key = candidate as PrimitiveKey;\n const cached = lane._primitiveCandidates.get(key);\n if (cached) {\n return cached;\n }\n\n const created = createCandidateSource(candidate);\n lane._primitiveCandidates.set(key, created);\n return created;\n}\n\nfunction getSelectorSourceRecord<T>(source: () => T): SelectorSourceRecord<T> {\n const cached = selectorRecords.get(source);\n if (cached) {\n return cached as SelectorSourceRecord<T>;\n }\n\n const record = createSelectorSourceRecord(source);\n selectorRecords.set(source, record as SelectorSourceRecord<unknown>);\n return record;\n}\n\nfunction createSelectorSourceRecord<T>(\n source: () => T\n): SelectorSourceRecord<T> {\n let record!: SelectorSourceRecord<T>;\n\n record = {\n _source: source,\n _value: undefined as T,\n _hasValue: false,\n _dirty: true,\n _scheduled: false,\n _evaluating: false,\n _sources: new Set(),\n _lanes: new Map(),\n _markDirty: () => {\n markSelectorRecordDirty(record as SelectorSourceRecord<unknown>);\n },\n _cleanup: () => {\n record._scheduled = false;\n record._dirty = false;\n record._hasValue = false;\n record._evaluating = false;\n record._pendingDependencySources = undefined;\n clearDerivedDependencySubscriptions(record, record._sources);\n record._lanes.clear();\n selectorRecords.delete(source as ReadableSource<unknown>);\n },\n };\n\n return record;\n}\n\nfunction getSelectorLane<T>(\n record: SelectorSourceRecord<T>,\n equals: SelectorEquals<T>\n): SelectorLane<T> {\n const cached = record._lanes.get(equals);\n if (cached) {\n return cached;\n }\n\n const lane = createSelectorLane(record, equals);\n record._lanes.set(equals, lane);\n return lane;\n}\n\nfunction createSelectorLane<T>(\n record: SelectorSourceRecord<T>,\n equals: SelectorEquals<T>\n): SelectorLane<T> {\n const lane: SelectorLane<T> = {\n _record: record,\n _equals: equals,\n _bindingCount: 0,\n _primitiveCandidates: new Map(),\n _objectCandidates: new WeakMap(),\n _objectCandidateSources: new Set(),\n _cleanup: () => {\n for (const sourceRef of lane._primitiveCandidates.values()) {\n sourceRef._readers?.clear();\n sourceRef._derivedSubscribers?.clear();\n }\n for (const sourceRef of lane._objectCandidateSources) {\n sourceRef._readers?.clear();\n sourceRef._derivedSubscribers?.clear();\n }\n lane._primitiveCandidates.clear();\n lane._objectCandidates = new WeakMap();\n lane._objectCandidateSources.clear();\n },\n };\n\n return lane;\n}\n\nfunction notifySelectorSource(source: SelectorCandidateSource<unknown>): void {\n incrementPerfMetric('selectorInvalidations');\n markReadableDerivedSubscribersDirty(source);\n markReactivePropsDirtySource(source);\n notifyReadableReaders(source);\n}\n\nfunction notifyAllSelectorSources<T>(lane: SelectorLane<T>): void {\n for (const source of lane._primitiveCandidates.values()) {\n notifySelectorSource(source);\n }\n for (const source of lane._objectCandidateSources) {\n notifySelectorSource(source);\n }\n}\n\nfunction notifySelectorLaneValueChange<T>(\n lane: SelectorLane<T>,\n prevValue: T,\n nextValue: T\n): void {\n if (!lane._bindingCount) {\n return;\n }\n\n if (!isDefaultSelectorEquals(lane._equals)) {\n if (lane._equals(prevValue, nextValue)) {\n return;\n }\n notifyAllSelectorSources(lane);\n return;\n }\n\n if (!Object.is(prevValue, nextValue)) {\n notifySelectorSource(getCandidateSource(lane, prevValue));\n notifySelectorSource(getCandidateSource(lane, nextValue));\n }\n}\n\nfunction recomputeSelectorSourceRecord<T>(\n record: SelectorSourceRecord<T>,\n notifyDownstream: boolean\n): T {\n if (!record._dirty && record._hasValue) {\n return record._value;\n }\n\n if (record._evaluating) {\n throw new Error('selector() cannot read itself recursively');\n }\n\n record._evaluating = true;\n record._dirty = false;\n record._pendingDependencySources = new Set();\n\n const prevSources = record._sources;\n const hadValue = record._hasValue;\n const prevValue = record._value;\n let nextValue: T;\n\n try {\n nextValue = withDerivedReadTracking(record, record._source);\n } catch (error) {\n record._dirty = true;\n record._pendingDependencySources = undefined;\n throw error;\n } finally {\n record._evaluating = false;\n }\n\n const nextSources = record._pendingDependencySources ?? new Set();\n record._pendingDependencySources = undefined;\n syncDerivedDependencySubscriptions(record, prevSources, nextSources);\n record._sources = nextSources;\n\n const valueChanged = !record._hasValue || !Object.is(prevValue, nextValue);\n record._hasValue = true;\n record._value = nextValue;\n\n if (valueChanged && notifyDownstream && hadValue) {\n for (const lane of Array.from(record._lanes.values())) {\n notifySelectorLaneValueChange(lane, prevValue, nextValue);\n }\n }\n\n return record._value;\n}\n\nfunction attachSelectorHookBinding<T>(\n hook: SelectorHook<T>,\n source: () => T,\n equals: SelectorEquals<T>\n): void {\n const record = getSelectorSourceRecord(source);\n const lane = getSelectorLane(record, equals);\n\n hook._source = source;\n hook._equals = equals;\n hook._record = record;\n hook._lane = lane;\n lane._bindingCount += 1;\n}\n\nfunction detachSelectorHookBinding<T>(hook: SelectorHook<T>): void {\n const record = hook._record;\n const lane = hook._lane;\n\n hook._record = null;\n hook._lane = null;\n\n if (!record || !lane) {\n return;\n }\n\n if (lane._bindingCount > 0) {\n lane._bindingCount -= 1;\n }\n\n if (lane._bindingCount > 0) {\n return;\n }\n\n lane._cleanup();\n record._lanes.delete(lane._equals);\n\n if (record._lanes.size === 0) {\n record._cleanup();\n }\n}\n\nfunction ensureSelectorHookBinding<T>(\n hook: SelectorHook<T>\n): SelectorSourceRecord<T> {\n const record = hook._record;\n const lane = hook._lane;\n\n if (\n record &&\n lane &&\n lane._bindingCount > 0 &&\n record._lanes.get(hook._equals) === lane &&\n record._source === hook._source\n ) {\n return record;\n }\n\n if (hook._record || hook._lane) {\n detachSelectorHookBinding(hook);\n }\n\n attachSelectorHookBinding(hook, hook._source, hook._equals);\n return hook._record!;\n}\n\nfunction createSelectorHook<T>(\n instance: ComponentInstance,\n hookIndex: number,\n source: () => T,\n equals: SelectorEquals<T>\n): SelectorHook<T> {\n const hook = function selectorPredicate(candidate: T): boolean {\n const selectorHook = hook as SelectorHook<T>;\n const record = ensureSelectorHookBinding(selectorHook);\n const lane = selectorHook._lane;\n if (!lane) {\n throw new Error('selector() binding could not be established.');\n }\n\n const sourceRef = getCandidateSource(lane, candidate);\n recordReadableRead(sourceRef);\n\n const perfMetricsStore = getPerfMetricsStore();\n if (perfMetricsStore) {\n perfMetricsStore.selectorCandidateReads += 1;\n }\n\n const current =\n record._dirty || !record._hasValue\n ? recomputeSelectorSourceRecord(record, record._scheduled)\n : record._value;\n\n return lane._equals(current, candidate);\n } as SelectorHook<T>;\n\n hook._owner = instance;\n hook._hookIndex = hookIndex;\n hook._source = source;\n hook._equals = equals;\n hook._record = null;\n hook._lane = null;\n hook._cleanup = () => {\n detachSelectorHookBinding(hook);\n };\n\n attachSelectorHookBinding(hook, source, equals);\n\n (instance.cleanupFns ??= []).push(() => {\n hook._cleanup();\n selectorCells.get(instance)?.delete(hookIndex);\n });\n\n return hook;\n}\n\nfunction getOrCreateSelectorHook<T>(\n instance: ComponentInstance,\n hookIndex: number,\n source: () => T,\n equals: SelectorEquals<T>\n): SelectorHook<T> {\n const store = getSelectorStore(instance);\n const existing = store.get(hookIndex) as SelectorHook<T> | undefined;\n if (existing) {\n if (existing._source !== source || existing._equals !== equals) {\n detachSelectorHookBinding(existing);\n attachSelectorHookBinding(existing, source, equals);\n } else {\n ensureSelectorHookBinding(existing);\n }\n return existing;\n }\n\n const created = createSelectorHook(instance, hookIndex, source, equals);\n store.set(hookIndex, created as unknown as SelectorHook<unknown>);\n return created;\n}\n\nexport function selector<T>(\n source: () => T,\n equals: SelectorEquals<T> = Object.is\n): Selector<T> {\n markReadableUsage(source);\n\n const instance = getCurrentInstance();\n if (!instance) {\n throw new Error(\n 'selector() can only be called during component render execution. ' +\n 'Move selector() calls to the top level of your component function.'\n );\n }\n\n const hookIndex = claimHookIndex(instance, 'selector');\n const hook = getOrCreateSelectorHook(instance, hookIndex, source, equals);\n if (!hook._record) {\n throw new Error('selector() record binding was not established.');\n }\n\n if (!hook._record._hasValue) {\n // Initialize the shared source once so downstream selectors can subscribe,\n // but do not consume a pending dirty state on later renders.\n recomputeSelectorSourceRecord(hook._record, false);\n }\n return hook;\n}\n"],"mappings":"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"}
@@ -1,8 +1,3 @@
1
1
  import { DiscoveredResources, RouteConfig, RouteRenderReason, RouteRenderResult, RouteRenderStatus, SSGGenerateOptions, SSGMetadata, SSGMode, SSGOptions, SSGResult } from "./types.js";
2
2
  import { createStaticGen } from "./create-static-gen.js";
3
- import { batchRenderRoutes } from "./batch-render.js";
4
- import { getOutputFilePath } from "./route-utils.js";
5
- import { writeStaticFiles } from "./write-static-files.js";
6
- import { generateSSGResult, resultToMetadata, writeMetadata } from "./generate-metadata.js";
7
- import { resolveSsgData, validateRoutes } from "./resolve-ssg-data.js";
8
- export { type DiscoveredResources, type RouteConfig, type RouteRenderReason, type RouteRenderResult, type RouteRenderStatus, type SSGGenerateOptions, type SSGMetadata, type SSGMode, type SSGOptions, type SSGResult, batchRenderRoutes, createStaticGen, generateSSGResult, getOutputFilePath, resolveSsgData, resultToMetadata, validateRoutes, writeMetadata, writeStaticFiles };
3
+ export { type DiscoveredResources, type RouteConfig, type RouteRenderReason, type RouteRenderResult, type RouteRenderStatus, type SSGGenerateOptions, type SSGMetadata, type SSGMode, type SSGOptions, type SSGResult, createStaticGen };
package/dist/ssg/index.js CHANGED
@@ -1,7 +1,2 @@
1
- import { resolveSsgData, validateRoutes } from "./resolve-ssg-data.js";
2
- import { getOutputFilePath } from "./route-utils.js";
3
- import { batchRenderRoutes } from "./batch-render.js";
4
- import { writeStaticFiles } from "./write-static-files.js";
5
- import { generateSSGResult, resultToMetadata, writeMetadata } from "./generate-metadata.js";
6
1
  import { createStaticGen } from "./create-static-gen.js";
7
- export { batchRenderRoutes, createStaticGen, generateSSGResult, getOutputFilePath, resolveSsgData, resultToMetadata, validateRoutes, writeMetadata, writeStaticFiles };
2
+ export { createStaticGen };
@@ -1,6 +1,7 @@
1
1
  import { Route, RouteAuthOptions } from "../common/router.js";
2
- import { SSRData } from "../common/ssr.js";
3
2
  import { SSRDataMissingError } from "../common/ssr-errors.js";
3
+ import { SSRData } from "../common/ssr.js";
4
+
4
5
  //#region src/ssr/context.d.ts
5
6
  interface RenderContext {
6
7
  url: string;
@@ -1 +1 @@
1
- {"version":3,"file":"context.d.ts","names":[],"sources":["../../src/ssr/context.ts"],"mappings":";;;;UAgBiB,aAAA;EACf,GAAA;EACA,IAAA;EACA,IAAA,GAAO,OAAA;EACP,MAAA,GAAS,MAAA;EACT,MAAA,YAAkB,KAAA;EAClB,SAAA,GAAY,gBAAA;EACZ,MAAA,GAAS,WAAA;EACT,UAAA,GAAa,GAAA;EAEb,UAAA;EACA,UAAA,EAAY,MAAA;AAAA;AAAA,KAIF,UAAA,GAAa,aAAA;AAAA,iBA0BT,mBAAA,CACd,IAAA,WACA,IAAA;EACE,GAAA;EACA,IAAA,GAAO,OAAA;EACP,MAAA,GAAS,MAAA;EACT,MAAA,YAAkB,KAAA;EAClB,SAAA,GAAY,gBAAA;EACZ,MAAA,GAAS,WAAA;AAAA,IAEV,aAAA;;;;;iBAqBa,iBAAA,GAAA,CAAqB,GAAA,EAAK,aAAA,EAAe,EAAA,QAAU,CAAA,GAAI,CAAA;AAzDvE;;;;AAAA,iBA2EgB,gBAAA,CAAA,GAAoB,aAAA;AAAA,cAQvB,aAAA,SAAa,gBAAA;AAAA,cACb,cAAA,SAAc,iBAAA;AAAA,cACd,oBAAA,SAAoB,gBAAA;AAAA,iBAEjB,iBAAA,GAAA,CAAqB,GAAA,EAAK,aAAA,EAAe,EAAA,QAAU,CAAA,GAAI,CAAA;;;;;iBASvD,mBAAA,CAAA"}
1
+ {"version":3,"file":"context.d.ts","names":[],"sources":["../../src/ssr/context.ts"],"mappings":";;;;;UAgBiB,aAAA;EACf,GAAA;EACA,IAAA;EACA,IAAA,GAAO,OAAA;EACP,MAAA,GAAS,MAAA;EACT,MAAA,YAAkB,KAAA;EAClB,SAAA,GAAY,gBAAA;EACZ,MAAA,GAAS,WAAA;EACT,UAAA,GAAa,GAAA;EAEb,UAAA;EACA,UAAA,EAAY,MAAA;AAAA;AAAA,KAIF,UAAA,GAAa,aAAA;AAAA,iBAoDT,mBAAA,CACd,IAAA,WACA,IAAA;EACE,GAAA;EACA,IAAA,GAAO,OAAA;EACP,MAAA,GAAS,MAAA;EACT,MAAA,YAAkB,KAAA;EAClB,SAAA,GAAY,gBAAA;EACZ,MAAA,GAAS,WAAA;AAAA,IAEV,aAAA;;;;;iBAqBa,iBAAA,GAAA,CAAqB,GAAA,EAAK,aAAA,EAAe,EAAA,QAAU,CAAA,GAAI,CAAA;AAnFvE;;;;AAAA,iBAsGgB,gBAAA,CAAA,GAAoB,aAAA;AAAA,cASvB,aAAA,SAAa,gBAAA;AAAA,cACb,cAAA,SAAc,iBAAA;AAAA,cACd,oBAAA,SAAoB,gBAAA;AAAA,iBAEjB,iBAAA,GAAA,CAAqB,GAAA,EAAK,aAAA,EAAe,EAAA,QAAU,CAAA,GAAI,CAAA;;;;;iBASvD,mBAAA,CAAA"}
@@ -1,4 +1,3 @@
1
- import { __require } from "../_virtual/_rolldown/runtime.js";
2
1
  import { SSRDataMissingError } from "../common/ssr-errors.js";
3
2
  import "./errors.js";
4
3
  import { clearEscapeCache } from "./escape.js";
@@ -6,16 +5,32 @@ import { clearEscapeCache } from "./escape.js";
6
5
  /**
7
6
  * SSR Context Management
8
7
  *
9
- * Provides concurrency-safe context for server-side rendering.
10
- * In Node.js, uses AsyncLocalStorage for isolation between concurrent requests.
11
- * Falls back to stack-based approach in non-Node environments.
8
+ * Provides render-context storage for server-side rendering.
9
+ * Node SSR lazily installs AsyncLocalStorage on first use; browser builds use
10
+ * the fallback stack.
12
11
  */
13
- let asyncLocalStorage = null;
14
- try {
15
- const asyncHooks = __require("async_hooks");
16
- if (asyncHooks?.AsyncLocalStorage) asyncLocalStorage = new asyncHooks.AsyncLocalStorage();
17
- } catch {}
12
+ let renderContextAccessor = null;
13
+ let renderContextAccessorInitialized = false;
18
14
  let fallbackStack = null;
15
+ function ensureRenderContextAccessor() {
16
+ if (renderContextAccessorInitialized) return;
17
+ renderContextAccessorInitialized = true;
18
+ if (typeof process === "undefined" || !process.versions?.node) return;
19
+ try {
20
+ const asyncHooks = new Function("return require(" + JSON.stringify("async_hooks") + ");")();
21
+ if (asyncHooks.AsyncLocalStorage) {
22
+ const asyncLocalStorage = new asyncHooks.AsyncLocalStorage();
23
+ renderContextAccessor = {
24
+ getStore() {
25
+ return asyncLocalStorage.getStore();
26
+ },
27
+ run(store, fn) {
28
+ return asyncLocalStorage.run(store, fn);
29
+ }
30
+ };
31
+ }
32
+ } catch {}
33
+ }
19
34
  function createRenderContext(seed = 12345, opts = {}) {
20
35
  clearEscapeCache();
21
36
  return {
@@ -36,7 +51,8 @@ function createRenderContext(seed = 12345, opts = {}) {
36
51
  * Concurrency-safe in Node.js via AsyncLocalStorage.
37
52
  */
38
53
  function withRenderContext(ctx, fn) {
39
- if (asyncLocalStorage) return asyncLocalStorage.run(ctx, fn);
54
+ ensureRenderContextAccessor();
55
+ if (renderContextAccessor) return renderContextAccessor.run(ctx, fn);
40
56
  const prev = fallbackStack;
41
57
  fallbackStack = ctx;
42
58
  try {
@@ -50,7 +66,8 @@ function withRenderContext(ctx, fn) {
50
66
  * Returns null if not inside a render.
51
67
  */
52
68
  function getRenderContext() {
53
- if (asyncLocalStorage) return asyncLocalStorage.getStore() ?? null;
69
+ ensureRenderContextAccessor();
70
+ if (renderContextAccessor) return renderContextAccessor.getStore() ?? null;
54
71
  return fallbackStack;
55
72
  }
56
73
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","names":[],"sources":["../../src/ssr/context.ts"],"sourcesContent":["/**\n * SSR Context Management\n *\n * Provides concurrency-safe context for server-side rendering.\n * In Node.js, uses AsyncLocalStorage for isolation between concurrent requests.\n * Falls back to stack-based approach in non-Node environments.\n */\n\nimport { SSRDataMissingError } from './errors';\nimport { clearEscapeCache } from './escape';\n\nexport type { SSRData } from '../common/ssr';\nimport type { SSRData } from '../common/ssr';\nimport type { Route, RouteAuthOptions } from '../common/router';\n\n// Unified per-render context combining SSRContext and RenderContext\nexport interface RenderContext {\n url: string;\n seed: number;\n data?: SSRData;\n params?: Record<string, string>;\n routes?: readonly Route[];\n routeAuth?: RouteAuthOptions;\n signal?: AbortSignal;\n queryCache?: Map<string, unknown>;\n // Per-render key state (moved from render-keys.ts globals)\n keyCounter: number;\n renderData: Record<string, unknown> | null;\n}\n\n// Legacy alias for compatibility\nexport type SSRContext = RenderContext;\n\n// AsyncLocalStorage for Node.js concurrency safety\ntype AsyncLocalStorageType<T> = {\n getStore(): T | undefined;\n run<R>(store: T, fn: () => R): R;\n};\n\nlet asyncLocalStorage: AsyncLocalStorageType<RenderContext> | null = null;\n\n// Try to load AsyncLocalStorage at module init (Node.js only)\ntry {\n // Dynamic require to avoid bundler issues in browser builds\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const asyncHooks = require('async_hooks');\n if (asyncHooks?.AsyncLocalStorage) {\n asyncLocalStorage =\n new asyncHooks.AsyncLocalStorage() as AsyncLocalStorageType<RenderContext>;\n }\n} catch {\n // Not in Node.js or async_hooks unavailable - use fallback\n}\n\n// Fallback stack for non-Node environments\nlet fallbackStack: RenderContext | null = null;\n\nexport function createRenderContext(\n seed = 12345,\n opts: {\n url?: string;\n data?: SSRData;\n params?: Record<string, string>;\n routes?: readonly Route[];\n routeAuth?: RouteAuthOptions;\n signal?: AbortSignal;\n } = {}\n): RenderContext {\n clearEscapeCache();\n\n return {\n url: opts.url ?? '',\n seed,\n data: opts.data,\n params: opts.params,\n routes: opts.routes,\n routeAuth: opts.routeAuth,\n signal: opts.signal,\n queryCache: new Map<string, unknown>(),\n keyCounter: 0,\n renderData: null,\n };\n}\n\n/**\n * Run a function with the given render context.\n * Concurrency-safe in Node.js via AsyncLocalStorage.\n */\nexport function withRenderContext<T>(ctx: RenderContext, fn: () => T): T {\n if (asyncLocalStorage) {\n return asyncLocalStorage.run(ctx, fn);\n }\n // Fallback: stack-based (not concurrency-safe)\n const prev = fallbackStack;\n fallbackStack = ctx;\n try {\n return fn();\n } finally {\n fallbackStack = prev;\n }\n}\n\n/**\n * Get the current render context.\n * Returns null if not inside a render.\n */\nexport function getRenderContext(): RenderContext | null {\n if (asyncLocalStorage) {\n return asyncLocalStorage.getStore() ?? null;\n }\n return fallbackStack;\n}\n\n// Legacy API aliases (deprecated, for backwards compatibility)\nexport const getSSRContext = getRenderContext;\nexport const withSSRContext = withRenderContext;\nexport const getCurrentSSRContext = getRenderContext;\n\nexport function runWithSSRContext<T>(ctx: RenderContext, fn: () => T): T {\n // This was a separate path for sync detection; now unified\n return withRenderContext(ctx, fn);\n}\n\n/**\n * Centralized SSR enforcement helper — throws a consistent error when async\n * data is encountered during synchronous SSR.\n */\nexport function throwSSRDataMissing(): never {\n throw new SSRDataMissingError();\n}\n\nexport { SSRDataMissingError };\n"],"mappings":";;;;;;;;;;;;AAuCA,IAAI,oBAAiE;AAGrE,IAAI;CAGF,MAAM,aAAA,UAAqB,cAAc;CACzC,IAAI,YAAY,mBACd,oBACE,IAAI,WAAW,mBAAmB;QAEhC;AAKR,IAAI,gBAAsC;AAE1C,SAAgB,oBACd,OAAO,OACP,OAOI,EAAE,EACS;CACf,kBAAkB;CAElB,OAAO;EACL,KAAK,KAAK,OAAO;EACjB;EACA,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,QAAQ,KAAK;EACb,4BAAY,IAAI,KAAsB;EACtC,YAAY;EACZ,YAAY;EACb;;;;;;AAOH,SAAgB,kBAAqB,KAAoB,IAAgB;CACvE,IAAI,mBACF,OAAO,kBAAkB,IAAI,KAAK,GAAG;CAGvC,MAAM,OAAO;CACb,gBAAgB;CAChB,IAAI;EACF,OAAO,IAAI;WACH;EACR,gBAAgB;;;;;;;AAQpB,SAAgB,mBAAyC;CACvD,IAAI,mBACF,OAAO,kBAAkB,UAAU,IAAI;CAEzC,OAAO;;;;;;AAiBT,SAAgB,sBAA6B;CAC3C,MAAM,IAAI,qBAAqB"}
1
+ {"version":3,"file":"context.js","names":[],"sources":["../../src/ssr/context.ts"],"sourcesContent":["/**\n * SSR Context Management\n *\n * Provides render-context storage for server-side rendering.\n * Node SSR lazily installs AsyncLocalStorage on first use; browser builds use\n * the fallback stack.\n */\n\nimport { SSRDataMissingError } from './errors';\nimport { clearEscapeCache } from './escape';\n\nexport type { SSRData } from '../common/ssr';\nimport type { SSRData } from '../common/ssr';\nimport type { Route, RouteAuthOptions } from '../common/router';\n\n// Unified per-render context combining SSRContext and RenderContext\nexport interface RenderContext {\n url: string;\n seed: number;\n data?: SSRData;\n params?: Record<string, string>;\n routes?: readonly Route[];\n routeAuth?: RouteAuthOptions;\n signal?: AbortSignal;\n queryCache?: Map<string, unknown>;\n // Per-render key state (moved from render-keys.ts globals)\n keyCounter: number;\n renderData: Record<string, unknown> | null;\n}\n\n// Legacy alias for compatibility\nexport type SSRContext = RenderContext;\n\ntype RenderContextAccessor = {\n getStore(): RenderContext | undefined;\n run<R>(store: RenderContext, fn: () => R): R;\n};\n\ntype AsyncHooksModule = {\n AsyncLocalStorage?: new () => RenderContextAccessor;\n};\n\nlet renderContextAccessor: RenderContextAccessor | null = null;\nlet renderContextAccessorInitialized = false;\n\n// Fallback stack for non-Node environments\nlet fallbackStack: RenderContext | null = null;\n\nfunction ensureRenderContextAccessor(): void {\n if (renderContextAccessorInitialized) {\n return;\n }\n\n renderContextAccessorInitialized = true;\n\n if (typeof process === 'undefined' || !process.versions?.node) {\n return;\n }\n\n try {\n // Hide the Node builtin from browser dependency scanners.\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n const loadAsyncHooks = new Function(\n 'return require(' + JSON.stringify('async_hooks') + ');'\n ) as () => AsyncHooksModule;\n const asyncHooks = loadAsyncHooks();\n\n if (asyncHooks.AsyncLocalStorage) {\n const asyncLocalStorage = new asyncHooks.AsyncLocalStorage();\n renderContextAccessor = {\n getStore() {\n return asyncLocalStorage.getStore();\n },\n run<R>(store: RenderContext, fn: () => R): R {\n return asyncLocalStorage.run(store, fn);\n },\n };\n }\n } catch {\n // Keep the fallback stack when async_hooks is unavailable.\n }\n}\n\nexport function createRenderContext(\n seed = 12345,\n opts: {\n url?: string;\n data?: SSRData;\n params?: Record<string, string>;\n routes?: readonly Route[];\n routeAuth?: RouteAuthOptions;\n signal?: AbortSignal;\n } = {}\n): RenderContext {\n clearEscapeCache();\n\n return {\n url: opts.url ?? '',\n seed,\n data: opts.data,\n params: opts.params,\n routes: opts.routes,\n routeAuth: opts.routeAuth,\n signal: opts.signal,\n queryCache: new Map<string, unknown>(),\n keyCounter: 0,\n renderData: null,\n };\n}\n\n/**\n * Run a function with the given render context.\n * Concurrency-safe in Node.js via AsyncLocalStorage.\n */\nexport function withRenderContext<T>(ctx: RenderContext, fn: () => T): T {\n ensureRenderContextAccessor();\n if (renderContextAccessor) {\n return renderContextAccessor.run(ctx, fn);\n }\n // Fallback: stack-based (not concurrency-safe)\n const prev = fallbackStack;\n fallbackStack = ctx;\n try {\n return fn();\n } finally {\n fallbackStack = prev;\n }\n}\n\n/**\n * Get the current render context.\n * Returns null if not inside a render.\n */\nexport function getRenderContext(): RenderContext | null {\n ensureRenderContextAccessor();\n if (renderContextAccessor) {\n return renderContextAccessor.getStore() ?? null;\n }\n return fallbackStack;\n}\n\n// Legacy API aliases (deprecated, for backwards compatibility)\nexport const getSSRContext = getRenderContext;\nexport const withSSRContext = withRenderContext;\nexport const getCurrentSSRContext = getRenderContext;\n\nexport function runWithSSRContext<T>(ctx: RenderContext, fn: () => T): T {\n // This was a separate path for sync detection; now unified\n return withRenderContext(ctx, fn);\n}\n\n/**\n * Centralized SSR enforcement helper — throws a consistent error when async\n * data is encountered during synchronous SSR.\n */\nexport function throwSSRDataMissing(): never {\n throw new SSRDataMissingError();\n}\n\nexport { SSRDataMissingError };\n"],"mappings":";;;;;;;;;;;AA0CA,IAAI,wBAAsD;AAC1D,IAAI,mCAAmC;AAGvC,IAAI,gBAAsC;AAE1C,SAAS,8BAAoC;CAC3C,IAAI,kCACF;CAGF,mCAAmC;CAEnC,IAAI,OAAO,YAAY,eAAe,CAAC,QAAQ,UAAU,MACvD;CAGF,IAAI;EAMF,MAAM,aAAa,IAHQ,SACzB,oBAAoB,KAAK,UAAU,cAAc,GAAG,KAEnC,EAAgB;EAEnC,IAAI,WAAW,mBAAmB;GAChC,MAAM,oBAAoB,IAAI,WAAW,mBAAmB;GAC5D,wBAAwB;IACtB,WAAW;KACT,OAAO,kBAAkB,UAAU;;IAErC,IAAO,OAAsB,IAAgB;KAC3C,OAAO,kBAAkB,IAAI,OAAO,GAAG;;IAE1C;;SAEG;;AAKV,SAAgB,oBACd,OAAO,OACP,OAOI,EAAE,EACS;CACf,kBAAkB;CAElB,OAAO;EACL,KAAK,KAAK,OAAO;EACjB;EACA,MAAM,KAAK;EACX,QAAQ,KAAK;EACb,QAAQ,KAAK;EACb,WAAW,KAAK;EAChB,QAAQ,KAAK;EACb,4BAAY,IAAI,KAAsB;EACtC,YAAY;EACZ,YAAY;EACb;;;;;;AAOH,SAAgB,kBAAqB,KAAoB,IAAgB;CACvE,6BAA6B;CAC7B,IAAI,uBACF,OAAO,sBAAsB,IAAI,KAAK,GAAG;CAG3C,MAAM,OAAO;CACb,gBAAgB;CAChB,IAAI;EACF,OAAO,IAAI;WACH;EACR,gBAAgB;;;;;;;AAQpB,SAAgB,mBAAyC;CACvD,6BAA6B;CAC7B,IAAI,uBACF,OAAO,sBAAsB,UAAU,IAAI;CAE7C,OAAO;;;;;;AAiBT,SAAgB,sBAA6B;CAC3C,MAAM,IAAI,qBAAqB"}
@@ -1,14 +1,10 @@
1
1
  import { JSXElement } from "../common/jsx.js";
2
2
  import { RouteAuthOptions, RouteHandler, RouteManifest, RouteRequestResult } from "../common/router.js";
3
- import { SSRData } from "../common/ssr.js";
4
3
  import { SSRDataMissingError } from "../common/ssr-errors.js";
4
+ import { SSRData } from "../common/ssr.js";
5
5
  import { SSRComponent, VNode } from "./types.js";
6
- import { ResourcePlan, collectResources, resolvePlan, resolveResources } from "./render-keys.js";
7
6
 
8
7
  //#region src/ssr/index.d.ts
9
- type Component = SSRComponent;
10
- declare function pushSSRStrictPurityGuard(): void;
11
- declare function popSSRStrictPurityGuard(): void;
12
8
  /**
13
9
  * Single synchronous SSR entrypoint: render a component to an HTML string.
14
10
  * This is strictly synchronous and deterministic. Optionally provide a seed
@@ -43,31 +39,6 @@ declare function resolveRequest(opts: {
43
39
  auth?: RouteAuthOptions;
44
40
  signal?: AbortSignal;
45
41
  }): Promise<RouteRequestResult>;
46
- declare function renderToStringSyncForUrl(opts: {
47
- url: string;
48
- routes: Array<{
49
- path: string;
50
- handler: RouteHandler;
51
- namespace?: string;
52
- }>;
53
- options?: {
54
- seed?: number;
55
- data?: SSRData;
56
- };
57
- }): string;
58
- declare function verifyHydrationSyncForUrl(opts: {
59
- root: Element;
60
- url: string;
61
- routes: Array<{
62
- path: string;
63
- handler: RouteHandler;
64
- namespace?: string;
65
- }>;
66
- options?: {
67
- seed?: number;
68
- data?: SSRData;
69
- };
70
- }): boolean;
71
42
  type SSRRoute = {
72
43
  path: string;
73
44
  handler: RouteHandler;
@@ -89,5 +60,5 @@ declare function renderToStream(opts: {
89
60
  onComplete(): void;
90
61
  }): void;
91
62
  //#endregion
92
- export { Component, ResourcePlan, type SSRComponent, SSRDataMissingError, SSRRoute, type VNode, collectResources, popSSRStrictPurityGuard, pushSSRStrictPurityGuard, renderResolvedToStringSync, renderToStream, renderToString, renderToStringSync, renderToStringSyncForUrl, resolvePlan, resolveRequest, resolveResources, verifyHydrationSyncForUrl };
63
+ export { type SSRComponent, SSRDataMissingError, SSRRoute, type VNode, renderResolvedToStringSync, renderToStream, renderToString, renderToStringSync, resolveRequest };
93
64
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/ssr/index.ts"],"mappings":";;;;;;;;KAiHY,SAAA,GAAY,YAAA;AAAA,iBAQR,wBAAA,CAAA;AAAA,iBAmBA,uBAAA,CAAA;;;;;AAkgChB;iBAAgB,kBAAA,CACd,SAAA,GACE,KAAA,GAAQ,MAAA,sBACL,KAAA,GAAQ,UAAA,iDACb,KAAA,GAAQ,MAAA,mBACR,OAAA;EAAY,IAAA;EAAe,IAAA,GAAO,OAAA;AAAA;AAAA,iBA2BpB,0BAAA,CAA2B,IAAA;EACzC,GAAA;EACA,MAAA,EAAQ,KAAA;IAAQ,IAAA;IAAc,OAAA,EAAS,YAAA;IAAc,SAAA;EAAA;EACrD,OAAA,EAAS,YAAA;EACT,MAAA,GAAS,MAAA;EACT,OAAA;IAAY,IAAA;IAAe,IAAA,GAAO,OAAA;EAAA;AAAA;AAAA,iBA6Bd,cAAA,CAAe,IAAA;EACnC,GAAA;EACA,QAAA,GAAW,aAAA;EACX,MAAA,GAAS,KAAA;IAAQ,IAAA;IAAc,OAAA,EAAS,YAAA;IAAc,SAAA;EAAA;EACtD,IAAA,GAAO,gBAAA;EACP,MAAA,GAAS,WAAA;AAAA,IACP,OAAA,CAAQ,kBAAA;AAAA,iBAmCI,wBAAA,CAAyB,IAAA;EACvC,GAAA;EACA,MAAA,EAAQ,KAAA;IAAQ,IAAA;IAAc,OAAA,EAAS,YAAA;IAAc,SAAA;EAAA;EACrD,OAAA;IAAY,IAAA;IAAe,IAAA,GAAO,OAAA;EAAA;AAAA;AAAA,iBAqBpB,yBAAA,CAA0B,IAAA;EACxC,IAAA,EAAM,OAAA;EACN,GAAA;EACA,MAAA,EAAQ,KAAA;IAAQ,IAAA;IAAc,OAAA,EAAS,YAAA;IAAc,SAAA;EAAA;EACrD,OAAA;IAAY,IAAA;IAAe,IAAA,GAAO,OAAA;EAAA;AAAA;AAAA,KAkDxB,QAAA;EACV,IAAA;EACA,OAAA,EAAS,YAAA;EACT,SAAA;AAAA;AAAA,iBAGc,cAAA,CACd,SAAA,GACE,KAAA,GAAQ,MAAA,sBACL,KAAA,GAAQ,UAAA;AAAA,iBAEC,cAAA,CAAe,IAAA;EAC7B,GAAA;EACA,MAAA,EAAQ,QAAA;EACR,IAAA;EACA,IAAA,GAAO,OAAA;AAAA;AAAA,iBAuBO,cAAA,CAAe,IAAA;EAC7B,GAAA;EACA,MAAA,EAAQ,QAAA;EACR,IAAA;EACA,IAAA,GAAO,OAAA;EACP,OAAA,CAAQ,IAAA;EACR,UAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../src/ssr/index.ts"],"mappings":";;;;;;;;;;;;iBA4nCgB,kBAAA,CACd,SAAA,GACE,KAAA,GAAQ,MAAA,sBACL,KAAA,GAAQ,UAAA,iDACb,KAAA,GAAQ,MAAA,mBACR,OAAA;EAAY,IAAA;EAAe,IAAA,GAAO,OAAA;AAAA;AAAA,iBA2BpB,0BAAA,CAA2B,IAAA;EACzC,GAAA;EACA,MAAA,EAAQ,KAAA;IAAQ,IAAA;IAAc,OAAA,EAAS,YAAA;IAAc,SAAA;EAAA;EACrD,OAAA,EAAS,YAAA;EACT,MAAA,GAAS,MAAA;EACT,OAAA;IAAY,IAAA;IAAe,IAAA,GAAO,OAAA;EAAA;AAAA;AAAA,iBA6Bd,cAAA,CAAe,IAAA;EACnC,GAAA;EACA,QAAA,GAAW,aAAA;EACX,MAAA,GAAS,KAAA;IAAQ,IAAA;IAAc,OAAA,EAAS,YAAA;IAAc,SAAA;EAAA;EACtD,IAAA,GAAO,gBAAA;EACP,MAAA,GAAS,WAAA;AAAA,IACP,OAAA,CAAQ,kBAAA;AAAA,KAqCA,QAAA;EACV,IAAA;EACA,OAAA,EAAS,YAAA;EACT,SAAA;AAAA;AAAA,iBAGc,cAAA,CACd,SAAA,GACE,KAAA,GAAQ,MAAA,sBACL,KAAA,GAAQ,UAAA;AAAA,iBAEC,cAAA,CAAe,IAAA;EAC7B,GAAA;EACA,MAAA,EAAQ,QAAA;EACR,IAAA;EACA,IAAA,GAAO,OAAA;AAAA;AAAA,iBAuBO,cAAA,CAAe,IAAA;EAC7B,GAAA;EACA,MAAA,EAAQ,QAAA;EACR,IAAA;EACA,IAAA,GAAO,OAAA;EACP,OAAA,CAAQ,IAAA;EACR,UAAA;AAAA"}