@jqhtml/core 2.3.54 → 2.3.59
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/README.md +3 -1
- package/dist/boot.d.ts +0 -0
- package/dist/boot.d.ts.map +0 -0
- package/dist/boot.js +130 -0
- package/dist/boot.js.map +1 -0
- package/dist/cache-key-serializer.d.ts +0 -0
- package/dist/cache-key-serializer.d.ts.map +0 -0
- package/dist/cache-key-serializer.js +140 -0
- package/dist/cache-key-serializer.js.map +1 -0
- package/dist/component-cache.d.ts +0 -0
- package/dist/component-cache.d.ts.map +0 -0
- package/dist/component-cache.js +270 -0
- package/dist/component-cache.js.map +1 -0
- package/dist/component-events.d.ts +0 -0
- package/dist/component-events.d.ts.map +0 -0
- package/dist/component-events.js +141 -0
- package/dist/component-events.js.map +1 -0
- package/dist/component-queue.d.ts +0 -0
- package/dist/component-queue.d.ts.map +0 -0
- package/dist/component-queue.js +118 -0
- package/dist/component-queue.js.map +1 -0
- package/dist/component-registry.d.ts +0 -0
- package/dist/component-registry.d.ts.map +0 -0
- package/dist/component-registry.js +298 -0
- package/dist/component-registry.js.map +1 -0
- package/dist/component.d.ts +8 -0
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js +1892 -0
- package/dist/component.js.map +1 -0
- package/dist/config.d.ts +0 -0
- package/dist/config.d.ts.map +0 -0
- package/dist/config.js +64 -0
- package/dist/config.js.map +1 -0
- package/dist/data-proxy.d.ts +0 -0
- package/dist/data-proxy.d.ts.map +0 -0
- package/dist/data-proxy.js +223 -0
- package/dist/data-proxy.js.map +1 -0
- package/dist/debug-entry.d.ts +0 -0
- package/dist/debug-entry.d.ts.map +0 -0
- package/dist/debug-entry.js +8 -0
- package/dist/debug-entry.js.map +1 -0
- package/dist/debug.d.ts +0 -0
- package/dist/debug.d.ts.map +0 -0
- package/dist/debug.js +203 -0
- package/dist/debug.js.map +1 -0
- package/dist/index.cjs +36 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -0
- package/dist/index.d.ts.map +0 -0
- package/dist/index.js +36 -8
- package/dist/index.js.map +1 -1
- package/dist/instruction-processor.d.ts +0 -0
- package/dist/instruction-processor.d.ts.map +1 -1
- package/dist/instruction-processor.js +563 -0
- package/dist/instruction-processor.js.map +1 -0
- package/dist/jqhtml-core.esm.js +37 -9
- package/dist/jqhtml-core.esm.js.map +1 -1
- package/dist/jqhtml-debug.esm.js +0 -0
- package/dist/jqhtml-debug.esm.js.map +0 -0
- package/dist/jquery-plugin.d.ts +0 -0
- package/dist/jquery-plugin.d.ts.map +0 -0
- package/dist/jquery-plugin.js +472 -0
- package/dist/jquery-plugin.js.map +1 -0
- package/dist/lifecycle-manager.d.ts +0 -0
- package/dist/lifecycle-manager.d.ts.map +0 -0
- package/dist/lifecycle-manager.js +201 -0
- package/dist/lifecycle-manager.js.map +1 -0
- package/dist/load-coordinator.d.ts +0 -0
- package/dist/load-coordinator.d.ts.map +1 -1
- package/dist/load-coordinator.js +309 -0
- package/dist/load-coordinator.js.map +1 -0
- package/dist/local-storage.d.ts +0 -0
- package/dist/local-storage.d.ts.map +0 -0
- package/dist/local-storage.js +699 -0
- package/dist/local-storage.js.map +1 -0
- package/dist/preload-data.d.ts +0 -0
- package/dist/preload-data.d.ts.map +0 -0
- package/dist/preload-data.js +136 -0
- package/dist/preload-data.js.map +1 -0
- package/dist/template-renderer.d.ts +0 -0
- package/dist/template-renderer.d.ts.map +0 -0
- package/dist/template-renderer.js +278 -0
- package/dist/template-renderer.js.map +1 -0
- package/dist/viewport.d.ts +0 -0
- package/dist/viewport.d.ts.map +0 -0
- package/dist/viewport.js +69 -0
- package/dist/viewport.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,9 @@ Components have a simple lifecycle: `on_load()` fetches data, `on_render()` sets
|
|
|
15
15
|
|
|
16
16
|
## Status
|
|
17
17
|
|
|
18
|
-
Alpha release. It works and I use it daily, but expect rough edges.
|
|
18
|
+
Alpha release. It works and I use it daily, but expect rough edges.
|
|
19
|
+
|
|
20
|
+
Full documentation: **[docs.jqhtml.org](https://docs.jqhtml.org/)**
|
|
19
21
|
|
|
20
22
|
If you try it in a project, I'd love to hear about it.
|
|
21
23
|
|
package/dist/boot.d.ts
CHANGED
|
File without changes
|
package/dist/boot.d.ts.map
CHANGED
|
File without changes
|
package/dist/boot.js
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JQHTML Boot - Component Hydration System
|
|
3
|
+
*
|
|
4
|
+
* Bridges server-rendered HTML and client-side jqhtml components.
|
|
5
|
+
*
|
|
6
|
+
* Server output: <div class="_Component_Init" data-component-init-name="User_Card" data-component-args='{"id":1}'></div>
|
|
7
|
+
* After boot(): <div class="User_Card Component">...rendered template...</div>
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* await jqhtml.boot(); // Hydrate all placeholders, wait for ready
|
|
11
|
+
* jqhtml.boot($('#container')); // Hydrate within scope
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Hydrate all _Component_Init placeholders within a scope.
|
|
15
|
+
*
|
|
16
|
+
* @param scope - jQuery object, HTMLElement, or undefined (defaults to body)
|
|
17
|
+
* @returns Promise that resolves when all components (including nested) are ready
|
|
18
|
+
*/
|
|
19
|
+
export function boot(scope) {
|
|
20
|
+
const jQ = typeof jQuery !== 'undefined' ? jQuery : $;
|
|
21
|
+
if (!scope) {
|
|
22
|
+
scope = jQ('body');
|
|
23
|
+
}
|
|
24
|
+
else if (!(scope instanceof jQ)) {
|
|
25
|
+
scope = jQ(scope);
|
|
26
|
+
}
|
|
27
|
+
const readyPromises = [];
|
|
28
|
+
// Find top-level placeholders only (skip those nested inside other placeholders)
|
|
29
|
+
scope.find('._Component_Init').each(function () {
|
|
30
|
+
const $element = jQ(this);
|
|
31
|
+
// Skip if removed from DOM
|
|
32
|
+
if (!document.contains($element[0])) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
// Skip nested placeholders - they'll be hydrated by parent's render callback
|
|
36
|
+
let parent = $element[0].parentElement;
|
|
37
|
+
while (parent) {
|
|
38
|
+
if (parent.classList.contains('_Component_Init')) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
parent = parent.parentElement;
|
|
42
|
+
}
|
|
43
|
+
// Hydrate this placeholder
|
|
44
|
+
const component = hydrateElement($element, jQ);
|
|
45
|
+
if (!component)
|
|
46
|
+
return;
|
|
47
|
+
// On render, recursively hydrate any nested placeholders
|
|
48
|
+
component.on('render', function () {
|
|
49
|
+
hydrateNested(component.$, jQ);
|
|
50
|
+
});
|
|
51
|
+
// Collect ready promise - parent.ready() waits for all children via _wait_for_children_ready()
|
|
52
|
+
readyPromises.push(component.ready());
|
|
53
|
+
});
|
|
54
|
+
// Fire jqhtml:ready event when all top-level components are ready
|
|
55
|
+
const result = Promise.all(readyPromises);
|
|
56
|
+
result.then(() => {
|
|
57
|
+
document.dispatchEvent(new CustomEvent('jqhtml:ready'));
|
|
58
|
+
});
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Hydrate nested _Component_Init placeholders within a component's DOM.
|
|
63
|
+
* Called from parent's 'render' event.
|
|
64
|
+
*/
|
|
65
|
+
function hydrateNested($scope, jQ) {
|
|
66
|
+
$scope.find('._Component_Init').each(function () {
|
|
67
|
+
const $element = jQ(this);
|
|
68
|
+
if (!document.contains($element[0])) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Skip if nested inside another placeholder
|
|
72
|
+
let parent = $element[0].parentElement;
|
|
73
|
+
while (parent && parent !== $scope[0]) {
|
|
74
|
+
if (parent.classList.contains('_Component_Init')) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
parent = parent.parentElement;
|
|
78
|
+
}
|
|
79
|
+
const component = hydrateElement($element, jQ);
|
|
80
|
+
if (!component)
|
|
81
|
+
return;
|
|
82
|
+
// Recursively handle deeper nesting
|
|
83
|
+
component.on('render', function () {
|
|
84
|
+
hydrateNested(component.$, jQ);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Hydrate a single _Component_Init element into a live component.
|
|
90
|
+
*/
|
|
91
|
+
function hydrateElement($element, jQ) {
|
|
92
|
+
const componentName = $element.attr('data-component-init-name');
|
|
93
|
+
if (!componentName)
|
|
94
|
+
return null;
|
|
95
|
+
// Parse args
|
|
96
|
+
const argsString = $element.attr('data-component-args');
|
|
97
|
+
let args = {};
|
|
98
|
+
if (argsString) {
|
|
99
|
+
try {
|
|
100
|
+
args = JSON.parse(argsString);
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
console.error(`[jqhtml.boot] Failed to parse args for ${componentName}:`, e);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// Strip data- prefix from args if present
|
|
107
|
+
const filteredArgs = {};
|
|
108
|
+
for (const [key, value] of Object.entries(args)) {
|
|
109
|
+
filteredArgs[key.startsWith('data-') ? key.substring(5) : key] = value;
|
|
110
|
+
}
|
|
111
|
+
// Capture innerHTML for content() and mark as boot-created
|
|
112
|
+
filteredArgs._inner_html = $element.html();
|
|
113
|
+
filteredArgs._component_name = componentName;
|
|
114
|
+
// Cleanup placeholder
|
|
115
|
+
$element.removeAttr('data-component-init-name');
|
|
116
|
+
$element.removeAttr('data-component-args');
|
|
117
|
+
$element.removeData('component-init-name');
|
|
118
|
+
$element.removeData('component-args');
|
|
119
|
+
$element.removeClass('_Component_Init');
|
|
120
|
+
$element.empty();
|
|
121
|
+
// Create component
|
|
122
|
+
try {
|
|
123
|
+
return $element.component(componentName, filteredArgs).component();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
console.error(`[jqhtml.boot] Failed to create ${componentName}:`, error);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=boot.js.map
|
package/dist/boot.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"boot.js","sourceRoot":"","sources":["../src/boot.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JQHTML Cache Key Serializer
|
|
3
|
+
*
|
|
4
|
+
* Produces a deterministic string for a plain-data argument value, so that two
|
|
5
|
+
* structurally equal objects built on separate renders yield the SAME cache key.
|
|
6
|
+
* Templates rebuild `{contact_id: 12}` on every render, so identity-based keying
|
|
7
|
+
* can never match and permanently opts the receiving component out of caching.
|
|
8
|
+
*
|
|
9
|
+
* ---------------------------------------------------------------------------
|
|
10
|
+
* THIS IS NOT `process_for_serialization()` IN local-storage.ts. DO NOT MERGE THEM.
|
|
11
|
+
*
|
|
12
|
+
* That serializer stores cache VALUES and deliberately degrades: a function, a
|
|
13
|
+
* symbol or a circular reference is dropped and serialization continues, because
|
|
14
|
+
* losing a method while keeping the data is the right trade for a payload.
|
|
15
|
+
*
|
|
16
|
+
* For a cache KEY that policy manufactures false hits. Two argument objects that
|
|
17
|
+
* differ ONLY by a callback would serialize identically, and a component would
|
|
18
|
+
* render with another component's cached content - strictly worse than not
|
|
19
|
+
* caching at all. So this serializer DECLINES on the first value it cannot
|
|
20
|
+
* express exactly. It never drops anything.
|
|
21
|
+
* ---------------------------------------------------------------------------
|
|
22
|
+
*
|
|
23
|
+
* Allow-list, and nothing else: null, undefined, boolean, number, string, Date,
|
|
24
|
+
* arrays, and plain objects (prototype Object.prototype or null), in any nesting.
|
|
25
|
+
* Everything else declines with a reason that reaches `data-nocache`.
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Values larger than this are declined rather than keyed. The supported case is a
|
|
29
|
+
* handful of key/value pairs or a list of ids - not a payload. Declining loudly
|
|
30
|
+
* beats spending the budget on a key nobody benefits from.
|
|
31
|
+
*/
|
|
32
|
+
export const MAX_KEY_BYTES = 500;
|
|
33
|
+
class Decline extends Error {
|
|
34
|
+
constructor(reason) {
|
|
35
|
+
super(reason);
|
|
36
|
+
this.reason = reason;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function push(state, text) {
|
|
40
|
+
state.size += text.length;
|
|
41
|
+
if (state.size > MAX_KEY_BYTES) {
|
|
42
|
+
throw new Decline('too-large');
|
|
43
|
+
}
|
|
44
|
+
return text;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Length-prefix strings so that no combination of separators can make two
|
|
48
|
+
* different structures produce the same text.
|
|
49
|
+
*/
|
|
50
|
+
function encode_string(state, prefix, value) {
|
|
51
|
+
return push(state, `${prefix}${value.length}:${value}`);
|
|
52
|
+
}
|
|
53
|
+
function walk(value, state) {
|
|
54
|
+
// --- primitives, each tagged so shapes cannot collide ---
|
|
55
|
+
if (value === null)
|
|
56
|
+
return push(state, 'n');
|
|
57
|
+
if (value === undefined)
|
|
58
|
+
return push(state, 'u');
|
|
59
|
+
const type = typeof value;
|
|
60
|
+
if (type === 'boolean')
|
|
61
|
+
return push(state, value ? 'b1' : 'b0');
|
|
62
|
+
if (type === 'number')
|
|
63
|
+
return push(state, `d${String(value)}`);
|
|
64
|
+
if (type === 'string')
|
|
65
|
+
return encode_string(state, 's', value);
|
|
66
|
+
if (type === 'function')
|
|
67
|
+
throw new Decline('function');
|
|
68
|
+
if (type === 'symbol')
|
|
69
|
+
throw new Decline('symbol');
|
|
70
|
+
if (type === 'bigint')
|
|
71
|
+
throw new Decline('bigint');
|
|
72
|
+
if (type !== 'object')
|
|
73
|
+
throw new Decline(type);
|
|
74
|
+
// --- objects: reject the impostors before treating anything as data ---
|
|
75
|
+
if (typeof value.nodeType === 'number')
|
|
76
|
+
throw new Decline('dom-node');
|
|
77
|
+
if (value.jquery)
|
|
78
|
+
throw new Decline('jquery');
|
|
79
|
+
if (state.seen.has(value))
|
|
80
|
+
throw new Decline('circular');
|
|
81
|
+
state.seen.add(value);
|
|
82
|
+
try {
|
|
83
|
+
if (value instanceof Date) {
|
|
84
|
+
const time = value.getTime();
|
|
85
|
+
if (Number.isNaN(time))
|
|
86
|
+
throw new Decline('invalid-date');
|
|
87
|
+
return push(state, `t${value.toISOString()}`);
|
|
88
|
+
}
|
|
89
|
+
if (Array.isArray(value)) {
|
|
90
|
+
// Order is meaningful - never sorted.
|
|
91
|
+
const parts = [];
|
|
92
|
+
push(state, 'a[');
|
|
93
|
+
for (let i = 0; i < value.length; i++) {
|
|
94
|
+
parts.push(walk(value[i], state));
|
|
95
|
+
}
|
|
96
|
+
push(state, ']');
|
|
97
|
+
return `a[${parts.join(',')}]`;
|
|
98
|
+
}
|
|
99
|
+
// Plain object ONLY. A class instance, Map, Set, RegExp, Error, etc. is
|
|
100
|
+
// declined: two different classes with identical fields would otherwise
|
|
101
|
+
// serialize the same and collide.
|
|
102
|
+
const proto = Object.getPrototypeOf(value);
|
|
103
|
+
if (proto !== Object.prototype && proto !== null) {
|
|
104
|
+
throw new Decline('non-plain-object');
|
|
105
|
+
}
|
|
106
|
+
// Recursive key sort - the existing top-level sort is not enough for nesting.
|
|
107
|
+
const keys = Object.keys(value).sort();
|
|
108
|
+
const parts = [];
|
|
109
|
+
push(state, 'o{');
|
|
110
|
+
for (const key of keys) {
|
|
111
|
+
const encoded_key = encode_string(state, 'k', key);
|
|
112
|
+
parts.push(`${encoded_key}=${walk(value[key], state)}`);
|
|
113
|
+
}
|
|
114
|
+
push(state, '}');
|
|
115
|
+
return `o{${parts.join(',')}}`;
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
state.seen.delete(value);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Serialize a value for use in a cache key.
|
|
123
|
+
*
|
|
124
|
+
* @returns `{ok: true, text}` when the value is exactly expressible, or
|
|
125
|
+
* `{ok: false, reason}` naming why it is not. Never throws.
|
|
126
|
+
*/
|
|
127
|
+
export function serialize_for_cache_key(value) {
|
|
128
|
+
const state = { seen: new WeakSet(), size: 0 };
|
|
129
|
+
try {
|
|
130
|
+
return { ok: true, text: walk(value, state) };
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (error instanceof Decline) {
|
|
134
|
+
return { ok: false, reason: error.reason };
|
|
135
|
+
}
|
|
136
|
+
// A throwing getter or exotic proxy trap - decline rather than guess.
|
|
137
|
+
return { ok: false, reason: 'unserializable' };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=cache-key-serializer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache-key-serializer.js","sourceRoot":"","sources":["../src/cache-key-serializer.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JQHTML Component Cache Integration
|
|
3
|
+
*
|
|
4
|
+
* Extracted from component.ts - handles cache key generation,
|
|
5
|
+
* cache reads during create(), cache checks during reload(),
|
|
6
|
+
* and HTML cache snapshots during ready().
|
|
7
|
+
*
|
|
8
|
+
* Uses Jqhtml_Local_Storage as the underlying storage layer.
|
|
9
|
+
*/
|
|
10
|
+
import { Load_Coordinator } from './load-coordinator.js';
|
|
11
|
+
import { Jqhtml_Local_Storage } from './local-storage.js';
|
|
12
|
+
import { warn_uncacheable_args_enabled } from './config.js';
|
|
13
|
+
/**
|
|
14
|
+
* Generate a cache key for a component using its name + args.
|
|
15
|
+
* Supports custom cache_id() override.
|
|
16
|
+
*
|
|
17
|
+
* @param component - The component instance
|
|
18
|
+
* @returns Cache key string or null if caching is disabled
|
|
19
|
+
*/
|
|
20
|
+
export function generate_cache_key(component) {
|
|
21
|
+
if (typeof component.cache_id === 'function') {
|
|
22
|
+
try {
|
|
23
|
+
const custom_cache_id = component.cache_id();
|
|
24
|
+
return { cache_key: `${component.component_name()}::${String(custom_cache_id)}` };
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
return { cache_key: null, uncacheable_property: 'cache_id()', uncacheable_reason: 'cache-id-threw' };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Standard args-based key. The CACHE opts into content serialization for plain-data
|
|
31
|
+
// object args; deduplication does not - see InvocationKeyOptions for why.
|
|
32
|
+
const result = Load_Coordinator.generate_invocation_key(component.component_name(), component.args, { allow_content_serialization: true });
|
|
33
|
+
return {
|
|
34
|
+
cache_key: result.key,
|
|
35
|
+
uncacheable_property: result.uncacheable_property,
|
|
36
|
+
uncacheable_reason: result.uncacheable_reason,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// One warning per component+property. A list of 50 rows must not print 50 warnings.
|
|
40
|
+
const _warned_uncacheable = new Set();
|
|
41
|
+
/**
|
|
42
|
+
* Development warning: this component fetches data but cannot be cached, because
|
|
43
|
+
* its args do not reduce to a stable key and it defines no cache_id() to say what
|
|
44
|
+
* its identity is. Nothing is broken - the component works - but it silently opts
|
|
45
|
+
* out of cache reuse and of load deduplication.
|
|
46
|
+
*
|
|
47
|
+
* Controlled by the `warn_uncacheable_args` integration flag (see config.ts).
|
|
48
|
+
*/
|
|
49
|
+
function warn_uncacheable_component(component, uncacheable_property, uncacheable_reason) {
|
|
50
|
+
if (!warn_uncacheable_args_enabled())
|
|
51
|
+
return;
|
|
52
|
+
let name = 'unknown';
|
|
53
|
+
try {
|
|
54
|
+
name = component.component_name();
|
|
55
|
+
}
|
|
56
|
+
catch { /* name unavailable */ }
|
|
57
|
+
const dedupe_key = `${name}::${uncacheable_property || '?'}::${uncacheable_reason || '?'}`;
|
|
58
|
+
if (_warned_uncacheable.has(dedupe_key))
|
|
59
|
+
return;
|
|
60
|
+
_warned_uncacheable.add(dedupe_key);
|
|
61
|
+
// cache_id() exists but threw - a different problem with a different fix
|
|
62
|
+
if (uncacheable_property === 'cache_id()' || uncacheable_reason === 'cache-id-threw') {
|
|
63
|
+
console.warn(`[JQHTML] <${name}> defines cache_id() but it threw, so this component is not cached ` +
|
|
64
|
+
`and its loads are not deduplicated. Fix cache_id() so it returns a stable string.`, { component: name, cid: component._cid });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const REASONS = {
|
|
68
|
+
'function': 'it contains a function - a callback is real identity that content cannot express',
|
|
69
|
+
'symbol': 'it contains a symbol',
|
|
70
|
+
'bigint': 'it contains a bigint',
|
|
71
|
+
'dom-node': 'it contains a DOM node',
|
|
72
|
+
'jquery': 'it contains a jQuery object',
|
|
73
|
+
'circular': 'it contains a circular reference',
|
|
74
|
+
'non-plain-object': 'it contains a class instance, Map, Set or similar - only plain objects and arrays can be keyed by content',
|
|
75
|
+
'too-large': 'it serializes to more than 500 bytes - args are meant to identify data, not carry it',
|
|
76
|
+
'invalid-date': 'it contains an invalid Date',
|
|
77
|
+
};
|
|
78
|
+
const why = REASONS[uncacheable_reason || ''] || 'it cannot be serialized deterministically';
|
|
79
|
+
console.warn(`[JQHTML] <${name}> cannot be cached: arg $${uncacheable_property} is not keyable because ` +
|
|
80
|
+
`${why}.\n` +
|
|
81
|
+
` The component works, but it will not be restored from cache when reused.\n` +
|
|
82
|
+
` Fix: define cache_id() on the component to state its identity explicitly, e.g.\n` +
|
|
83
|
+
` cache_id() { return \`${name.toLowerCase()}_\${this.args.some_id}\`; }\n` +
|
|
84
|
+
` Or pass plain data (objects/arrays of primitives are keyed automatically) instead of ` +
|
|
85
|
+
`$${uncacheable_property}.\n` +
|
|
86
|
+
` Find it in DevTools with the selector ` +
|
|
87
|
+
`[data-nocache="${uncacheable_property}:${uncacheable_reason || ''}"].`, {
|
|
88
|
+
component: name,
|
|
89
|
+
cid: component._cid,
|
|
90
|
+
uncacheable_arg: uncacheable_property,
|
|
91
|
+
reason: uncacheable_reason,
|
|
92
|
+
all_args: component.args ? Object.keys(component.args) : [],
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Read cache during create() phase.
|
|
97
|
+
* Sets component._cache_key, _cached_html, _use_cached_data_hit as side effects.
|
|
98
|
+
*
|
|
99
|
+
* @param component - The component instance
|
|
100
|
+
*/
|
|
101
|
+
export function read_cache_in_create(component) {
|
|
102
|
+
const { cache_key, uncacheable_property, uncacheable_reason } = generate_cache_key(component);
|
|
103
|
+
// If cache_key is null, caching disabled
|
|
104
|
+
if (cache_key === null) {
|
|
105
|
+
// Set data-nocache attribute for debugging
|
|
106
|
+
if (uncacheable_property) {
|
|
107
|
+
// "<arg>:<reason>" - a bare property name left authors reverse-engineering why
|
|
108
|
+
component.$.attr('data-nocache', uncacheable_reason ? `${uncacheable_property}:${uncacheable_reason}` : uncacheable_property);
|
|
109
|
+
}
|
|
110
|
+
warn_uncacheable_component(component, uncacheable_property, uncacheable_reason);
|
|
111
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
112
|
+
console.log(`[Cache] Component ${component._cid} (${component.component_name()}) has non-serializable args - caching disabled`, { uncacheable_property });
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Store cache key for later use
|
|
117
|
+
component._cache_key = cache_key;
|
|
118
|
+
// Get cache mode
|
|
119
|
+
const cache_mode = Jqhtml_Local_Storage.get_cache_mode();
|
|
120
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
121
|
+
console.log(`[Cache ${cache_mode}] Component ${component._cid} (${component.component_name()}) checking cache in create()`, { cache_key, cache_mode, has_cache_key_set: Jqhtml_Local_Storage.has_cache_key() });
|
|
122
|
+
}
|
|
123
|
+
if (cache_mode === 'html') {
|
|
124
|
+
// HTML cache mode - check for cached HTML to inject on first render
|
|
125
|
+
const html_cache_key = `${cache_key}::html`;
|
|
126
|
+
const cached_html = Jqhtml_Local_Storage.get(html_cache_key);
|
|
127
|
+
if (cached_html !== null && typeof cached_html === 'string') {
|
|
128
|
+
component._cached_html = cached_html;
|
|
129
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
130
|
+
console.log(`[Cache html] Component ${component._cid} (${component.component_name()}) found cached HTML`, { cache_key: html_cache_key, html_length: cached_html.length });
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
135
|
+
console.log(`[Cache html] Component ${component._cid} (${component.component_name()}) cache miss`, { cache_key: html_cache_key });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// Warn if use_cached_data is set in html cache mode
|
|
139
|
+
if (component.args.use_cached_data === true) {
|
|
140
|
+
console.warn(`[JQHTML] Component "${component.component_name()}" has use_cached_data=true but cache mode is 'html'.\n` +
|
|
141
|
+
`use_cached_data only applies to 'data' cache mode. In 'html' mode, the entire rendered HTML is cached.\n` +
|
|
142
|
+
`The use_cached_data flag will be ignored.`);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
// Data cache mode (default) - check for cached data to hydrate this.data
|
|
147
|
+
const cached_data = Jqhtml_Local_Storage.get(cache_key);
|
|
148
|
+
if (cached_data !== null && typeof cached_data === 'object') {
|
|
149
|
+
// Hydrate this.data with cached data
|
|
150
|
+
component.data = cached_data;
|
|
151
|
+
if (component.args.use_cached_data === true) {
|
|
152
|
+
component._use_cached_data_hit = true;
|
|
153
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
154
|
+
console.log(`[Cache data] Component ${component._cid} (${component.component_name()}) using cached data (use_cached_data=true, skipping on_load)`, { cache_key, data: cached_data });
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
159
|
+
console.log(`[Cache data] Component ${component._cid} (${component.component_name()}) hydrated from cache`, { cache_key, data: cached_data });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
165
|
+
console.log(`[Cache data] Component ${component._cid} (${component.component_name()}) cache miss`, { cache_key });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Check cache during reload() when args have changed.
|
|
172
|
+
* If cache hit, hydrates data/html and triggers an immediate render.
|
|
173
|
+
*
|
|
174
|
+
* @param component - The component instance
|
|
175
|
+
* @returns true if rendered from cache, false otherwise
|
|
176
|
+
*/
|
|
177
|
+
export function check_cache_on_reload(component) {
|
|
178
|
+
const { cache_key } = generate_cache_key(component);
|
|
179
|
+
if (cache_key === null) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
const cache_mode = Jqhtml_Local_Storage.get_cache_mode();
|
|
183
|
+
component._cache_key = cache_key;
|
|
184
|
+
if (cache_mode === 'html') {
|
|
185
|
+
// HTML cache mode - check for cached HTML
|
|
186
|
+
const html_cache_key = `${cache_key}::html`;
|
|
187
|
+
const cached_html = Jqhtml_Local_Storage.get(html_cache_key);
|
|
188
|
+
if (cached_html !== null && typeof cached_html === 'string') {
|
|
189
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
190
|
+
console.log(`[Cache html] reload() - Component ${component._cid} (${component.component_name()}) found cached HTML (args changed)`, { cache_key: html_cache_key, html_length: cached_html.length });
|
|
191
|
+
}
|
|
192
|
+
component._cached_html = cached_html;
|
|
193
|
+
// Call _render() directly (not render()) since _reload() manages the full lifecycle
|
|
194
|
+
// Using render() would trigger a separate queue entry and interfere with _reload()'s flow
|
|
195
|
+
component._render();
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
// Data cache mode (default) - check for cached data
|
|
201
|
+
const cached_data = Jqhtml_Local_Storage.get(cache_key);
|
|
202
|
+
if (cached_data !== null && typeof cached_data === 'object' && JSON.stringify(cached_data) !== '{}') {
|
|
203
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
204
|
+
console.log(`[Cache data] reload() - Component ${component._cid} (${component.component_name()}) hydrated from cache (args changed)`, { cache_key, data: cached_data });
|
|
205
|
+
}
|
|
206
|
+
// Hydrate this.data with cached data
|
|
207
|
+
component.__data_frozen = false;
|
|
208
|
+
component.data = cached_data;
|
|
209
|
+
component.__data_frozen = true;
|
|
210
|
+
// Call _render() directly (not render()) since _reload() manages the full lifecycle
|
|
211
|
+
component._render();
|
|
212
|
+
return true;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Write HTML cache snapshot during ready() phase.
|
|
219
|
+
* Only caches if the component is dynamic (data changed during on_load).
|
|
220
|
+
*
|
|
221
|
+
* @param component - The component instance
|
|
222
|
+
*/
|
|
223
|
+
export function write_html_cache_snapshot(component) {
|
|
224
|
+
if (!component._should_cache_html_after_ready || !component._cache_key) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (component._is_dynamic) {
|
|
228
|
+
component._should_cache_html_after_ready = false;
|
|
229
|
+
const html = component.$.html();
|
|
230
|
+
const html_cache_key = `${component._cache_key}::html`;
|
|
231
|
+
Jqhtml_Local_Storage.set(html_cache_key, html);
|
|
232
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
233
|
+
console.log(`[Cache html] Component ${component._cid} (${component.component_name()}) cached HTML after children on_render complete`, { cache_key: html_cache_key, html_length: html.length });
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
component._should_cache_html_after_ready = false;
|
|
238
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
239
|
+
console.log(`[Cache html] Component ${component._cid} (${component.component_name()}) is static (no data change) - skipping HTML cache`);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Write data/HTML to cache after on_load() completes.
|
|
245
|
+
* Called from _apply_load_result().
|
|
246
|
+
*
|
|
247
|
+
* @param component - The component instance
|
|
248
|
+
* @param data_changed - Whether this.data changed during on_load
|
|
249
|
+
*/
|
|
250
|
+
export function write_cache_on_loaded(component, data_changed) {
|
|
251
|
+
if (!data_changed || !component._cache_key) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const cache_mode = Jqhtml_Local_Storage.get_cache_mode();
|
|
255
|
+
if (cache_mode === 'html') {
|
|
256
|
+
// HTML cache mode - flag to cache HTML after children ready in _ready()
|
|
257
|
+
component._should_cache_html_after_ready = true;
|
|
258
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
259
|
+
console.log(`[Cache html] Component ${component._cid} (${component.component_name()}) will cache HTML after ready`, { cache_key: component._cache_key });
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
// Data cache mode (default) - write this.data to cache
|
|
264
|
+
Jqhtml_Local_Storage.set(component._cache_key, component.data);
|
|
265
|
+
if (window.jqhtml?.debug?.verbose) {
|
|
266
|
+
console.log(`[Cache data] Component ${component._cid} (${component.component_name()}) cached data after on_load()`, { cache_key: component._cache_key, data: component.data });
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=component-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-cache.js","sourceRoot":"","sources":["../src/component-cache.ts"],"names":[],"mappings":"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"}
|
|
File without changes
|
|
File without changes
|