@schalkneethling/miyagi-core 4.2.0 → 4.3.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/dist/js/iframe.js +1 -1
- package/frontend/assets/js/_socket.js +79 -6
- package/lib/config.js +24 -0
- package/lib/default-config.js +58 -0
- package/lib/init/args.js +13 -0
- package/lib/init/config.js +216 -0
- package/lib/init/watcher.js +608 -234
- package/package.json +3 -3
package/dist/js/iframe.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
customElements.define("accordion-tabs",class extends HTMLElement{#e;#t;#
|
|
1
|
+
customElements.define("accordion-tabs",class extends HTMLElement{#e;#t;#n;#i;#s;static get observedAttributes(){return["breakpoint","current"]}constructor(){super()}connectedCallback(){if(!this.closest("code")){if(this.content=[],this.hasAttribute("breakpoint")){const e=this.getAttribute("breakpoint"),t=parseInt(e,10);let n;n=e.endsWith("rem")?t*parseInt(window.getComputedStyle(document.documentElement).fontSize,10):e.endsWith("em")?t*parseInt(window.getComputedStyle(this).fontSize,10):t,this.#t=n}window.requestAnimationFrame(()=>{this.details=Array.from(this.children),this.details.forEach((e,t)=>{const n=e.querySelector("summary");e.open&&(this.index=t),this.content.push({title:n.textContent,content:[...n.parentElement.children].filter(e=>1===e.nodeType&&e!==n)})});let e=!1;this.#i=new ResizeObserver(t=>{if(e)for(const e of t)this.#r(e.borderBoxSize[0].inlineSize);e=!0}),this.#r(this.clientWidth,()=>{this.#i.observe(this)})})}}attributeChangedCallback(e,t,n){"current"===e&&(this.index=parseInt(n,10),this.#r(this.clientWidth))}disconnectedCallback(){this.#i&&this.#i.disconnect()}async#r(e,t){!this.#t||e<this.#t?(await this.#o(),this.#n="accordion"):(await this.#a(),this.#n="tabs"),t&&t()}#o(){return this.#e||(this.#e=new e(this)),"tabs"===this.#n?(this.#c(),this.#e.setElements(),this.#e.elements.forEach(e=>this.appendChild(e))):this.#e.render(),!0}async#a(){this.#c(),this.#s?(this.#s.index="number"==typeof this.index?this.index:0,this.#s.setElements()):this.#s=new t(this);const[e,n]=this.#s.elements;return this.appendChild(e),n.forEach(e=>{this.appendChild(e)}),await this.#s.render(!1)}#c(){Array.from(this.children).forEach(e=>this.removeChild(e))}});class e{constructor(e){this.AccordionTabs=e,this.elements=this.AccordionTabs.details,this.elements.forEach((e,t)=>{e.querySelector("summary").addEventListener("click",({target:e})=>{requestAnimationFrame(()=>{this.#d(e.closest("details"),t)})})}),this.render()}setElements(){this.elements.forEach((e,t)=>{this.AccordionTabs.content[t].content.forEach(t=>e.appendChild(t)),e.open=t===this.AccordionTabs.index})}render(){this.elements.forEach((e,t)=>{e.open=t===this.AccordionTabs.index})}#d(e,t){e.open?(this.elements.forEach(t=>{e!==t&&(t.open=!1)}),this.AccordionTabs.index=t):this.AccordionTabs.index=null}}class t{#h;#l=[];#b=[];#u;constructor(e){this.#h=e,this.elements=this.getElements(),this.index="number"==typeof this.#h.index?this.#h.index:0,this.#u=new n(this)}getElements(){const e=document.createElement("ol"),t=[];return this.#h.content.forEach(({title:n,content:i},s)=>{const r=document.createElement("button"),o=document.createElement("li"),a=document.createElement("div"),c=crypto.randomUUID(),d=`tab-${c}`,h=`panel-${c}`;e.setAttribute("role","tablist"),o.setAttribute("role","presentation"),r.textContent=n,r.type="button",r.id=d,r.setAttribute("aria-selected",s===this.index?"true":"false"),r.setAttribute("tabindex",s===this.index?0:-1),r.setAttribute("aria-controls",h),r.setAttribute("role","tab"),this.#l.push(r),o.appendChild(r),e.appendChild(o),i.forEach(e=>{a.appendChild(e)}),a.id=h,a.hidden=this.index!==s,a.setAttribute("role","tabpanel"),a.setAttribute("tabindex","0"),a.setAttribute("aria-labelledby",d),t.push(a),this.#b.push(a)}),[e,t]}setElements(){this.elements[1].forEach((e,t)=>{this.#h.content[t].content.forEach(t=>e.appendChild(t))})}setActiveTab(e){this.#h.index=this.index=e,this.render()}async render(e=!0){return this.elements[1].forEach((e,t)=>{e.hidden=t!==this.index}),await this.#u.render(e)}}class n{#m;#p;constructor(e){this.#m=e,this.#p=Array.from(this.#m.elements[0].querySelectorAll("button")),this.#p.forEach(e=>{e.addEventListener("click",this.#T.bind(this)),e.addEventListener("keydown",this.#f.bind(this))})}#T({currentTarget:e}){this.#m.setActiveTab(this.#p.indexOf(e))}#f(e){const{dir:t}=e.target.closest("[dir]")||document.documentElement;let n=!1;switch(e.key){case"ArrowLeft":"rtl"===t?this.#w():this.#A(),n=!0;break;case"ArrowRight":"rtl"===t?this.#A():this.#w(),n=!0;break;case"Home":this.#m.setActiveTab(0),n=!0;break;case"End":this.#m.setActiveTab(this.#p.length-1),n=!0}n&&(e.stopPropagation(),e.preventDefault())}#w(){this.#m.setActiveTab(this.#m.index===this.#p.length-1?0:this.#m.index+1)}#A(){this.#m.setActiveTab(0===this.#m.index?this.#p.length-1:this.#m.index-1)}render(e=!0){return this.#p.forEach((t,n)=>{n===this.#m.index?(t.setAttribute("aria-selected","true"),t.removeAttribute("tabindex"),e&&t.focus()):(t.setAttribute("aria-selected","false"),t.setAttribute("tabindex",-1))}),new Promise(e=>setTimeout(e,1e3))}}let i,s=250;function r(e){const t=function(e){return"reloadParent"===e?"parent":"string"==typeof e&&0===e.length?"iframe":null}(e);return t||function(e){try{return JSON.parse(e).scope||"iframe"}catch{return"iframe"}}(e)}function o(){i=new WebSocket(`${"https:"===window.location.protocol?"wss":"ws"}://${window.location.host}/__miyagi_ws`),i.onopen=()=>{s=250},i.onmessage=e=>{"parent"!==r(e.data)?window.location.reload():parent.window.location.reload()},i.onerror=()=>{i.close()},i.onclose=()=>{!function(){const e=Math.floor(100*Math.random()),t=Math.min(s+e,5e3);s=Math.min(2*s,5e3),window.setTimeout(()=>{o()},t)}()}}o();function a(e){return["INPUT","SELECT","TEXTAREA"].includes(e)}window.location.pathname.startsWith("/component?")&&window.location.href.indexOf("&embedded=true")>=0&&window.self===window.top&&(window.location=new URL(window.location).replace("&embedded=true","")),document.addEventListener("DOMContentLoaded",function(){const e=Array.from(document.querySelectorAll(".Component-file")),t=document.querySelector(".Styleguide");e.length>0&&import("./_iframe-links-DdifIr4P.js").then(t=>{t.default(e)}).catch(e=>console.error(e)),document.querySelector(".Code")&&import("./_prism-By3NMwUd.js"),t&&import("./index-BKDKaBC6.js").then(e=>new e.default(t)).catch(e=>console.error(e)),document.querySelector(".js-openMockData")&&import("./_mock-data-Dypo4Bl_.js")}),document.addEventListener("keyup",e=>{const{path:t,originalTarget:n,target:i,key:s}=e,r=t?t[0]:n||i;((e,t)=>!a(e.tagName)&&"f"===t)(r,s)?parent.window.dispatchEvent(new CustomEvent("searchTriggered")):((e,t)=>!a(e.tagName)&&"g"===t)(r,s)&&parent.window.dispatchEvent(new CustomEvent("gotoTriggered"))});
|
|
@@ -1,9 +1,82 @@
|
|
|
1
|
-
const
|
|
1
|
+
const SOCKET_PATH = "/__miyagi_ws";
|
|
2
|
+
const INITIAL_RETRY_DELAY_MS = 250;
|
|
3
|
+
const MAX_RETRY_DELAY_MS = 5000;
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
let retryDelay = INITIAL_RETRY_DELAY_MS;
|
|
6
|
+
let websocket;
|
|
7
|
+
|
|
8
|
+
function getWebSocketUrl() {
|
|
9
|
+
const protocol = window.location.protocol === "https:" ? "wss" : "ws";
|
|
10
|
+
return `${protocol}://${window.location.host}${SOCKET_PATH}`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function triggerReload(scope) {
|
|
14
|
+
if (scope === "parent") {
|
|
5
15
|
parent.window.location.reload();
|
|
6
|
-
|
|
7
|
-
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
window.location.reload();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function parseLegacyScope(messageData) {
|
|
23
|
+
if (messageData === "reloadParent") {
|
|
24
|
+
return "parent";
|
|
8
25
|
}
|
|
9
|
-
|
|
26
|
+
|
|
27
|
+
if (typeof messageData === "string" && messageData.length === 0) {
|
|
28
|
+
return "iframe";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function parseJsonScope(messageData) {
|
|
35
|
+
try {
|
|
36
|
+
const parsed = JSON.parse(messageData);
|
|
37
|
+
return parsed.scope || "iframe";
|
|
38
|
+
} catch {
|
|
39
|
+
return "iframe";
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function parseScope(messageData) {
|
|
44
|
+
const legacyScope = parseLegacyScope(messageData);
|
|
45
|
+
if (legacyScope) {
|
|
46
|
+
return legacyScope;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return parseJsonScope(messageData);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function scheduleReconnect() {
|
|
53
|
+
const jitter = Math.floor(Math.random() * 100);
|
|
54
|
+
const delay = Math.min(retryDelay + jitter, MAX_RETRY_DELAY_MS);
|
|
55
|
+
retryDelay = Math.min(retryDelay * 2, MAX_RETRY_DELAY_MS);
|
|
56
|
+
|
|
57
|
+
window.setTimeout(() => {
|
|
58
|
+
connect();
|
|
59
|
+
}, delay);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function connect() {
|
|
63
|
+
websocket = new WebSocket(getWebSocketUrl());
|
|
64
|
+
|
|
65
|
+
websocket.onopen = () => {
|
|
66
|
+
retryDelay = INITIAL_RETRY_DELAY_MS;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
websocket.onmessage = (message) => {
|
|
70
|
+
triggerReload(parseScope(message.data));
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
websocket.onerror = () => {
|
|
74
|
+
websocket.close();
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
websocket.onclose = () => {
|
|
78
|
+
scheduleReconnect();
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
connect();
|
package/lib/config.js
CHANGED
|
@@ -70,5 +70,29 @@ function getCliArgs(args) {
|
|
|
70
70
|
|
|
71
71
|
cliArgs.build = buildArgs;
|
|
72
72
|
|
|
73
|
+
if (
|
|
74
|
+
cliArgs.watchReport !== undefined ||
|
|
75
|
+
cliArgs.watchReportFormat !== undefined ||
|
|
76
|
+
cliArgs.watchReportNoColor !== undefined
|
|
77
|
+
) {
|
|
78
|
+
cliArgs.watch = cliArgs.watch || {};
|
|
79
|
+
cliArgs.watch.report = cliArgs.watch.report || {};
|
|
80
|
+
|
|
81
|
+
if (cliArgs.watchReport !== undefined) {
|
|
82
|
+
cliArgs.watch.report.enabled = cliArgs.watchReport;
|
|
83
|
+
delete cliArgs.watchReport;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (cliArgs.watchReportFormat !== undefined) {
|
|
87
|
+
cliArgs.watch.report.format = cliArgs.watchReportFormat;
|
|
88
|
+
delete cliArgs.watchReportFormat;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (cliArgs.watchReportNoColor !== undefined) {
|
|
92
|
+
cliArgs.watch.report.useColors = !cliArgs.watchReportNoColor;
|
|
93
|
+
delete cliArgs.watchReportNoColor;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
73
97
|
return cliArgs;
|
|
74
98
|
}
|
package/lib/default-config.js
CHANGED
|
@@ -97,6 +97,64 @@ export default {
|
|
|
97
97
|
},
|
|
98
98
|
watchConfigFile: true,
|
|
99
99
|
},
|
|
100
|
+
watch: {
|
|
101
|
+
enabled: true,
|
|
102
|
+
backend: "chokidar",
|
|
103
|
+
sources: [],
|
|
104
|
+
ignore: {
|
|
105
|
+
defaults: true,
|
|
106
|
+
patterns: [],
|
|
107
|
+
},
|
|
108
|
+
behavior: {
|
|
109
|
+
debounceMs: 60,
|
|
110
|
+
coalesceWindowMs: 120,
|
|
111
|
+
awaitWriteFinish: {
|
|
112
|
+
enabled: true,
|
|
113
|
+
stabilityThresholdMs: 200,
|
|
114
|
+
pollIntervalMs: 50,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
reload: {
|
|
118
|
+
enabled: true,
|
|
119
|
+
rules: {
|
|
120
|
+
template: "iframe",
|
|
121
|
+
data: "parent",
|
|
122
|
+
docs: "parent",
|
|
123
|
+
schema: "iframe",
|
|
124
|
+
componentAsset: "none",
|
|
125
|
+
globalCss: "none",
|
|
126
|
+
globalJs: "none",
|
|
127
|
+
unknown: "parent",
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
socket: {
|
|
131
|
+
reconnect: {
|
|
132
|
+
enabled: true,
|
|
133
|
+
initialDelayMs: 250,
|
|
134
|
+
maxDelayMs: 5000,
|
|
135
|
+
jitter: true,
|
|
136
|
+
},
|
|
137
|
+
heartbeat: {
|
|
138
|
+
enabled: true,
|
|
139
|
+
intervalMs: 30000,
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
report: {
|
|
143
|
+
enabled: true,
|
|
144
|
+
onStart: true,
|
|
145
|
+
format: "summary",
|
|
146
|
+
destination: "stdout",
|
|
147
|
+
useColors: true,
|
|
148
|
+
},
|
|
149
|
+
configFile: {
|
|
150
|
+
enabled: true,
|
|
151
|
+
},
|
|
152
|
+
debug: {
|
|
153
|
+
logEvents: false,
|
|
154
|
+
logDecisions: false,
|
|
155
|
+
logResolvedSources: false,
|
|
156
|
+
},
|
|
157
|
+
},
|
|
100
158
|
schema: {
|
|
101
159
|
ajv: AJV,
|
|
102
160
|
verbose: false,
|
package/lib/init/args.js
CHANGED
|
@@ -14,6 +14,19 @@ export default yargs(hideBin(process.argv))
|
|
|
14
14
|
"Logging additional information — helpful mainly in case of errors.",
|
|
15
15
|
type: "boolean",
|
|
16
16
|
},
|
|
17
|
+
"watch-report": {
|
|
18
|
+
description: "Enable watch report output on startup.",
|
|
19
|
+
type: "boolean",
|
|
20
|
+
},
|
|
21
|
+
"watch-report-format": {
|
|
22
|
+
description: "Set watch report format.",
|
|
23
|
+
type: "string",
|
|
24
|
+
choices: ["pretty", "summary", "json"],
|
|
25
|
+
},
|
|
26
|
+
"watch-report-no-color": {
|
|
27
|
+
description: "Disable colors in watch report output.",
|
|
28
|
+
type: "boolean",
|
|
29
|
+
},
|
|
17
30
|
})
|
|
18
31
|
.command("build", "Creates a static build of all your components", {
|
|
19
32
|
folder: {
|
package/lib/init/config.js
CHANGED
|
@@ -39,6 +39,30 @@ function sanitizePath(path) {
|
|
|
39
39
|
return sanitizedPath;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Keep watch paths relative-friendly (do not strip leading slash),
|
|
44
|
+
* but normalize common user input like "./foo/"
|
|
45
|
+
* @param {string} watchPath
|
|
46
|
+
* @returns {string}
|
|
47
|
+
*/
|
|
48
|
+
function sanitizeWatchPath(watchPath) {
|
|
49
|
+
if (typeof watchPath !== "string") {
|
|
50
|
+
return watchPath;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let sanitizedPath = watchPath;
|
|
54
|
+
|
|
55
|
+
if (sanitizedPath.startsWith("./")) {
|
|
56
|
+
sanitizedPath = sanitizedPath.slice(2);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (sanitizedPath.endsWith("/")) {
|
|
60
|
+
sanitizedPath = sanitizedPath.slice(0, -1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return sanitizedPath;
|
|
64
|
+
}
|
|
65
|
+
|
|
42
66
|
/**
|
|
43
67
|
* @param {string|Array} strOrArr - file path or array of file paths
|
|
44
68
|
* @returns {Array} the given file path in an array or simply the given array
|
|
@@ -47,6 +71,195 @@ function arrayfy(strOrArr) {
|
|
|
47
71
|
return Array.isArray(strOrArr) ? strOrArr : [strOrArr];
|
|
48
72
|
}
|
|
49
73
|
|
|
74
|
+
/**
|
|
75
|
+
* @param {object} merged
|
|
76
|
+
* @returns {object[]}
|
|
77
|
+
*/
|
|
78
|
+
function getDefaultWatchSources(merged) {
|
|
79
|
+
const sources = [];
|
|
80
|
+
const sourceByPath = new Set();
|
|
81
|
+
|
|
82
|
+
const addSource = (source) => {
|
|
83
|
+
if (!source || typeof source.path !== "string" || source.path.length === 0) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const key = `${source.type}:${source.path}`;
|
|
88
|
+
// Deduplicate watch targets; While calling add on Set will dedup,
|
|
89
|
+
// we need a conditional to avoid adding duplicates to the `sources` array.
|
|
90
|
+
if (sourceByPath.has(key)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
sourceByPath.add(key);
|
|
95
|
+
sources.push(source);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
if (merged.components.folder) {
|
|
99
|
+
addSource({
|
|
100
|
+
id: "components",
|
|
101
|
+
type: "dir",
|
|
102
|
+
path: sanitizeWatchPath(merged.components.folder),
|
|
103
|
+
recursive: true,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (merged.docs?.folder) {
|
|
108
|
+
addSource({
|
|
109
|
+
id: "docs",
|
|
110
|
+
type: "dir",
|
|
111
|
+
path: sanitizeWatchPath(merged.docs.folder),
|
|
112
|
+
recursive: true,
|
|
113
|
+
optional: true,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
for (const folder of merged.assets.folder || []) {
|
|
118
|
+
addSource({
|
|
119
|
+
id: `assets-folder-${folder}`,
|
|
120
|
+
type: "dir",
|
|
121
|
+
path: sanitizeWatchPath(path.join(merged.assets.root, folder)),
|
|
122
|
+
recursive: true,
|
|
123
|
+
optional: true,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const localCssFiles = [...(merged.assets.css || []), ...(merged.assets.shared?.css || [])]
|
|
128
|
+
.filter((filePath) => !filePath.startsWith("http://"))
|
|
129
|
+
.filter((filePath) => !filePath.startsWith("https://"))
|
|
130
|
+
.filter((filePath) => !filePath.startsWith("://"));
|
|
131
|
+
|
|
132
|
+
for (const cssFile of localCssFiles) {
|
|
133
|
+
addSource({
|
|
134
|
+
id: `assets-css-${cssFile}`,
|
|
135
|
+
type: "file",
|
|
136
|
+
path: sanitizeWatchPath(path.join(merged.assets.root, cssFile)),
|
|
137
|
+
optional: true,
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
const localJsFiles = [...(merged.assets.js || []), ...(merged.assets.shared?.js || [])]
|
|
142
|
+
.map((entry) => entry.src || entry)
|
|
143
|
+
.filter((filePath) => typeof filePath === "string")
|
|
144
|
+
.filter((filePath) => !filePath.startsWith("http://"))
|
|
145
|
+
.filter((filePath) => !filePath.startsWith("https://"))
|
|
146
|
+
.filter((filePath) => !filePath.startsWith("://"));
|
|
147
|
+
|
|
148
|
+
for (const jsFile of localJsFiles) {
|
|
149
|
+
addSource({
|
|
150
|
+
id: `assets-js-${jsFile}`,
|
|
151
|
+
type: "file",
|
|
152
|
+
path: sanitizeWatchPath(path.join(merged.assets.root, jsFile)),
|
|
153
|
+
optional: true,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (merged.userFileName && merged.watch?.configFile?.enabled) {
|
|
158
|
+
addSource({
|
|
159
|
+
id: "config-file",
|
|
160
|
+
type: "file",
|
|
161
|
+
path: sanitizeWatchPath(merged.userFileName),
|
|
162
|
+
optional: true,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
return sources;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @param {object} watchConfig
|
|
171
|
+
* @returns {object[]}
|
|
172
|
+
*/
|
|
173
|
+
function normalizeWatchSources(watchConfig) {
|
|
174
|
+
if (!Array.isArray(watchConfig.sources) || watchConfig.sources.length === 0) {
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return watchConfig.sources
|
|
179
|
+
.map((source, index) => {
|
|
180
|
+
if (!source || typeof source.path !== "string" || source.path.length === 0) {
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const type = source.type === "file" ? "file" : "dir";
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
id: source.id || `source-${index + 1}`,
|
|
188
|
+
type,
|
|
189
|
+
path: sanitizeWatchPath(source.path),
|
|
190
|
+
recursive: source.recursive !== false,
|
|
191
|
+
optional: source.optional === true,
|
|
192
|
+
};
|
|
193
|
+
})
|
|
194
|
+
.filter(Boolean);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Applies legacy watch-related config keys to watch config
|
|
199
|
+
* while preserving explicit new watch config values.
|
|
200
|
+
* @param {object} merged
|
|
201
|
+
* @param {object} userConfig
|
|
202
|
+
*/
|
|
203
|
+
function applyLegacyWatchCompatibility(merged, userConfig) {
|
|
204
|
+
merged.watch.configFile = merged.watch.configFile || { enabled: true };
|
|
205
|
+
merged.watch.configFile.enabled =
|
|
206
|
+
typeof merged.watch.configFile.enabled === "boolean"
|
|
207
|
+
? merged.watch.configFile.enabled
|
|
208
|
+
: merged.ui.watchConfigFile;
|
|
209
|
+
|
|
210
|
+
merged.watch.reload = merged.watch.reload || {};
|
|
211
|
+
merged.watch.reload.enabled =
|
|
212
|
+
typeof merged.watch.reload.enabled === "boolean"
|
|
213
|
+
? merged.watch.reload.enabled
|
|
214
|
+
: merged.ui.reload;
|
|
215
|
+
|
|
216
|
+
const userReloadRules = userConfig.watch?.reload?.rules || {};
|
|
217
|
+
merged.watch.reload.rules = {
|
|
218
|
+
...defaultUserConfig.watch.reload.rules,
|
|
219
|
+
...(merged.watch.reload.rules || {}),
|
|
220
|
+
componentAsset:
|
|
221
|
+
userReloadRules.componentAsset ??
|
|
222
|
+
(merged.ui.reloadAfterChanges.componentAssets
|
|
223
|
+
? "iframe"
|
|
224
|
+
: defaultUserConfig.watch.reload.rules.componentAsset),
|
|
225
|
+
globalCss:
|
|
226
|
+
userReloadRules.globalCss ??
|
|
227
|
+
(merged.ui.reloadAfterChanges.componentAssets
|
|
228
|
+
? "iframe"
|
|
229
|
+
: defaultUserConfig.watch.reload.rules.globalCss),
|
|
230
|
+
globalJs:
|
|
231
|
+
userReloadRules.globalJs ??
|
|
232
|
+
(merged.ui.reloadAfterChanges.componentAssets
|
|
233
|
+
? "iframe"
|
|
234
|
+
: defaultUserConfig.watch.reload.rules.globalJs),
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
merged.watch.ignore = merged.watch.ignore || {};
|
|
238
|
+
merged.watch.ignore.patterns = [
|
|
239
|
+
...(merged.watch.ignore.patterns || []),
|
|
240
|
+
...(merged.components.ignores || []),
|
|
241
|
+
].filter((entry) => typeof entry === "string");
|
|
242
|
+
merged.watch.ignore.patterns = [...new Set(merged.watch.ignore.patterns)];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Normalizes and validates new watch config values.
|
|
247
|
+
* @param {object} merged
|
|
248
|
+
*/
|
|
249
|
+
function normalizeAndValidateWatchConfig(merged) {
|
|
250
|
+
if (merged.watch?.backend === "node-watch") {
|
|
251
|
+
throw new Error(
|
|
252
|
+
'`watch.backend="node-watch"` is no longer supported. Please use `watch.backend="chokidar"`. See https://docs.miyagi.dev/configuration/options/ for migration details.',
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
merged.watch.backend = "chokidar";
|
|
257
|
+
merged.watch.sources = normalizeWatchSources(merged.watch);
|
|
258
|
+
if (merged.watch.sources.length === 0) {
|
|
259
|
+
merged.watch.sources = getDefaultWatchSources(merged);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
50
263
|
/**
|
|
51
264
|
*
|
|
52
265
|
* @param {object} root0
|
|
@@ -335,6 +548,9 @@ export default (userConfig = {}) => {
|
|
|
335
548
|
merged.lint.logLevel = defaultUserConfig.lint.logLevel;
|
|
336
549
|
}
|
|
337
550
|
|
|
551
|
+
applyLegacyWatchCompatibility(merged, config);
|
|
552
|
+
normalizeAndValidateWatchConfig(merged);
|
|
553
|
+
|
|
338
554
|
return merged;
|
|
339
555
|
};
|
|
340
556
|
|