@openelement/core 0.41.0-alpha.1
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/LICENSE +21 -0
- package/README.md +36 -0
- package/package.json +124 -0
- package/src/binding-activation.d.ts +2 -0
- package/src/binding-activation.js +254 -0
- package/src/binding-descriptor.d.ts +79 -0
- package/src/binding-descriptor.js +9 -0
- package/src/context.d.ts +32 -0
- package/src/context.js +76 -0
- package/src/csr.d.ts +13 -0
- package/src/csr.js +14 -0
- package/src/dsd-hydration-events.d.ts +2 -0
- package/src/dsd-hydration-events.js +13 -0
- package/src/dsd-hydration.d.ts +40 -0
- package/src/dsd-hydration.js +48 -0
- package/src/errors.d.ts +54 -0
- package/src/errors.js +113 -0
- package/src/event-hydration.d.ts +12 -0
- package/src/event-hydration.js +118 -0
- package/src/event-marker.d.ts +7 -0
- package/src/event-marker.js +54 -0
- package/src/html-escape.d.ts +29 -0
- package/src/html-escape.js +126 -0
- package/src/hydrate.d.ts +15 -0
- package/src/hydrate.js +15 -0
- package/src/index.d.ts +58 -0
- package/src/index.js +46 -0
- package/src/island-transform.d.ts +14 -0
- package/src/island-transform.js +60 -0
- package/src/island.d.ts +59 -0
- package/src/island.js +342 -0
- package/src/isr-runtime.d.ts +28 -0
- package/src/isr-runtime.js +99 -0
- package/src/isr.d.ts +22 -0
- package/src/isr.js +41 -0
- package/src/jsx-render-dom.d.ts +22 -0
- package/src/jsx-render-dom.js +376 -0
- package/src/jsx-runtime.d.ts +58 -0
- package/src/jsx-runtime.js +99 -0
- package/src/jsx-types.d.ts +46 -0
- package/src/logger.d.ts +15 -0
- package/src/logger.js +24 -0
- package/src/prop.d.ts +24 -0
- package/src/prop.js +160 -0
- package/src/registry.d.ts +17 -0
- package/src/registry.js +219 -0
- package/src/render-dsd-stream.d.ts +46 -0
- package/src/render-dsd-stream.js +86 -0
- package/src/render-dsd.d.ts +27 -0
- package/src/render-dsd.js +315 -0
- package/src/render-ir.d.ts +32 -0
- package/src/render-ir.js +245 -0
- package/src/runtime.d.ts +9 -0
- package/src/runtime.js +16 -0
- package/src/security.d.ts +1 -0
- package/src/security.js +40 -0
- package/src/signal-context.d.ts +15 -0
- package/src/signal-context.js +59 -0
- package/src/static.d.ts +35 -0
- package/src/static.js +34 -0
- package/src/style-sheet.d.ts +9 -0
- package/src/style-sheet.js +56 -0
- package/src/tag-utils.d.ts +11 -0
- package/src/tag-utils.js +28 -0
- package/src/vnode.d.ts +15 -0
- package/src/vnode.js +31 -0
package/src/logger.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/core - Tagged console logger.
|
|
3
|
+
*
|
|
4
|
+
* Lightweight scoped logger. Returns plain functions so it is tree-shakable
|
|
5
|
+
* and has zero class overhead.
|
|
6
|
+
*
|
|
7
|
+
* @module @openelement/core/logger
|
|
8
|
+
*/ export function createLogger(tag) {
|
|
9
|
+
return {
|
|
10
|
+
debug: (msg, ...args)=>console.debug(`[${tag}] ${msg}`, ...args),
|
|
11
|
+
info: (msg, ...args)=>console.info(`[${tag}] ${msg}`, ...args),
|
|
12
|
+
warn: (msg, ...args)=>console.warn(`[${tag}] ${msg}`, ...args),
|
|
13
|
+
error: (msg, ...args)=>console.error(`[${tag}] ${msg}`, ...args)
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
// ponytail: warn-once via Set, two callers, shared helper if >3 callers
|
|
17
|
+
const _warned = new Set();
|
|
18
|
+
export function warnOnce(key, logger, msg) {
|
|
19
|
+
if (!_warned.has(key)) {
|
|
20
|
+
_warned.add(key);
|
|
21
|
+
logger.warn(msg);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9sb2dnZXIudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAb3BlbmVsZW1lbnQvY29yZSAtIFRhZ2dlZCBjb25zb2xlIGxvZ2dlci5cbiAqXG4gKiBMaWdodHdlaWdodCBzY29wZWQgbG9nZ2VyLiBSZXR1cm5zIHBsYWluIGZ1bmN0aW9ucyBzbyBpdCBpcyB0cmVlLXNoYWthYmxlXG4gKiBhbmQgaGFzIHplcm8gY2xhc3Mgb3ZlcmhlYWQuXG4gKlxuICogQG1vZHVsZSBAb3BlbmVsZW1lbnQvY29yZS9sb2dnZXJcbiAqL1xuXG5leHBvcnQgaW50ZXJmYWNlIExvZ2dlciB7XG4gIGRlYnVnOiAobXNnOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSkgPT4gdm9pZDtcbiAgaW5mbzogKG1zZzogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pID0+IHZvaWQ7XG4gIHdhcm46IChtc2c6IHN0cmluZywgLi4uYXJnczogdW5rbm93bltdKSA9PiB2b2lkO1xuICBlcnJvcjogKG1zZzogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pID0+IHZvaWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVMb2dnZXIodGFnOiBzdHJpbmcpOiBMb2dnZXIge1xuICByZXR1cm4ge1xuICAgIGRlYnVnOiAobXNnOiBzdHJpbmcsIC4uLmFyZ3M6IHVua25vd25bXSkgPT4gY29uc29sZS5kZWJ1ZyhgWyR7dGFnfV0gJHttc2d9YCwgLi4uYXJncyksXG4gICAgaW5mbzogKG1zZzogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pID0+IGNvbnNvbGUuaW5mbyhgWyR7dGFnfV0gJHttc2d9YCwgLi4uYXJncyksXG4gICAgd2FybjogKG1zZzogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pID0+IGNvbnNvbGUud2FybihgWyR7dGFnfV0gJHttc2d9YCwgLi4uYXJncyksXG4gICAgZXJyb3I6IChtc2c6IHN0cmluZywgLi4uYXJnczogdW5rbm93bltdKSA9PiBjb25zb2xlLmVycm9yKGBbJHt0YWd9XSAke21zZ31gLCAuLi5hcmdzKSxcbiAgfTtcbn1cblxuLy8gcG9ueXRhaWw6IHdhcm4tb25jZSB2aWEgU2V0LCB0d28gY2FsbGVycywgc2hhcmVkIGhlbHBlciBpZiA+MyBjYWxsZXJzXG5jb25zdCBfd2FybmVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG5leHBvcnQgZnVuY3Rpb24gd2Fybk9uY2Uoa2V5OiBzdHJpbmcsIGxvZ2dlcjogTG9nZ2VyLCBtc2c6IHN0cmluZyk6IHZvaWQge1xuICBpZiAoIV93YXJuZWQuaGFzKGtleSkpIHtcbiAgICBfd2FybmVkLmFkZChrZXkpO1xuICAgIGxvZ2dlci53YXJuKG1zZyk7XG4gIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7OztDQU9DLEdBU0QsT0FBTyxTQUFTLGFBQWEsR0FBVztFQUN0QyxPQUFPO0lBQ0wsT0FBTyxDQUFDLEtBQWEsR0FBRyxPQUFvQixRQUFRLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEtBQUs7SUFDaEYsTUFBTSxDQUFDLEtBQWEsR0FBRyxPQUFvQixRQUFRLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEtBQUs7SUFDOUUsTUFBTSxDQUFDLEtBQWEsR0FBRyxPQUFvQixRQUFRLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEtBQUs7SUFDOUUsT0FBTyxDQUFDLEtBQWEsR0FBRyxPQUFvQixRQUFRLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRSxLQUFLLEtBQUs7RUFDbEY7QUFDRjtBQUVBLHdFQUF3RTtBQUN4RSxNQUFNLFVBQVUsSUFBSTtBQUNwQixPQUFPLFNBQVMsU0FBUyxHQUFXLEVBQUUsTUFBYyxFQUFFLEdBQVc7RUFDL0QsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLE1BQU07SUFDckIsUUFBUSxHQUFHLENBQUM7SUFDWixPQUFPLElBQUksQ0FBQztFQUNkO0FBQ0YifQ==
|
package/src/prop.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/core — Reactive property runtime.
|
|
3
|
+
*
|
|
4
|
+
* ADR-0057: static props + Signal model.
|
|
5
|
+
*
|
|
6
|
+
* v0.29.5: WeakMap replaces Symbol.for() for type-safe signal storage.
|
|
7
|
+
*/ interface _El extends HTMLElement {
|
|
8
|
+
}
|
|
9
|
+
import type { PropDecl, PropDeclFull, PropDeclShorthand, PropsFrom, PropType } from '@openelement/protocol/prop';
|
|
10
|
+
export type { PropDecl, PropDeclFull, PropDeclShorthand, PropsFrom, PropType };
|
|
11
|
+
export declare function initializeStaticProps(instance: _El): void;
|
|
12
|
+
export declare function disposeStaticProps(instance: _El): void;
|
|
13
|
+
export declare function handleStaticPropAttributeChange(instance: _El, name: string, _oldValue: string | null, newValue: string | null): void;
|
|
14
|
+
export declare function syncStaticPropsFromAttributes(instance: _El): void;
|
|
15
|
+
export declare function unwrap<T>(sig: {
|
|
16
|
+
value: T;
|
|
17
|
+
} | T): T;
|
|
18
|
+
import type { NormalizedPropDecl } from '@openelement/protocol/prop';
|
|
19
|
+
export type { NormalizedPropDecl };
|
|
20
|
+
export declare function normalizePropDecl(decl: unknown): NormalizedPropDecl;
|
|
21
|
+
export declare function registerStaticObservedAttributes(ctor: {
|
|
22
|
+
props?: Record<string, unknown>;
|
|
23
|
+
observedAttributes?: string[];
|
|
24
|
+
}, propsDef: Record<string, unknown>): void;
|
package/src/prop.js
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/core — Reactive property runtime.
|
|
3
|
+
*
|
|
4
|
+
* ADR-0057: static props + Signal model.
|
|
5
|
+
*
|
|
6
|
+
* v0.29.5: WeakMap replaces Symbol.for() for type-safe signal storage.
|
|
7
|
+
*/ // Minimal element interface for core WeakMap identity
|
|
8
|
+
// ─── WeakMap storage (v0.29.5: replaces Symbol.for()) ───────────
|
|
9
|
+
const _staticPropSignals = new WeakMap();
|
|
10
|
+
const _staticPropUnsubs = new WeakMap();
|
|
11
|
+
// ─── Static props runtime ───────────────────────────────────────
|
|
12
|
+
export function initializeStaticProps(instance) {
|
|
13
|
+
const ctor = instance.constructor;
|
|
14
|
+
const propsDef = ctor.props;
|
|
15
|
+
if (!propsDef || typeof propsDef !== 'object') return;
|
|
16
|
+
const sigMap = new Map();
|
|
17
|
+
_staticPropSignals.set(instance, sigMap);
|
|
18
|
+
const unsubs = [];
|
|
19
|
+
_staticPropUnsubs.set(instance, unsubs);
|
|
20
|
+
for (const [name, decl] of Object.entries(propsDef)){
|
|
21
|
+
const { default: defVal, reflect } = normalizePropDecl(decl);
|
|
22
|
+
const sig = createPropSignal(defVal);
|
|
23
|
+
sigMap.set(name, sig);
|
|
24
|
+
Object.defineProperty(instance, name, {
|
|
25
|
+
get () {
|
|
26
|
+
return sig;
|
|
27
|
+
},
|
|
28
|
+
set (v1) {
|
|
29
|
+
sig.value = v1;
|
|
30
|
+
},
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true
|
|
33
|
+
});
|
|
34
|
+
if (reflect) {
|
|
35
|
+
const unsub = sig.subscribe(()=>{
|
|
36
|
+
const { type } = normalizePropDecl(decl);
|
|
37
|
+
if (type === Boolean) {
|
|
38
|
+
if (sig.value) instance.setAttribute(name, '');
|
|
39
|
+
else instance.removeAttribute(name);
|
|
40
|
+
} else {
|
|
41
|
+
instance.setAttribute(name, String(sig.value));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
unsubs.push(unsub);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
registerStaticObservedAttributes(ctor, propsDef);
|
|
48
|
+
}
|
|
49
|
+
export function disposeStaticProps(instance) {
|
|
50
|
+
const unsubs = _staticPropUnsubs.get(instance);
|
|
51
|
+
if (unsubs) {
|
|
52
|
+
for (const fn of unsubs.splice(0))fn();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function handleStaticPropAttributeChange(instance, name, _oldValue, newValue) {
|
|
56
|
+
const sigMap = _staticPropSignals.get(instance);
|
|
57
|
+
if (!sigMap) return;
|
|
58
|
+
const ctor = instance.constructor;
|
|
59
|
+
const propsDef = ctor.props;
|
|
60
|
+
if (!propsDef) return;
|
|
61
|
+
for (const [propName, decl] of Object.entries(propsDef)){
|
|
62
|
+
if (propName.toLowerCase() !== name.toLowerCase()) continue;
|
|
63
|
+
const sig = sigMap.get(propName);
|
|
64
|
+
if (!sig) continue;
|
|
65
|
+
const { type } = normalizePropDecl(decl);
|
|
66
|
+
if (newValue === null) {
|
|
67
|
+
sig.value = type === Boolean ? false : type === Number ? 0 : '';
|
|
68
|
+
} else if (type === Boolean) {
|
|
69
|
+
sig.value = true;
|
|
70
|
+
} else if (type === Number) {
|
|
71
|
+
const n = Number(newValue);
|
|
72
|
+
sig.value = Number.isNaN(n) ? 0 : n;
|
|
73
|
+
} else {
|
|
74
|
+
sig.value = newValue;
|
|
75
|
+
}
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function syncStaticPropsFromAttributes(instance) {
|
|
80
|
+
const ctor = instance.constructor;
|
|
81
|
+
const propsDef = ctor.props;
|
|
82
|
+
if (!propsDef) return;
|
|
83
|
+
const sigMap = _staticPropSignals.get(instance);
|
|
84
|
+
if (!sigMap) return;
|
|
85
|
+
const el = instance;
|
|
86
|
+
for (const [name, decl] of Object.entries(propsDef)){
|
|
87
|
+
const sig = sigMap.get(name);
|
|
88
|
+
if (!sig) continue;
|
|
89
|
+
if (el.hasAttribute(name)) {
|
|
90
|
+
const { type } = normalizePropDecl(decl);
|
|
91
|
+
const raw = el.getAttribute(name);
|
|
92
|
+
if (raw === null) continue;
|
|
93
|
+
if (type === Boolean) {
|
|
94
|
+
sig.value = true;
|
|
95
|
+
} else if (type === Number) {
|
|
96
|
+
const n = Number(raw);
|
|
97
|
+
sig.value = Number.isNaN(n) ? 0 : n;
|
|
98
|
+
} else {
|
|
99
|
+
sig.value = raw;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export function unwrap(sig) {
|
|
105
|
+
if (sig !== null && typeof sig === 'object' && 'value' in sig && 'subscribe' in sig) {
|
|
106
|
+
return sig.value;
|
|
107
|
+
}
|
|
108
|
+
return sig;
|
|
109
|
+
}
|
|
110
|
+
export function normalizePropDecl(decl) {
|
|
111
|
+
if (typeof decl === 'function') {
|
|
112
|
+
return {
|
|
113
|
+
type: decl,
|
|
114
|
+
default: decl === Boolean ? false : decl === Number ? 0 : '',
|
|
115
|
+
reflect: false
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
if (decl && typeof decl === 'object') {
|
|
119
|
+
const d = decl;
|
|
120
|
+
return {
|
|
121
|
+
type: d.type ?? String,
|
|
122
|
+
default: d.default ?? (d.type === Boolean ? false : d.type === Number ? 0 : ''),
|
|
123
|
+
reflect: d.reflect === true
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
type: String,
|
|
128
|
+
default: '',
|
|
129
|
+
reflect: false
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
export function registerStaticObservedAttributes(ctor, propsDef) {
|
|
133
|
+
if (!ctor.observedAttributes) {
|
|
134
|
+
ctor.observedAttributes = [];
|
|
135
|
+
}
|
|
136
|
+
for (const name of Object.keys(propsDef)){
|
|
137
|
+
if (!ctor.observedAttributes.includes(name.toLowerCase())) {
|
|
138
|
+
ctor.observedAttributes.push(name.toLowerCase());
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function createPropSignal(initial) {
|
|
143
|
+
let _value = initial;
|
|
144
|
+
const _subs = new Set();
|
|
145
|
+
return {
|
|
146
|
+
get value () {
|
|
147
|
+
return _value;
|
|
148
|
+
},
|
|
149
|
+
set value (v){
|
|
150
|
+
_value = v;
|
|
151
|
+
for (const fn of _subs)fn(v);
|
|
152
|
+
},
|
|
153
|
+
subscribe (fn) {
|
|
154
|
+
_subs.add(fn);
|
|
155
|
+
fn(_value);
|
|
156
|
+
return ()=>_subs.delete(fn);
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9wcm9wLnRzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQG9wZW5lbGVtZW50L2NvcmUg4oCUIFJlYWN0aXZlIHByb3BlcnR5IHJ1bnRpbWUuXG4gKlxuICogQURSLTAwNTc6IHN0YXRpYyBwcm9wcyArIFNpZ25hbCBtb2RlbC5cbiAqXG4gKiB2MC4yOS41OiBXZWFrTWFwIHJlcGxhY2VzIFN5bWJvbC5mb3IoKSBmb3IgdHlwZS1zYWZlIHNpZ25hbCBzdG9yYWdlLlxuICovXG5cbi8vIE1pbmltYWwgZWxlbWVudCBpbnRlcmZhY2UgZm9yIGNvcmUgV2Vha01hcCBpZGVudGl0eVxuaW50ZXJmYWNlIF9FbCBleHRlbmRzIEhUTUxFbGVtZW50IHt9XG5cbmltcG9ydCB0eXBlIHtcbiAgUHJvcERlY2wsXG4gIFByb3BEZWNsRnVsbCxcbiAgUHJvcERlY2xTaG9ydGhhbmQsXG4gIFByb3BzRnJvbSxcbiAgUHJvcFR5cGUsXG59IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9wcm9wJztcbmV4cG9ydCB0eXBlIHsgUHJvcERlY2wsIFByb3BEZWNsRnVsbCwgUHJvcERlY2xTaG9ydGhhbmQsIFByb3BzRnJvbSwgUHJvcFR5cGUgfTtcblxuLy8g4pSA4pSA4pSAIEludGVybmFsIHR5cGVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG50eXBlIFByb3BTaWduYWwgPSB7IHZhbHVlOiB1bmtub3duOyBzdWJzY3JpYmUoZm46ICh2OiB1bmtub3duKSA9PiB2b2lkKTogKCkgPT4gdm9pZCB9O1xuXG4vLyDilIDilIDilIAgV2Vha01hcCBzdG9yYWdlICh2MC4yOS41OiByZXBsYWNlcyBTeW1ib2wuZm9yKCkpIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5jb25zdCBfc3RhdGljUHJvcFNpZ25hbHMgPSBuZXcgV2Vha01hcDxfRWwsIE1hcDxzdHJpbmcsIFByb3BTaWduYWw+PigpO1xuY29uc3QgX3N0YXRpY1Byb3BVbnN1YnMgPSBuZXcgV2Vha01hcDxfRWwsIEFycmF5PCgpID0+IHZvaWQ+PigpO1xuXG4vLyDilIDilIDilIAgU3RhdGljIHByb3BzIHJ1bnRpbWUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbmV4cG9ydCBmdW5jdGlvbiBpbml0aWFsaXplU3RhdGljUHJvcHMoaW5zdGFuY2U6IF9FbCk6IHZvaWQge1xuICBjb25zdCBjdG9yID0gaW5zdGFuY2UuY29uc3RydWN0b3IgYXMgeyBwcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH07XG4gIGNvbnN0IHByb3BzRGVmID0gY3Rvci5wcm9wcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcbiAgaWYgKCFwcm9wc0RlZiB8fCB0eXBlb2YgcHJvcHNEZWYgIT09ICdvYmplY3QnKSByZXR1cm47XG5cbiAgY29uc3Qgc2lnTWFwID0gbmV3IE1hcDxzdHJpbmcsIFByb3BTaWduYWw+KCk7XG4gIF9zdGF0aWNQcm9wU2lnbmFscy5zZXQoaW5zdGFuY2UsIHNpZ01hcCk7XG5cbiAgY29uc3QgdW5zdWJzOiBBcnJheTwoKSA9PiB2b2lkPiA9IFtdO1xuICBfc3RhdGljUHJvcFVuc3Vicy5zZXQoaW5zdGFuY2UsIHVuc3Vicyk7XG5cbiAgZm9yIChjb25zdCBbbmFtZSwgZGVjbF0gb2YgT2JqZWN0LmVudHJpZXMocHJvcHNEZWYpKSB7XG4gICAgY29uc3QgeyBkZWZhdWx0OiBkZWZWYWwsIHJlZmxlY3QgfSA9IG5vcm1hbGl6ZVByb3BEZWNsKGRlY2wpO1xuICAgIGNvbnN0IHNpZyA9IGNyZWF0ZVByb3BTaWduYWwoZGVmVmFsKTtcblxuICAgIHNpZ01hcC5zZXQobmFtZSwgc2lnKTtcblxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShpbnN0YW5jZSwgbmFtZSwge1xuICAgICAgZ2V0KCkge1xuICAgICAgICByZXR1cm4gc2lnO1xuICAgICAgfSxcbiAgICAgIHNldCh2OiB1bmtub3duKSB7XG4gICAgICAgIHNpZy52YWx1ZSA9IHY7XG4gICAgICB9LFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICB9KTtcblxuICAgIGlmIChyZWZsZWN0KSB7XG4gICAgICBjb25zdCB1bnN1YiA9IHNpZy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICBjb25zdCB7IHR5cGUgfSA9IG5vcm1hbGl6ZVByb3BEZWNsKGRlY2wpO1xuICAgICAgICBpZiAodHlwZSA9PT0gQm9vbGVhbikge1xuICAgICAgICAgIGlmIChzaWcudmFsdWUpIGluc3RhbmNlLnNldEF0dHJpYnV0ZShuYW1lLCAnJyk7XG4gICAgICAgICAgZWxzZSBpbnN0YW5jZS5yZW1vdmVBdHRyaWJ1dGUobmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaW5zdGFuY2Uuc2V0QXR0cmlidXRlKG5hbWUsIFN0cmluZyhzaWcudmFsdWUpKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICB1bnN1YnMucHVzaCh1bnN1Yik7XG4gICAgfVxuICB9XG5cbiAgcmVnaXN0ZXJTdGF0aWNPYnNlcnZlZEF0dHJpYnV0ZXMoY3RvciwgcHJvcHNEZWYpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGlzcG9zZVN0YXRpY1Byb3BzKGluc3RhbmNlOiBfRWwpOiB2b2lkIHtcbiAgY29uc3QgdW5zdWJzID0gX3N0YXRpY1Byb3BVbnN1YnMuZ2V0KGluc3RhbmNlKTtcbiAgaWYgKHVuc3Vicykge1xuICAgIGZvciAoY29uc3QgZm4gb2YgdW5zdWJzLnNwbGljZSgwKSkgZm4oKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFuZGxlU3RhdGljUHJvcEF0dHJpYnV0ZUNoYW5nZShcbiAgaW5zdGFuY2U6IF9FbCxcbiAgbmFtZTogc3RyaW5nLFxuICBfb2xkVmFsdWU6IHN0cmluZyB8IG51bGwsXG4gIG5ld1ZhbHVlOiBzdHJpbmcgfCBudWxsLFxuKTogdm9pZCB7XG4gIGNvbnN0IHNpZ01hcCA9IF9zdGF0aWNQcm9wU2lnbmFscy5nZXQoaW5zdGFuY2UpO1xuICBpZiAoIXNpZ01hcCkgcmV0dXJuO1xuXG4gIGNvbnN0IGN0b3IgPSBpbnN0YW5jZS5jb25zdHJ1Y3RvciBhcyB7IHByb3BzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gfTtcbiAgY29uc3QgcHJvcHNEZWYgPSBjdG9yLnByb3BzIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkO1xuICBpZiAoIXByb3BzRGVmKSByZXR1cm47XG5cbiAgZm9yIChjb25zdCBbcHJvcE5hbWUsIGRlY2xdIG9mIE9iamVjdC5lbnRyaWVzKHByb3BzRGVmKSkge1xuICAgIGlmIChwcm9wTmFtZS50b0xvd2VyQ2FzZSgpICE9PSBuYW1lLnRvTG93ZXJDYXNlKCkpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHNpZyA9IHNpZ01hcC5nZXQocHJvcE5hbWUpO1xuICAgIGlmICghc2lnKSBjb250aW51ZTtcbiAgICBjb25zdCB7IHR5cGUgfSA9IG5vcm1hbGl6ZVByb3BEZWNsKGRlY2wpO1xuICAgIGlmIChuZXdWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgc2lnLnZhbHVlID0gdHlwZSA9PT0gQm9vbGVhbiA/IGZhbHNlIDogdHlwZSA9PT0gTnVtYmVyID8gMCA6ICcnO1xuICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gQm9vbGVhbikge1xuICAgICAgc2lnLnZhbHVlID0gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKHR5cGUgPT09IE51bWJlcikge1xuICAgICAgY29uc3QgbiA9IE51bWJlcihuZXdWYWx1ZSk7XG4gICAgICBzaWcudmFsdWUgPSBOdW1iZXIuaXNOYU4obikgPyAwIDogbjtcbiAgICB9IGVsc2Uge1xuICAgICAgc2lnLnZhbHVlID0gbmV3VmFsdWU7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3luY1N0YXRpY1Byb3BzRnJvbUF0dHJpYnV0ZXMoaW5zdGFuY2U6IF9FbCk6IHZvaWQge1xuICBjb25zdCBjdG9yID0gaW5zdGFuY2UuY29uc3RydWN0b3IgYXMgeyBwcm9wcz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+IH07XG4gIGNvbnN0IHByb3BzRGVmID0gY3Rvci5wcm9wcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IHVuZGVmaW5lZDtcbiAgaWYgKCFwcm9wc0RlZikgcmV0dXJuO1xuXG4gIGNvbnN0IHNpZ01hcCA9IF9zdGF0aWNQcm9wU2lnbmFscy5nZXQoaW5zdGFuY2UpO1xuICBpZiAoIXNpZ01hcCkgcmV0dXJuO1xuXG4gIGNvbnN0IGVsID0gaW5zdGFuY2UgYXMgdW5rbm93biBhcyB7XG4gICAgZ2V0QXR0cmlidXRlKG46IHN0cmluZyk6IHN0cmluZyB8IG51bGw7XG4gICAgaGFzQXR0cmlidXRlKG46IHN0cmluZyk6IGJvb2xlYW47XG4gIH07XG5cbiAgZm9yIChjb25zdCBbbmFtZSwgZGVjbF0gb2YgT2JqZWN0LmVudHJpZXMocHJvcHNEZWYpKSB7XG4gICAgY29uc3Qgc2lnID0gc2lnTWFwLmdldChuYW1lKTtcbiAgICBpZiAoIXNpZykgY29udGludWU7XG4gICAgaWYgKGVsLmhhc0F0dHJpYnV0ZShuYW1lKSkge1xuICAgICAgY29uc3QgeyB0eXBlIH0gPSBub3JtYWxpemVQcm9wRGVjbChkZWNsKTtcbiAgICAgIGNvbnN0IHJhdyA9IGVsLmdldEF0dHJpYnV0ZShuYW1lKTtcbiAgICAgIGlmIChyYXcgPT09IG51bGwpIGNvbnRpbnVlO1xuICAgICAgaWYgKHR5cGUgPT09IEJvb2xlYW4pIHtcbiAgICAgICAgc2lnLnZhbHVlID0gdHJ1ZTtcbiAgICAgIH0gZWxzZSBpZiAodHlwZSA9PT0gTnVtYmVyKSB7XG4gICAgICAgIGNvbnN0IG4gPSBOdW1iZXIocmF3KTtcbiAgICAgICAgc2lnLnZhbHVlID0gTnVtYmVyLmlzTmFOKG4pID8gMCA6IG47XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaWcudmFsdWUgPSByYXc7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bndyYXA8VD4oc2lnOiB7IHZhbHVlOiBUIH0gfCBUKTogVCB7XG4gIGlmIChcbiAgICBzaWcgIT09IG51bGwgJiYgdHlwZW9mIHNpZyA9PT0gJ29iamVjdCcgJiYgJ3ZhbHVlJyBpbiAoc2lnIGFzIG9iamVjdCkgJiZcbiAgICAnc3Vic2NyaWJlJyBpbiAoc2lnIGFzIG9iamVjdClcbiAgKSB7XG4gICAgcmV0dXJuIChzaWcgYXMgeyB2YWx1ZTogVCB9KS52YWx1ZTtcbiAgfVxuICByZXR1cm4gc2lnIGFzIFQ7XG59XG5cbi8vIOKUgOKUgOKUgCBTaGFyZWQgdXRpbGl0aWVzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG5pbXBvcnQgdHlwZSB7IE5vcm1hbGl6ZWRQcm9wRGVjbCB9IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9wcm9wJztcbmV4cG9ydCB0eXBlIHsgTm9ybWFsaXplZFByb3BEZWNsIH07XG5cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVQcm9wRGVjbChkZWNsOiB1bmtub3duKTogTm9ybWFsaXplZFByb3BEZWNsIHtcbiAgaWYgKHR5cGVvZiBkZWNsID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IGRlY2wgYXMgTm9ybWFsaXplZFByb3BEZWNsWyd0eXBlJ10sXG4gICAgICBkZWZhdWx0OiBkZWNsID09PSBCb29sZWFuID8gZmFsc2UgOiBkZWNsID09PSBOdW1iZXIgPyAwIDogJycsXG4gICAgICByZWZsZWN0OiBmYWxzZSxcbiAgICB9O1xuICB9XG4gIGlmIChkZWNsICYmIHR5cGVvZiBkZWNsID09PSAnb2JqZWN0Jykge1xuICAgIGNvbnN0IGQgPSBkZWNsIGFzIHsgdHlwZT86IHVua25vd247IGRlZmF1bHQ/OiB1bmtub3duOyByZWZsZWN0PzogdW5rbm93biB9O1xuICAgIHJldHVybiB7XG4gICAgICB0eXBlOiAoZC50eXBlID8/IFN0cmluZykgYXMgTm9ybWFsaXplZFByb3BEZWNsWyd0eXBlJ10sXG4gICAgICBkZWZhdWx0OiBkLmRlZmF1bHQgPz8gKGQudHlwZSA9PT0gQm9vbGVhbiA/IGZhbHNlIDogZC50eXBlID09PSBOdW1iZXIgPyAwIDogJycpLFxuICAgICAgcmVmbGVjdDogZC5yZWZsZWN0ID09PSB0cnVlLFxuICAgIH07XG4gIH1cbiAgcmV0dXJuIHsgdHlwZTogU3RyaW5nLCBkZWZhdWx0OiAnJywgcmVmbGVjdDogZmFsc2UgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lzdGVyU3RhdGljT2JzZXJ2ZWRBdHRyaWJ1dGVzKFxuICBjdG9yOiB7IHByb3BzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47IG9ic2VydmVkQXR0cmlidXRlcz86IHN0cmluZ1tdIH0sXG4gIHByb3BzRGVmOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbik6IHZvaWQge1xuICBpZiAoIWN0b3Iub2JzZXJ2ZWRBdHRyaWJ1dGVzKSB7XG4gICAgY3Rvci5vYnNlcnZlZEF0dHJpYnV0ZXMgPSBbXTtcbiAgfVxuICBmb3IgKGNvbnN0IG5hbWUgb2YgT2JqZWN0LmtleXMocHJvcHNEZWYpKSB7XG4gICAgaWYgKCFjdG9yLm9ic2VydmVkQXR0cmlidXRlcy5pbmNsdWRlcyhuYW1lLnRvTG93ZXJDYXNlKCkpKSB7XG4gICAgICBjdG9yLm9ic2VydmVkQXR0cmlidXRlcy5wdXNoKG5hbWUudG9Mb3dlckNhc2UoKSk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVByb3BTaWduYWwoaW5pdGlhbDogdW5rbm93bik6IFByb3BTaWduYWwge1xuICBsZXQgX3ZhbHVlID0gaW5pdGlhbDtcbiAgY29uc3QgX3N1YnMgPSBuZXcgU2V0PCh2OiB1bmtub3duKSA9PiB2b2lkPigpO1xuXG4gIHJldHVybiB7XG4gICAgZ2V0IHZhbHVlKCk6IHVua25vd24ge1xuICAgICAgcmV0dXJuIF92YWx1ZTtcbiAgICB9LFxuICAgIHNldCB2YWx1ZSh2OiB1bmtub3duKSB7XG4gICAgICBfdmFsdWUgPSB2O1xuICAgICAgZm9yIChjb25zdCBmbiBvZiBfc3VicykgZm4odik7XG4gICAgfSxcbiAgICBzdWJzY3JpYmUoZm46ICh2OiB1bmtub3duKSA9PiB2b2lkKTogKCkgPT4gdm9pZCB7XG4gICAgICBfc3Vicy5hZGQoZm4pO1xuICAgICAgZm4oX3ZhbHVlKTtcbiAgICAgIHJldHVybiAoKSA9PiBfc3Vicy5kZWxldGUoZm4pO1xuICAgIH0sXG4gIH07XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztDQU1DLEdBRUQsc0RBQXNEO0FBZ0J0RCxtRUFBbUU7QUFFbkUsTUFBTSxxQkFBcUIsSUFBSTtBQUMvQixNQUFNLG9CQUFvQixJQUFJO0FBRTlCLG1FQUFtRTtBQUVuRSxPQUFPLFNBQVMsc0JBQXNCLFFBQWE7RUFDakQsTUFBTSxPQUFPLFNBQVMsV0FBVztFQUNqQyxNQUFNLFdBQVcsS0FBSyxLQUFLO0VBQzNCLElBQUksQ0FBQyxZQUFZLE9BQU8sYUFBYSxVQUFVO0VBRS9DLE1BQU0sU0FBUyxJQUFJO0VBQ25CLG1CQUFtQixHQUFHLENBQUMsVUFBVTtFQUVqQyxNQUFNLFNBQTRCLEVBQUU7RUFDcEMsa0JBQWtCLEdBQUcsQ0FBQyxVQUFVO0VBRWhDLEtBQUssTUFBTSxDQUFD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
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/core - Local WC Package Registry
|
|
3
|
+
*
|
|
4
|
+
* Provides registration, lookup, validation, and indexing for
|
|
5
|
+
* OpenElementPackageManifest instances. This is the foundation for
|
|
6
|
+
* the v0.16 WC Package Protocol.
|
|
7
|
+
*
|
|
8
|
+
* The registry is local (in-process) only. Public hub support
|
|
9
|
+
* is a future concern (v0.18+).
|
|
10
|
+
*/ import type { OpenElementDeclaration, OpenElementPackageManifest } from '@openelement/protocol/manifest';
|
|
11
|
+
import type { RegistryIndex, ValidationResult } from '@openelement/protocol/framework';
|
|
12
|
+
/** Register a package manifest with the local registry. */ export declare function register(manifest: OpenElementPackageManifest): void;
|
|
13
|
+
/** Look up a declaration by its custom element tag name. */ export declare function getByTagName(tagName: string): OpenElementDeclaration | undefined;
|
|
14
|
+
/** Get all registered package manifests. */ export declare function getAll(): readonly OpenElementPackageManifest[];
|
|
15
|
+
/** Validate a package manifest against the openElement protocol rules. */ export declare function validate(manifest: OpenElementPackageManifest): ValidationResult;
|
|
16
|
+
/** Generate an aggregated index of all registered manifests. */ export declare function generateIndex(): RegistryIndex;
|
|
17
|
+
/** Clear all registered manifests (useful for testing). */ export declare function clear(): void;
|
package/src/registry.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/core - Local WC Package Registry
|
|
3
|
+
*
|
|
4
|
+
* Provides registration, lookup, validation, and indexing for
|
|
5
|
+
* OpenElementPackageManifest instances. This is the foundation for
|
|
6
|
+
* the v0.16 WC Package Protocol.
|
|
7
|
+
*
|
|
8
|
+
* The registry is local (in-process) only. Public hub support
|
|
9
|
+
* is a future concern (v0.18+).
|
|
10
|
+
*/ const _packages = [];
|
|
11
|
+
/** Register a package manifest with the local registry. */ export function register(manifest) {
|
|
12
|
+
const existing = _packages.find((p)=>p.packageName === manifest.packageName);
|
|
13
|
+
if (existing) {
|
|
14
|
+
const idx = _packages.indexOf(existing);
|
|
15
|
+
_packages[idx] = manifest;
|
|
16
|
+
} else {
|
|
17
|
+
_packages.push(manifest);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Look up a declaration by its custom element tag name. */ export function getByTagName(tagName) {
|
|
21
|
+
for (const pkg of _packages){
|
|
22
|
+
const decl = pkg.declarations.find((d)=>d.tagName === tagName);
|
|
23
|
+
if (decl) return decl;
|
|
24
|
+
}
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Get all registered package manifests. */ export function getAll() {
|
|
28
|
+
return _packages;
|
|
29
|
+
}
|
|
30
|
+
/** Validate a package manifest against the openElement protocol rules. */ export function validate(manifest) {
|
|
31
|
+
const errors = [];
|
|
32
|
+
const warnings = [];
|
|
33
|
+
// 1. Required fields
|
|
34
|
+
if (!manifest.packageName) {
|
|
35
|
+
errors.push({
|
|
36
|
+
code: 'MISSING_PACKAGE_NAME',
|
|
37
|
+
message: 'packageName is required',
|
|
38
|
+
path: 'packageName'
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (!manifest.version) {
|
|
42
|
+
errors.push({
|
|
43
|
+
code: 'MISSING_VERSION',
|
|
44
|
+
message: 'version is required',
|
|
45
|
+
path: 'version'
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (!manifest.schemaVersion) {
|
|
49
|
+
errors.push({
|
|
50
|
+
code: 'MISSING_SCHEMA_VERSION',
|
|
51
|
+
message: 'schemaVersion is required',
|
|
52
|
+
path: 'schemaVersion'
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
if (!manifest.declarations || manifest.declarations.length === 0) {
|
|
56
|
+
errors.push({
|
|
57
|
+
code: 'MISSING_DECLARATIONS',
|
|
58
|
+
message: 'At least one declaration is required',
|
|
59
|
+
path: 'declarations'
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
// 2. Validate each declaration
|
|
63
|
+
const tagNames = new Set();
|
|
64
|
+
for(let i = 0; i < (manifest.declarations ?? []).length; i++){
|
|
65
|
+
const decl = manifest.declarations[i];
|
|
66
|
+
const path = `declarations[${i}]`;
|
|
67
|
+
if (!decl.tagName) {
|
|
68
|
+
errors.push({
|
|
69
|
+
code: 'MISSING_TAG_NAME',
|
|
70
|
+
message: 'tagName is required for each declaration',
|
|
71
|
+
path: `${path}.tagName`
|
|
72
|
+
});
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
// 3. Invalid custom element name
|
|
76
|
+
if (!isValidCustomElementName(decl.tagName)) {
|
|
77
|
+
errors.push({
|
|
78
|
+
code: 'INVALID_TAG_NAME',
|
|
79
|
+
message: `"${decl.tagName}" is not a valid custom element name (must contain a hyphen and start with a letter)`,
|
|
80
|
+
path: `${path}.tagName`
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// 5. Duplicate tag names within a package
|
|
84
|
+
if (tagNames.has(decl.tagName)) {
|
|
85
|
+
errors.push({
|
|
86
|
+
code: 'DUPLICATE_TAG_NAME',
|
|
87
|
+
message: `Duplicate tagName "${decl.tagName}" within package`,
|
|
88
|
+
path: `${path}.tagName`
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
tagNames.add(decl.tagName);
|
|
92
|
+
// 4. Unsafe module paths
|
|
93
|
+
if (decl.openElement?.module) {
|
|
94
|
+
if (isUnsafeModulePath(decl.openElement.module)) {
|
|
95
|
+
errors.push({
|
|
96
|
+
code: 'UNSAFE_MODULE_PATH',
|
|
97
|
+
message: `Module path "${decl.openElement.module}" contains unsafe patterns`,
|
|
98
|
+
path: `${path}.openElement.module`
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 4. Invalid layer
|
|
103
|
+
if (decl.openElement?.layer && ![
|
|
104
|
+
'dsd-static',
|
|
105
|
+
'dsd-interactive',
|
|
106
|
+
'pure-island'
|
|
107
|
+
].includes(decl.openElement.layer)) {
|
|
108
|
+
errors.push({
|
|
109
|
+
code: 'INVALID_LAYER',
|
|
110
|
+
message: `Invalid layer "${decl.openElement.layer}" (must be dsd-static, dsd-interactive, or pure-island)`,
|
|
111
|
+
path: `${path}.openElement.layer`
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
// 4. Invalid hydrate strategy
|
|
115
|
+
if (decl.openElement?.hydrate && ![
|
|
116
|
+
'load',
|
|
117
|
+
'idle',
|
|
118
|
+
'visible',
|
|
119
|
+
'only'
|
|
120
|
+
].includes(decl.openElement.hydrate)) {
|
|
121
|
+
errors.push({
|
|
122
|
+
code: 'INVALID_HYDRATE_STRATEGY',
|
|
123
|
+
message: `Invalid hydrate strategy "${decl.openElement.hydrate}"`,
|
|
124
|
+
path: `${path}.openElement.hydrate`
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// 6. Unresolved export declaration references
|
|
129
|
+
if (manifest.modules) {
|
|
130
|
+
for(let mi = 0; mi < manifest.modules.length; mi++){
|
|
131
|
+
const mod = manifest.modules[mi];
|
|
132
|
+
if (mod.declarations) {
|
|
133
|
+
for (const declRef of mod.declarations){
|
|
134
|
+
const found = manifest.declarations.some((d)=>d.tagName === declRef || d.className === declRef);
|
|
135
|
+
if (!found) {
|
|
136
|
+
warnings.push({
|
|
137
|
+
code: 'UNRESOLVED_DECLARATION_REF',
|
|
138
|
+
message: `Module references declaration "${declRef}" which is not in the declarations array`,
|
|
139
|
+
path: `modules[${mi}].declarations`
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// 7. Registry-level duplicate tag names (across packages)
|
|
147
|
+
for (const decl of manifest.declarations ?? []){
|
|
148
|
+
if (!decl.tagName) continue;
|
|
149
|
+
for (const existingPkg of _packages){
|
|
150
|
+
if (existingPkg.packageName === manifest.packageName) continue;
|
|
151
|
+
const conflict = existingPkg.declarations.find((d)=>d.tagName === decl.tagName);
|
|
152
|
+
if (conflict) {
|
|
153
|
+
warnings.push({
|
|
154
|
+
code: 'REGISTRY_TAG_CONFLICT',
|
|
155
|
+
message: `tagName "${decl.tagName}" already registered by ${existingPkg.packageName}`,
|
|
156
|
+
path: `declarations[${manifest.declarations.indexOf(decl)}].tagName`
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return {
|
|
162
|
+
valid: errors.length === 0,
|
|
163
|
+
errors,
|
|
164
|
+
warnings
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
/** Generate an aggregated index of all registered manifests. */ export function generateIndex() {
|
|
168
|
+
const entries = [];
|
|
169
|
+
for (const pkg of _packages){
|
|
170
|
+
for (const decl of pkg.declarations){
|
|
171
|
+
entries.push({
|
|
172
|
+
tagName: decl.tagName,
|
|
173
|
+
packageName: pkg.packageName,
|
|
174
|
+
version: pkg.version,
|
|
175
|
+
module: decl.openElement?.module,
|
|
176
|
+
ssr: decl.openElement?.ssr,
|
|
177
|
+
dsd: decl.openElement?.dsd,
|
|
178
|
+
hydrate: decl.openElement?.hydrate
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
entries.sort((a, b)=>a.tagName.localeCompare(b.tagName));
|
|
183
|
+
return {
|
|
184
|
+
totalPackages: _packages.length,
|
|
185
|
+
totalDeclarations: entries.length,
|
|
186
|
+
entries
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/** Clear all registered manifests (useful for testing). */ export function clear() {
|
|
190
|
+
_packages.length = 0;
|
|
191
|
+
}
|
|
192
|
+
/** Check if a tag name is a valid custom element name per HTML spec. */ function isValidCustomElementName(name) {
|
|
193
|
+
// Must contain a hyphen, start with a lowercase letter, and only
|
|
194
|
+
// contain allowed characters. Must not be a reserved name.
|
|
195
|
+
if (!name) return false;
|
|
196
|
+
const reserved = new Set([
|
|
197
|
+
'annotation-xml',
|
|
198
|
+
'color-profile',
|
|
199
|
+
'font-face',
|
|
200
|
+
'font-face-src',
|
|
201
|
+
'font-face-uri',
|
|
202
|
+
'font-face-format',
|
|
203
|
+
'font-face-name',
|
|
204
|
+
'missing-glyph'
|
|
205
|
+
]);
|
|
206
|
+
if (reserved.has(name)) return false;
|
|
207
|
+
// Basic check: starts with letter, contains hyphen, only [a-z0-9-]
|
|
208
|
+
return /^[a-z][a-z0-9]*-[a-z0-9-]*$/.test(name);
|
|
209
|
+
}
|
|
210
|
+
/** Check if a module path contains unsafe patterns. */ function isUnsafeModulePath(path) {
|
|
211
|
+
// Reject paths with directory traversal, absolute paths, or protocol handlers
|
|
212
|
+
if (path.startsWith('/') || path.startsWith('\\')) return true;
|
|
213
|
+
if (path.includes('..')) return true;
|
|
214
|
+
if (/^[a-z]+:\/\//i.test(path) && !path.startsWith('jsr:') && !path.startsWith('npm:')) {
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9yZWdpc3RyeS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBvcGVuZWxlbWVudC9jb3JlIC0gTG9jYWwgV0MgUGFja2FnZSBSZWdpc3RyeVxuICpcbiAqIFByb3ZpZGVzIHJlZ2lzdHJhdGlvbiwgbG9va3VwLCB2YWxpZGF0aW9uLCBhbmQgaW5kZXhpbmcgZm9yXG4gKiBPcGVuRWxlbWVudFBhY2thZ2VNYW5pZmVzdCBpbnN0YW5jZXMuIFRoaXMgaXMgdGhlIGZvdW5kYXRpb24gZm9yXG4gKiB0aGUgdjAuMTYgV0MgUGFja2FnZSBQcm90b2NvbC5cbiAqXG4gKiBUaGUgcmVnaXN0cnkgaXMgbG9jYWwgKGluLXByb2Nlc3MpIG9ubHkuIFB1YmxpYyBodWIgc3VwcG9ydFxuICogaXMgYSBmdXR1cmUgY29uY2VybiAodjAuMTgrKS5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG4gIE9wZW5FbGVtZW50RGVjbGFyYXRpb24sXG4gIE9wZW5FbGVtZW50UGFja2FnZU1hbmlmZXN0LFxufSBmcm9tICdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvbWFuaWZlc3QnO1xuaW1wb3J0IHR5cGUge1xuICBSZWdpc3RyeUluZGV4LFxuICBSZWdpc3RyeUluZGV4RW50cnksXG4gIFZhbGlkYXRpb25FcnJvcixcbiAgVmFsaWRhdGlvblJlc3VsdCxcbiAgVmFsaWRhdGlvbldhcm5pbmcsXG59IGZyb20gJ0BvcGVuZWxlbWVudC9wcm90b2NvbC9mcmFtZXdvcmsnO1xuXG5jb25zdCBfcGFja2FnZXM6IE9wZW5FbGVtZW50UGFja2FnZU1hbmlmZXN0W10gPSBbXTtcblxuLyoqIFJlZ2lzdGVyIGEgcGFja2FnZSBtYW5pZmVzdCB3aXRoIHRoZSBsb2NhbCByZWdpc3RyeS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpc3RlcihtYW5pZmVzdDogT3BlbkVsZW1lbnRQYWNrYWdlTWFuaWZlc3QpOiB2b2lkIHtcbiAgY29uc3QgZXhpc3RpbmcgPSBfcGFja2FnZXMuZmluZCgocCkgPT4gcC5wYWNrYWdlTmFtZSA9PT0gbWFuaWZlc3QucGFja2FnZU5hbWUpO1xuICBpZiAoZXhpc3RpbmcpIHtcbiAgICBjb25zdCBpZHggPSBfcGFja2FnZXMuaW5kZXhPZihleGlzdGluZyk7XG4gICAgX3BhY2thZ2VzW2lkeF0gPSBtYW5pZmVzdDtcbiAgfSBlbHNlIHtcbiAgICBfcGFja2FnZXMucHVzaChtYW5pZmVzdCk7XG4gIH1cbn1cblxuLyoqIExvb2sgdXAgYSBkZWNsYXJhdGlvbiBieSBpdHMgY3VzdG9tIGVsZW1lbnQgdGFnIG5hbWUuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0QnlUYWdOYW1lKHRhZ05hbWU6IHN0cmluZyk6IE9wZW5FbGVtZW50RGVjbGFyYXRpb24gfCB1bmRlZmluZWQge1xuICBmb3IgKGNvbnN0IHBrZyBvZiBfcGFja2FnZXMpIHtcbiAgICBjb25zdCBkZWNsID0gcGtnLmRlY2xhcmF0aW9ucy5maW5kKChkKSA9PiBkLnRhZ05hbWUgPT09IHRhZ05hbWUpO1xuICAgIGlmIChkZWNsKSByZXR1cm4gZGVjbDtcbiAgfVxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG4vKiogR2V0IGFsbCByZWdpc3RlcmVkIHBhY2thZ2UgbWFuaWZlc3RzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldEFsbCgpOiByZWFkb25seSBPcGVuRWxlbWVudFBhY2thZ2VNYW5pZmVzdFtdIHtcbiAgcmV0dXJuIF9wYWNrYWdlcztcbn1cblxuLyoqIFZhbGlkYXRlIGEgcGFja2FnZSBtYW5pZmVzdCBhZ2FpbnN0IHRoZSBvcGVuRWxlbWVudCBwcm90b2NvbCBydWxlcy4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZShtYW5pZmVzdDogT3BlbkVsZW1lbnRQYWNrYWdlTWFuaWZlc3QpOiBWYWxpZGF0aW9uUmVzdWx0IHtcbiAgY29uc3QgZXJyb3JzOiBWYWxpZGF0aW9uRXJyb3JbXSA9IFtdO1xuICBjb25zdCB3YXJuaW5nczogVmFsaWRhdGlvbldhcm5pbmdbXSA9IFtdO1xuXG4gIC8vIDEuIFJlcXVpcmVkIGZpZWxkc1xuICBpZiAoIW1hbmlmZXN0LnBhY2thZ2VOYW1lKSB7XG4gICAgZXJyb3JzLnB1c2goe1xuICAgICAgY29kZTogJ01JU1NJTkdfUEFDS0FHRV9OQU1FJyxcbiAgICAgIG1lc3NhZ2U6ICdwYWNrYWdlTmFtZSBpcyByZXF1aXJlZCcsXG4gICAgICBwYXRoOiAncGFja2FnZU5hbWUnLFxuICAgIH0pO1xuICB9XG4gIGlmICghbWFuaWZlc3QudmVyc2lvbikge1xuICAgIGVycm9ycy5wdXNoKHtcbiAgICAgIGNvZGU6ICdNSVNTSU5HX1ZFUlNJT04nLFxuICAgICAgbWVzc2FnZTogJ3ZlcnNpb24gaXMgcmVxdWlyZWQnLFxuICAgICAgcGF0aDogJ3ZlcnNpb24nLFxuICAgIH0pO1xuICB9XG4gIGlmICghbWFuaWZlc3Quc2NoZW1hVmVyc2lvbikge1xuICAgIGVycm9ycy5wdXNoKHtcbiAgICAgIGNvZGU6ICdNSVNTSU5HX1NDSEVNQV9WRVJTSU9OJyxcbiAgICAgIG1lc3NhZ2U6ICdzY2hlbWFWZXJzaW9uIGlzIHJlcXVpcmVkJyxcbiAgICAgIHBhdGg6ICdzY2hlbWFWZXJzaW9uJyxcbiAgICB9KTtcbiAgfVxuICBpZiAoIW1hbmlmZXN0LmRlY2xhcmF0aW9ucyB8fCBtYW5pZmVzdC5kZWNsYXJhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgZXJyb3JzLnB1c2goe1xuICAgICAgY29kZTogJ01JU1NJTkdfREVDTEFSQVRJT05TJyxcbiAgICAgIG1lc3NhZ2U6ICdBdCBsZWFzdCBvbmUgZGVjbGFyYXRpb24gaXMgcmVxdWlyZWQnLFxuICAgICAgcGF0aDogJ2RlY2xhcmF0aW9ucycsXG4gICAgfSk7XG4gIH1cblxuICAvLyAyLiBWYWxpZGF0ZSBlYWNoIGRlY2xhcmF0aW9uXG4gIGNvbnN0IHRhZ05hbWVzID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgKG1hbmlmZXN0LmRlY2xhcmF0aW9ucyA/PyBbXSkubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBkZWNsID0gbWFuaWZlc3QuZGVjbGFyYXRpb25zW2ldO1xuICAgIGNvbnN0IHBhdGggPSBgZGVjbGFyYXRpb25zWyR7aX1dYDtcblxuICAgIGlmICghZGVjbC50YWdOYW1lKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIGNvZGU6ICdNSVNTSU5HX1RBR19OQU1FJyxcbiAgICAgICAgbWVzc2FnZTogJ3RhZ05hbWUgaXMgcmVxdWlyZWQgZm9yIGVhY2ggZGVjbGFyYXRpb24nLFxuICAgICAgICBwYXRoOiBgJHtwYXRofS50YWdOYW1lYCxcbiAgICAgIH0pO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgLy8gMy4gSW52YWxpZCBjdXN0b20gZWxlbWVudCBuYW1lXG4gICAgaWYgKCFpc1ZhbGlkQ3VzdG9tRWxlbWVudE5hbWUoZGVjbC50YWdOYW1lKSkge1xuICAgICAgZXJyb3JzLnB1c2goe1xuICAgICAgICBjb2RlOiAnSU5WQUxJRF9UQUdfTkFNRScsXG4gICAgICAgIG1lc3NhZ2U6XG4gICAgICAgICAgYFwiJHtkZWNsLnRhZ05hbWV9XCIgaXMgbm90IGEgdmFsaWQgY3VzdG9tIGVsZW1lbnQgbmFtZSAobXVzdCBjb250YWluIGEgaHlwaGVuIGFuZCBzdGFydCB3aXRoIGEgbGV0dGVyKWAsXG4gICAgICAgIHBhdGg6IGAke3BhdGh9LnRhZ05hbWVgLFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gNS4gRHVwbGljYXRlIHRhZyBuYW1lcyB3aXRoaW4gYSBwYWNrYWdlXG4gICAgaWYgKHRhZ05hbWVzLmhhcyhkZWNsLnRhZ05hbWUpKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIGNvZGU6ICdEVVBMSUNBVEVfVEFHX05BTUUnLFxuICAgICAgICBtZXNzYWdlOiBgRHVwbGljYXRlIHRhZ05hbWUgXCIke2RlY2wudGFnTmFtZX1cIiB3aXRoaW4gcGFja2FnZWAsXG4gICAgICAgIHBhdGg6IGAke3BhdGh9LnRhZ05hbWVgLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHRhZ05hbWVzLmFkZChkZWNsLnRhZ05hbWUpO1xuXG4gICAgLy8gNC4gVW5zYWZlIG1vZHVsZSBwYXRoc1xuICAgIGlmIChkZWNsLm9wZW5FbGVtZW50Py5tb2R1bGUpIHtcbiAgICAgIGlmIChpc1Vuc2FmZU1vZHVsZVBhdGgoZGVjbC5vcGVuRWxlbWVudC5tb2R1bGUpKSB7XG4gICAgICAgIGVycm9ycy5wdXNoKHtcbiAgICAgICAgICBjb2RlOiAnVU5TQUZFX01PRFVMRV9QQVRIJyxcbiAgICAgICAgICBtZXNzYWdlOiBgTW9kdWxlIHBhdGggXCIke2RlY2wub3BlbkVsZW1lbnQubW9kdWxlfVwiIGNvbnRhaW5zIHVuc2FmZSBwYXR0ZXJuc2AsXG4gICAgICAgICAgcGF0aDogYCR7cGF0aH0ub3BlbkVsZW1lbnQubW9kdWxlYCxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gNC4gSW52YWxpZCBsYXllclxuICAgIGlmIChcbiAgICAgIGRlY2wub3BlbkVsZW1lbnQ/LmxheWVyICYmXG4gICAgICAhWydkc2Qtc3RhdGljJywgJ2RzZC1pbnRlcmFjdGl2ZScsICdwdXJlLWlzbGFuZCddLmluY2x1ZGVzKGRlY2wub3BlbkVsZW1lbnQubGF5ZXIpXG4gICAgKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIGNvZGU6ICdJTlZBTElEX0xBWUVSJyxcbiAgICAgICAgbWVzc2FnZTpcbiAgICAgICAgICBgSW52YWxpZCBsYXllciBcIiR7ZGVjbC5vcGVuRWxlbWVudC5sYXllcn1cIiAobXVzdCBiZSBkc2Qtc3RhdGljLCBkc2QtaW50ZXJhY3RpdmUsIG9yIHB1cmUtaXNsYW5kKWAsXG4gICAgICAgIHBhdGg6IGAke3BhdGh9Lm9wZW5FbGVtZW50LmxheWVyYCxcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIDQuIEludmFsaWQgaHlkcmF0ZSBzdHJhdGVneVxuICAgIGlmIChcbiAgICAgIGRlY2wub3BlbkVsZW1lbnQ/Lmh5ZHJhdGUgJiZcbiAgICAgICFbJ2xvYWQnLCAnaWRsZScsICd2aXNpYmxlJywgJ29ubHknXS5pbmNsdWRlcyhkZWNsLm9wZW5FbGVtZW50Lmh5ZHJhdGUpXG4gICAgKSB7XG4gICAgICBlcnJvcnMucHVzaCh7XG4gICAgICAgIGNvZGU6ICdJTlZBTElEX0hZRFJBVEVfU1RSQVRFR1knLFxuICAgICAgICBtZXNzYWdlOiBgSW52YWxpZCBoeWRyYXRlIHN0cmF0ZWd5IFwiJHtkZWNsLm9wZW5FbGVtZW50Lmh5ZHJhdGV9XCJgLFxuICAgICAgICBwYXRoOiBgJHtwYXRofS5vcGVuRWxlbWVudC5oeWRyYXRlYCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8vIDYuIFVucmVzb2x2ZWQgZXhwb3J0IGRlY2xhcmF0aW9uIHJlZmVyZW5jZXNcbiAgaWYgKG1hbmlmZXN0Lm1vZHVsZXMpIHtcbiAgICBmb3IgKGxldCBtaSA9IDA7IG1pIDwgbWFuaWZlc3QubW9kdWxlcy5sZW5ndGg7IG1pKyspIHtcbiAgICAgIGNvbnN0IG1vZCA9IG1hbmlmZXN0Lm1vZHVsZXNbbWldO1xuICAgICAgaWYgKG1vZC5kZWNsYXJhdGlvbnMpIHtcbiAgICAgICAgZm9yIChjb25zdCBkZWNsUmVmIG9mIG1vZC5kZWNsYXJhdGlvbnMpIHtcbiAgICAgICAgICBjb25zdCBmb3VuZCA9IG1hbmlmZXN0LmRlY2xhcmF0aW9ucy5zb21lKFxuICAgICAgICAgICAgKGQpID0+IGQudGFnTmFtZSA9PT0gZGVjbFJlZiB8fCBkLmNsYXNzTmFtZSA9PT0gZGVjbFJlZixcbiAgICAgICAgICApO1xuICAgICAgICAgIGlmICghZm91bmQpIHtcbiAgICAgICAgICAgIHdhcm5pbmdzLnB1c2goe1xuICAgICAgICAgICAgICBjb2RlOiAnVU5SRVNPTFZFRF9ERUNMQVJBVElPTl9SRUYnLFxuICAgICAgICAgICAgICBtZXNzYWdlOlxuICAgICAgICAgICAgICAgIGBNb2R1bGUgcmVmZXJlbmNlcyBkZWNsYXJhdGlvbiBcIiR7ZGVjbFJlZn1cIiB3aGljaCBpcyBub3QgaW4gdGhlIGRlY2xhcmF0aW9ucyBhcnJheWAsXG4gICAgICAgICAgICAgIHBhdGg6IGBtb2R1bGVzWyR7bWl9XS5kZWNsYXJhdGlvbnNgLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gNy4gUmVnaXN0cnktbGV2ZWwgZHVwbGljYXRlIHRhZyBuYW1lcyAoYWNyb3NzIHBhY2thZ2VzKVxuICBmb3IgKGNvbnN0IGRlY2wgb2YgbWFuaWZlc3QuZGVjbGFyYXRpb25zID8/IFtdKSB7XG4gICAgaWYgKCFkZWNsLnRhZ05hbWUpIGNvbnRpbnVlO1xuICAgIGZvciAoY29uc3QgZXhpc3RpbmdQa2cgb2YgX3BhY2thZ2VzKSB7XG4gICAgICBpZiAoZXhpc3RpbmdQa2cucGFja2FnZU5hbWUgPT09IG1hbmlmZXN0LnBhY2thZ2VOYW1lKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IGNvbmZsaWN0ID0gZXhpc3RpbmdQa2cuZGVjbGFyYXRpb25zLmZpbmQoKGQpID0+IGQudGFnTmFtZSA9PT0gZGVjbC50YWdOYW1lKTtcbiAgICAgIGlmIChjb25mbGljdCkge1xuICAgICAgICB3YXJuaW5ncy5wdXNoKHtcbiAgICAgICAgICBjb2RlOiAnUkVHSVNUUllfVEFHX0NPTkZMSUNUJyxcbiAgICAgICAgICBtZXNzYWdlOiBgdGFnTmFtZSBcIiR7ZGVjbC50YWdOYW1lfVwiIGFscmVhZHkgcmVnaXN0ZXJlZCBieSAke2V4aXN0aW5nUGtnLnBhY2thZ2VOYW1lfWAsXG4gICAgICAgICAgcGF0aDogYGRlY2xhcmF0aW9uc1ske21hbmlmZXN0LmRlY2xhcmF0aW9ucy5pbmRleE9mKGRlY2wpfV0udGFnTmFtZWAsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdmFsaWQ6IGVycm9ycy5sZW5ndGggPT09IDAsXG4gICAgZXJyb3JzLFxuICAgIHdhcm5pbmdzLFxuICB9O1xufVxuXG4vKiogR2VuZXJhdGUgYW4gYWdncmVnYXRlZCBpbmRleCBvZiBhbGwgcmVnaXN0ZXJlZCBtYW5pZmVzdHMuICovXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVJbmRleCgpOiBSZWdpc3RyeUluZGV4IHtcbiAgY29uc3QgZW50cmllczogUmVnaXN0cnlJbmRleEVudHJ5W10gPSBbXTtcblxuICBmb3IgKGNvbnN0IHBrZyBvZiBfcGFja2FnZXMpIHtcbiAgICBmb3IgKGNvbnN0IGRlY2wgb2YgcGtnLmRlY2xhcmF0aW9ucykge1xuICAgICAgZW50cmllcy5wdXNoKHtcbiAgICAgICAgdGFnTmFtZTogZGVjbC50YWdOYW1lLFxuICAgICAgICBwYWNrYWdlTmFtZTogcGtnLnBhY2thZ2VOYW1lLFxuICAgICAgICB2ZXJzaW9uOiBwa2cudmVyc2lvbixcbiAgICAgICAgbW9kdWxlOiBkZWNsLm9wZW5FbGVtZW50Py5tb2R1bGUsXG4gICAgICAgIHNzcjogZGVjbC5vcGVuRWxlbWVudD8uc3NyLFxuICAgICAgICBkc2Q6IGRlY2wub3BlbkVsZW1lbnQ/LmRzZCxcbiAgICAgICAgaHlkcmF0ZTogZGVjbC5vcGVuRWxlbWVudD8uaHlkcmF0ZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGVudHJpZXMuc29ydCgoYSwgYikgPT4gYS50YWdOYW1lLmxvY2FsZUNvbXBhcmUoYi50YWdOYW1lKSk7XG5cbiAgcmV0dXJuIHtcbiAgICB0b3RhbFBhY2thZ2VzOiBfcGFja2FnZXMubGVuZ3RoLFxuICAgIHRvdGFsRGVjbGFyYXRpb25zOiBlbnRyaWVzLmxlbmd0aCxcbiAgICBlbnRyaWVzLFxuICB9O1xufVxuXG4vKiogQ2xlYXIgYWxsIHJlZ2lzdGVyZWQgbWFuaWZlc3RzICh1c2VmdWwgZm9yIHRlc3RpbmcpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyKCk6IHZvaWQge1xuICBfcGFja2FnZXMubGVuZ3RoID0gMDtcbn1cblxuLyoqIENoZWNrIGlmIGEgdGFnIG5hbWUgaXMgYSB2YWxpZCBjdXN0b20gZWxlbWVudCBuYW1lIHBlciBIVE1MIHNwZWMuICovXG5mdW5jdGlvbiBpc1ZhbGlkQ3VzdG9tRWxlbWVudE5hbWUobmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIC8vIE11c3QgY29udGFpbiBhIGh5cGhlbiwgc3RhcnQgd2l0aCBhIGxvd2VyY2FzZSBsZXR0ZXIsIGFuZCBvbmx5XG4gIC8vIGNvbnRhaW4gYWxsb3dlZCBjaGFyYWN0ZXJzLiBNdXN0IG5vdCBiZSBhIHJlc2VydmVkIG5hbWUuXG4gIGlmICghbmFtZSkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCByZXNlcnZlZCA9IG5ldyBTZXQoW1xuICAgICdhbm5vdGF0aW9uLXhtbCcsXG4gICAgJ2NvbG9yLXByb2ZpbGUnLFxuICAgICdmb250LWZhY2UnLFxuICAgICdmb250LWZhY2Utc3JjJyxcbiAgICAnZm9udC1mYWNlLXVyaScsXG4gICAgJ2ZvbnQtZmFjZS1mb3JtYXQnLFxuICAgICdmb250LWZhY2UtbmFtZScsXG4gICAgJ21pc3NpbmctZ2x5cGgnLFxuICBdKTtcbiAgaWYgKHJlc2VydmVkLmhhcyhuYW1lKSkgcmV0dXJuIGZhbHNlO1xuICAvLyBCYXNpYyBjaGVjazogc3RhcnRzIHdpdGggbGV0dGVyLCBjb250YWlucyBoeXBoZW4sIG9ubHkgW2EtejAtOS1dXG4gIHJldHVybiAvXlthLXpdW2EtejAtOV0qLVthLXowLTktXSokLy50ZXN0KG5hbWUpO1xufVxuXG4vKiogQ2hlY2sgaWYgYSBtb2R1bGUgcGF0aCBjb250YWlucyB1bnNhZmUgcGF0dGVybnMuICovXG5mdW5jdGlvbiBpc1Vuc2FmZU1vZHVsZVBhdGgocGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIC8vIFJlamVjdCBwYXRocyB3aXRoIGRpcmVjdG9yeSB0cmF2ZXJzYWwsIGFic29sdXRlIHBhdGhzLCBvciBwcm90b2NvbCBoYW5kbGVyc1xuICBpZiAocGF0aC5zdGFydHNXaXRoKCcvJykgfHwgcGF0aC5zdGFydHNXaXRoKCdcXFxcJykpIHJldHVybiB0cnVlO1xuICBpZiAocGF0aC5pbmNsdWRlcygnLi4nKSkgcmV0dXJuIHRydWU7XG4gIGlmICgvXlthLXpdKzpcXC9cXC8vaS50ZXN0KHBhdGgpICYmICFwYXRoLnN0YXJ0c1dpdGgoJ2pzcjonKSAmJiAhcGF0aC5zdGFydHNXaXRoKCducG06JykpIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuICByZXR1cm4gZmFsc2U7XG59XG4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7OztDQVNDLEdBY0QsTUFBTSxZQUEwQyxFQUFFO0FBRWxELHlEQUF5RCxHQUN6RCxPQUFPLFNBQVMsU0FBUyxRQUFvQztFQUMzRCxNQUFNLFdBQVcsVUFBVSxJQUFJLENBQUMsQ0FBQyxJQUFNLEVBQUUsV0FBVyxLQUFLLFNBQVMsV0FBVztFQUM3RSxJQUFJLFVBQVU7SUFDWixNQUFNLE1BQU0sVUFBVSxPQUFPLENBQUM7SUFDOUIsU0FBUyxDQUFDLElBQUksR0FBRztFQUNuQixPQUFPO0lBQ0wsVUFBVSxJQUFJLENBQUM7RUFDakI7QUFDRjtBQUVBLDBEQUEwRCxHQUMxRCxPQUFPLFNBQVMsYUFBYSxPQUFlO0VBQzFDLEtBQUssTUFBTSxPQUFPLFVBQVc7SUFDM0IsTUFBTSxPQUFPLElBQUksWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQU0sRUFBRSxPQUFPLEtBQUs7SUFDeEQsSUFBSSxNQUFNLE9BQU87RUFDbkI7RUFDQSxPQUFPO0FBQ1Q7QUFFQSwwQ0FBMEMsR0FDMUMsT0FBTyxTQUFTO0VBQ2QsT0FBTztBQUNUO0FBRUEsd0VBQXdFLEdBQ3hFLE9BQU8sU0FBUyxTQUFTLFFBQW9DO0VBQzNELE1BQU0sU0FBNEIsRUFBRTtFQUNwQyxNQUFNLFdBQWdDLEVBQUU7RUFFeEMscUJBQXFCO0VBQ3JCLElBQUksQ0FBQyxTQUFTLFdBQVcsRUFBRTtJQUN6QixPQUFPLElBQUksQ0FBQztNQUNWLE1BQU07TUFDTixTQUFTO01BQ1Qs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
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { RenderError, RenderOutput } from '@openelement/protocol/render';
|
|
2
|
+
export interface RenderDsdStreamChunk {
|
|
3
|
+
html: string;
|
|
4
|
+
output: RenderOutput;
|
|
5
|
+
}
|
|
6
|
+
export interface RenderDsdStreamMetrics {
|
|
7
|
+
chunkCount: number;
|
|
8
|
+
errorCount: number;
|
|
9
|
+
startedAt: number;
|
|
10
|
+
endedAt?: number;
|
|
11
|
+
}
|
|
12
|
+
export interface RenderDsdStreamOptions {
|
|
13
|
+
shell?: string | (() => string | Promise<string>);
|
|
14
|
+
footer?: string | (() => string | Promise<string>);
|
|
15
|
+
onChunk?: (chunk: RenderDsdStreamChunk) => void;
|
|
16
|
+
onError?: (error: RenderError, tagName: string) => void;
|
|
17
|
+
metrics?: RenderDsdStreamMetrics;
|
|
18
|
+
}
|
|
19
|
+
export interface RenderDsdStreamComponent {
|
|
20
|
+
tagName: string;
|
|
21
|
+
componentClass: CustomElementConstructor;
|
|
22
|
+
props?: Record<string, unknown>;
|
|
23
|
+
sourceInfo?: {
|
|
24
|
+
route?: string;
|
|
25
|
+
source?: string;
|
|
26
|
+
};
|
|
27
|
+
dsdOptions?: import('@openelement/protocol/render').DsdOptions;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Create a fresh metrics collector for streaming Dsd.
|
|
31
|
+
*/ export declare function createRenderDsdStreamMetrics(): RenderDsdStreamMetrics;
|
|
32
|
+
/**
|
|
33
|
+
* Render components as a streaming Dsd response.
|
|
34
|
+
*
|
|
35
|
+
* Returns a ReadableStream<Uint8Array> that emits:
|
|
36
|
+
* 1. Shell (opening HTML)
|
|
37
|
+
* 2. Each component's Dsd output, in order
|
|
38
|
+
* 3. Footer (closing HTML)
|
|
39
|
+
*
|
|
40
|
+
* Failed components emit a bare-tag fallback and the stream continues.
|
|
41
|
+
* Compatible with Web Response constructor for edge handlers.
|
|
42
|
+
*
|
|
43
|
+
* @param components - Iterable of components to render
|
|
44
|
+
* @param options - Stream options (shell, footer, callbacks, metrics)
|
|
45
|
+
* @returns ReadableStream of encoded Dsd HTML chunks
|
|
46
|
+
*/ export declare function renderDsdStream(components: Iterable<RenderDsdStreamComponent>, options?: RenderDsdStreamOptions): ReadableStream<Uint8Array>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @openelement/core - Streaming Dsd Renderer.
|
|
3
|
+
*
|
|
4
|
+
* Progressive Dsd delivery via Web Streams (ReadableStream<Uint8Array>).
|
|
5
|
+
* Extracted from render-dsd.ts in v0.21.0 (SOP-003).
|
|
6
|
+
*
|
|
7
|
+
* Provides:
|
|
8
|
+
* - renderDsdStream() — stream components as they render
|
|
9
|
+
* - createRenderDsdStreamMetrics() — metrics collector factory
|
|
10
|
+
* - RenderDsdStreamChunk, RenderDsdStreamComponent,
|
|
11
|
+
* RenderDsdStreamMetrics, RenderDsdStreamOptions types
|
|
12
|
+
*
|
|
13
|
+
* @module @openelement/core/render-dsd-stream
|
|
14
|
+
*/ import { renderDsd, safeNow } from './render-dsd.js';
|
|
15
|
+
const textEncoder = new TextEncoder();
|
|
16
|
+
async function resolveStreamPart(part) {
|
|
17
|
+
if (!part) return '';
|
|
18
|
+
return typeof part === 'function' ? await part() : part;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Create a fresh metrics collector for streaming Dsd.
|
|
22
|
+
*/ export function createRenderDsdStreamMetrics() {
|
|
23
|
+
return {
|
|
24
|
+
chunkCount: 0,
|
|
25
|
+
errorCount: 0,
|
|
26
|
+
startedAt: safeNow()
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Render components as a streaming Dsd response.
|
|
31
|
+
*
|
|
32
|
+
* Returns a ReadableStream<Uint8Array> that emits:
|
|
33
|
+
* 1. Shell (opening HTML)
|
|
34
|
+
* 2. Each component's Dsd output, in order
|
|
35
|
+
* 3. Footer (closing HTML)
|
|
36
|
+
*
|
|
37
|
+
* Failed components emit a bare-tag fallback and the stream continues.
|
|
38
|
+
* Compatible with Web Response constructor for edge handlers.
|
|
39
|
+
*
|
|
40
|
+
* @param components - Iterable of components to render
|
|
41
|
+
* @param options - Stream options (shell, footer, callbacks, metrics)
|
|
42
|
+
* @returns ReadableStream of encoded Dsd HTML chunks
|
|
43
|
+
*/ export function renderDsdStream(components, options = {}) {
|
|
44
|
+
const encoderMetrics = options.metrics ?? createRenderDsdStreamMetrics();
|
|
45
|
+
return new ReadableStream({
|
|
46
|
+
async start (controller) {
|
|
47
|
+
try {
|
|
48
|
+
const shell = await resolveStreamPart(options.shell);
|
|
49
|
+
if (shell) {
|
|
50
|
+
controller.enqueue(textEncoder.encode(shell));
|
|
51
|
+
encoderMetrics.chunkCount++;
|
|
52
|
+
}
|
|
53
|
+
for (const component of components){
|
|
54
|
+
const output = await renderDsd(component.tagName, {
|
|
55
|
+
componentClass: component.componentClass,
|
|
56
|
+
props: component.props ?? {},
|
|
57
|
+
sourceInfo: component.sourceInfo,
|
|
58
|
+
dsdOptions: component.dsdOptions
|
|
59
|
+
});
|
|
60
|
+
for (const error of output.errors){
|
|
61
|
+
encoderMetrics.errorCount++;
|
|
62
|
+
options.onError?.(error, component.tagName);
|
|
63
|
+
}
|
|
64
|
+
controller.enqueue(textEncoder.encode(output.html));
|
|
65
|
+
encoderMetrics.chunkCount++;
|
|
66
|
+
options.onChunk?.({
|
|
67
|
+
html: output.html,
|
|
68
|
+
output
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
const footer = await resolveStreamPart(options.footer);
|
|
72
|
+
if (footer) {
|
|
73
|
+
controller.enqueue(textEncoder.encode(footer));
|
|
74
|
+
encoderMetrics.chunkCount++;
|
|
75
|
+
}
|
|
76
|
+
encoderMetrics.endedAt = safeNow();
|
|
77
|
+
controller.close();
|
|
78
|
+
} catch (error) {
|
|
79
|
+
encoderMetrics.errorCount++;
|
|
80
|
+
encoderMetrics.endedAt = safeNow();
|
|
81
|
+
controller.error(error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImZpbGU6Ly8vaG9tZS9ydW5uZXIvd29yay9vcGVuZWxlbWVudC9vcGVuZWxlbWVudC9wYWNrYWdlcy9jb3JlL3NyYy9yZW5kZXItZHNkLXN0cmVhbS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEBvcGVuZWxlbWVudC9jb3JlIC0gU3RyZWFtaW5nIERzZCBSZW5kZXJlci5cbiAqXG4gKiBQcm9ncmVzc2l2ZSBEc2QgZGVsaXZlcnkgdmlhIFdlYiBTdHJlYW1zIChSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PikuXG4gKiBFeHRyYWN0ZWQgZnJvbSByZW5kZXItZHNkLnRzIGluIHYwLjIxLjAgKFNPUC0wMDMpLlxuICpcbiAqIFByb3ZpZGVzOlxuICogICAtIHJlbmRlckRzZFN0cmVhbSgpIOKAlCBzdHJlYW0gY29tcG9uZW50cyBhcyB0aGV5IHJlbmRlclxuICogICAtIGNyZWF0ZVJlbmRlckRzZFN0cmVhbU1ldHJpY3MoKSDigJQgbWV0cmljcyBjb2xsZWN0b3IgZmFjdG9yeVxuICogICAtIFJlbmRlckRzZFN0cmVhbUNodW5rLCBSZW5kZXJEc2RTdHJlYW1Db21wb25lbnQsXG4gKiAgICAgUmVuZGVyRHNkU3RyZWFtTWV0cmljcywgUmVuZGVyRHNkU3RyZWFtT3B0aW9ucyB0eXBlc1xuICpcbiAqIEBtb2R1bGUgQG9wZW5lbGVtZW50L2NvcmUvcmVuZGVyLWRzZC1zdHJlYW1cbiAqL1xuXG5pbXBvcnQgeyByZW5kZXJEc2QsIHNhZmVOb3cgfSBmcm9tICcuL3JlbmRlci1kc2QuanMnO1xuaW1wb3J0IHR5cGUgeyBSZW5kZXJFcnJvciwgUmVuZGVyT3V0cHV0IH0gZnJvbSAnQG9wZW5lbGVtZW50L3Byb3RvY29sL3JlbmRlcic7XG5cbi8vIC0tLSBTdHJlYW1pbmcgdHlwZXMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlbmRlckRzZFN0cmVhbUNodW5rIHtcbiAgaHRtbDogc3RyaW5nO1xuICBvdXRwdXQ6IFJlbmRlck91dHB1dDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZW5kZXJEc2RTdHJlYW1NZXRyaWNzIHtcbiAgY2h1bmtDb3VudDogbnVtYmVyO1xuICBlcnJvckNvdW50OiBudW1iZXI7XG4gIHN0YXJ0ZWRBdDogbnVtYmVyO1xuICBlbmRlZEF0PzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlbmRlckRzZFN0cmVhbU9wdGlvbnMge1xuICBzaGVsbD86IHN0cmluZyB8ICgoKSA9PiBzdHJpbmcgfCBQcm9taXNlPHN0cmluZz4pO1xuICBmb290ZXI/OiBzdHJpbmcgfCAoKCkgPT4gc3RyaW5nIHwgUHJvbWlzZTxzdHJpbmc+KTtcbiAgb25DaHVuaz86IChjaHVuazogUmVuZGVyRHNkU3RyZWFtQ2h1bmspID0+IHZvaWQ7XG4gIG9uRXJyb3I/OiAoZXJyb3I6IFJlbmRlckVycm9yLCB0YWdOYW1lOiBzdHJpbmcpID0+IHZvaWQ7XG4gIG1ldHJpY3M/OiBSZW5kZXJEc2RTdHJlYW1NZXRyaWNzO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlbmRlckRzZFN0cmVhbUNvbXBvbmVudCB7XG4gIHRhZ05hbWU6IHN0cmluZztcbiAgY29tcG9uZW50Q2xhc3M6IEN1c3RvbUVsZW1lbnRDb25zdHJ1Y3RvcjtcbiAgcHJvcHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgc291cmNlSW5mbz86IHsgcm91dGU/OiBzdHJpbmc7IHNvdXJjZT86IHN0cmluZyB9O1xuICBkc2RPcHRpb25zPzogaW1wb3J0KCdAb3BlbmVsZW1lbnQvcHJvdG9jb2wvcmVuZGVyJykuRHNkT3B0aW9ucztcbn1cblxuY29uc3QgdGV4dEVuY29kZXIgPSBuZXcgVGV4dEVuY29kZXIoKTtcblxuYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZVN0cmVhbVBhcnQoXG4gIHBhcnQ/OiBzdHJpbmcgfCAoKCkgPT4gc3RyaW5nIHwgUHJvbWlzZTxzdHJpbmc+KSxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGlmICghcGFydCkgcmV0dXJuICcnO1xuICByZXR1cm4gdHlwZW9mIHBhcnQgPT09ICdmdW5jdGlvbicgPyBhd2FpdCBwYXJ0KCkgOiBwYXJ0O1xufVxuXG4vKipcbiAqIENyZWF0ZSBhIGZyZXNoIG1ldHJpY3MgY29sbGVjdG9yIGZvciBzdHJlYW1pbmcgRHNkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVuZGVyRHNkU3RyZWFtTWV0cmljcygpOiBSZW5kZXJEc2RTdHJlYW1NZXRyaWNzIHtcbiAgcmV0dXJuIHtcbiAgICBjaHVua0NvdW50OiAwLFxuICAgIGVycm9yQ291bnQ6IDAsXG4gICAgc3RhcnRlZEF0OiBzYWZlTm93KCksXG4gIH07XG59XG5cbi8qKlxuICogUmVuZGVyIGNvbXBvbmVudHMgYXMgYSBzdHJlYW1pbmcgRHNkIHJlc3BvbnNlLlxuICpcbiAqIFJldHVybnMgYSBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB0aGF0IGVtaXRzOlxuICogICAxLiBTaGVsbCAob3BlbmluZyBIVE1MKVxuICogICAyLiBFYWNoIGNvbXBvbmVudCdzIERzZCBvdXRwdXQsIGluIG9yZGVyXG4gKiAgIDMuIEZvb3RlciAoY2xvc2luZyBIVE1MKVxuICpcbiAqIEZhaWxlZCBjb21wb25lbnRzIGVtaXQgYSBiYXJlLXRhZyBmYWxsYmFjayBhbmQgdGhlIHN0cmVhbSBjb250aW51ZXMuXG4gKiBDb21wYXRpYmxlIHdpdGggV2ViIFJlc3BvbnNlIGNvbnN0cnVjdG9yIGZvciBlZGdlIGhhbmRsZXJzLlxuICpcbiAqIEBwYXJhbSBjb21wb25lbnRzIC0gSXRlcmFibGUgb2YgY29tcG9uZW50cyB0byByZW5kZXJcbiAqIEBwYXJhbSBvcHRpb25zIC0gU3RyZWFtIG9wdGlvbnMgKHNoZWxsLCBmb290ZXIsIGNhbGxiYWNrcywgbWV0cmljcylcbiAqIEByZXR1cm5zIFJlYWRhYmxlU3RyZWFtIG9mIGVuY29kZWQgRHNkIEhUTUwgY2h1bmtzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJEc2RTdHJlYW0oXG4gIGNvbXBvbmVudHM6IEl0ZXJhYmxlPFJlbmRlckRzZFN0cmVhbUNvbXBvbmVudD4sXG4gIG9wdGlvbnM6IFJlbmRlckRzZFN0cmVhbU9wdGlvbnMgPSB7fSxcbik6IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgZW5jb2Rlck1ldHJpY3MgPSBvcHRpb25zLm1ldHJpY3MgPz8gY3JlYXRlUmVuZGVyRHNkU3RyZWFtTWV0cmljcygpO1xuXG4gIHJldHVybiBuZXcgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4oe1xuICAgIGFzeW5jIHN0YXJ0KGNvbnRyb2xsZXIpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHNoZWxsID0gYXdhaXQgcmVzb2x2ZVN0cmVhbVBhcnQob3B0aW9ucy5zaGVsbCk7XG4gICAgICAgIGlmIChzaGVsbCkge1xuICAgICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZSh0ZXh0RW5jb2Rlci5lbmNvZGUoc2hlbGwpKTtcbiAgICAgICAgICBlbmNvZGVyTWV0cmljcy5jaHVua0NvdW50Kys7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGNvbnN0IGNvbXBvbmVudCBvZiBjb21wb25lbnRzKSB7XG4gICAgICAgICAgY29uc3Qgb3V0cHV0ID0gYXdhaXQgcmVuZGVyRHNkKFxuICAgICAgICAgICAgY29tcG9uZW50LnRhZ05hbWUsXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGNvbXBvbmVudENsYXNzOiBjb21wb25lbnQuY29tcG9uZW50Q2xhc3MsXG4gICAgICAgICAgICAgIHByb3BzOiBjb21wb25lbnQucHJvcHMgPz8ge30sXG4gICAgICAgICAgICAgIHNvdXJjZUluZm86IGNvbXBvbmVudC5zb3VyY2VJbmZvLFxuICAgICAgICAgICAgICBkc2RPcHRpb25zOiBjb21wb25lbnQuZHNkT3B0aW9ucyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgKTtcbiAgICAgICAgICBmb3IgKGNvbnN0IGVycm9yIG9mIG91dHB1dC5lcnJvcnMpIHtcbiAgICAgICAgICAgIGVuY29kZXJNZXRyaWNzLmVycm9yQ291bnQrKztcbiAgICAgICAgICAgIG9wdGlvbnMub25FcnJvcj8uKGVycm9yLCBjb21wb25lbnQudGFnTmFtZSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZSh0ZXh0RW5jb2Rlci5lbmNvZGUob3V0cHV0Lmh0bWwpKTtcbiAgICAgICAgICBlbmNvZGVyTWV0cmljcy5jaHVua0NvdW50Kys7XG4gICAgICAgICAgb3B0aW9ucy5vbkNodW5rPy4oeyBodG1sOiBvdXRwdXQuaHRtbCwgb3V0cHV0IH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZm9vdGVyID0gYXdhaXQgcmVzb2x2ZVN0cmVhbVBhcnQob3B0aW9ucy5mb290ZXIpO1xuICAgICAgICBpZiAoZm9vdGVyKSB7XG4gICAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKHRleHRFbmNvZGVyLmVuY29kZShmb290ZXIpKTtcbiAgICAgICAgICBlbmNvZGVyTWV0cmljcy5jaHVua0NvdW50Kys7XG4gICAgICAgIH1cbiAgICAgICAgZW5jb2Rlck1ldHJpY3MuZW5kZWRBdCA9IHNhZmVOb3coKTtcbiAgICAgICAgY29udHJvbGxlci5jbG9zZSgpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgZW5jb2Rlck1ldHJpY3MuZXJyb3JDb3VudCsrO1xuICAgICAgICBlbmNvZGVyTWV0cmljcy5lbmRlZEF0ID0gc2FmZU5vdygpO1xuICAgICAgICBjb250cm9sbGVyLmVycm9yKGVycm9yKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7OztDQWFDLEdBRUQsU0FBUyxTQUFTLEVBQUUsT0FBTyxRQUFRLGtCQUFrQjtBQWlDckQsTUFBTSxjQUFjLElBQUk7QUFFeEIsZUFBZSxrQkFDYixJQUFnRDtFQUVoRCxJQUFJLENBQUMsTUFBTSxPQUFPO0VBQ2xCLE9BQU8sT0FBTyxTQUFTLGFBQWEsTUFBTSxTQUFTO0FBQ3JEO0FBRUE7O0NBRUMsR0FDRCxPQUFPLFNBQVM7RUFDZCxPQUFPO0lBQ0wsWUFBWTtJQUNaLFlBQVk7SUFDWixXQUFXO0VBQ2I7QUFDRjtBQUVBOzs7Ozs7Ozs7Ozs7OztDQWNDLEdBQ0QsT0FBTyxTQUFTLGdCQUNkLFVBQThDLEVBQzlDLFVBQWtDLENBQUMsQ0FBQztFQUVwQyxNQUFNLGlCQUFpQixRQUFRLE9BQU8sSUFBSTtFQUUxQyxPQUFPLElBQUksZUFBMkI7SUFDcEMsTUFBTSxPQUFNLFVBQVU7TUFDcEIsSUFBSTtRQUNGLE1BQU0sUUFBUSxNQUFNLGtCQUFrQixRQUFRLEtBQUs7UUFDbkQsSUFBSSxPQUFPO1VBQ1QsV0FBVyxPQUFPLENBQUMsWUFBWSxNQUFNLENBQUM7VUFDdEMsZUFBZSxVQUFVO1FBQzNCO1FBRUEsS0FBSyxNQUFNLGFBQWEsV0FBWTtVQUNsQyxNQUFNLFNBQVMsTUFBTSxVQUNuQixVQUFVLE9BQU8sRUFDakI7WUFDRSxnQkFBZ0IsVUFBVSxjQUFjO1lBQ3hDLE9BQU8sVUFBVSxLQUFLLElBQUksQ0FBQztZQUMzQixZQUFZLFVBQVUsVUFBVTtZQUNoQyxZQUFZLFVBQVUsVUFBVTtVQUNsQztVQUVGLEtBQUssTUFBTSxTQUFTLE9BQU8sTUFBTSxDQUFFO1lBQ2pDLGVBQWUsVUFBVTtZQUN6QixRQUFRLE9BQU8sR0FBRyxPQUFPLFVBQVUsT0FBTztVQUM1QztVQUNBLFdBQVcsT0FBTyxDQUFDLFlBQVksTUFBTSxDQUFDLE9BQU8sSUFBSTtVQUNqRCxlQUFlLFVBQVU7VUFDekIsUUFBUSxPQUFPLEdBQUc7WUFBRSxNQUFNLE9BQU8sSUFBSTtZQUFFO1VBQU87UUFDaEQ7UUFFQSxNQUFNLFNBQVMsTUFBTSxrQkFBa0IsUUFBUSxNQUFNO1FBQ3JELElBQUksUUFBUTtVQUNWLFdBQVcsT0FBTyxDQUFDLFlBQVksTUFBTSxDQUFDO1VBQ3RDLGVBQWUsVUFBVTtRQUMzQjtRQUNBLGVBQWUsT0FBTyxHQUFHO1FBQ3pCLFdBQVcsS0FBSztNQUNsQixFQUFFLE9BQU8sT0FBTztRQUNkLGVBQWUsVUFBVTtRQUN6QixlQUFlLE9BQU8sR0FBRztRQUN6QixXQUFXLEtBQUssQ0FBQztNQUNuQjtJQUNGO0VBQ0Y7QUFDRiJ9
|