vite-hmr-tchmi 1.0.0 → 1.1.0
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 -7
- package/dist/index.d.ts +1 -0
- package/dist/index.js +28 -0
- package/package.json +7 -2
- package/.github/workflows/publish.yml +0 -28
- package/src/index.ts +0 -46
- package/tsconfig.json +0 -28
- package/vite.config.ts +0 -25
package/Readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# vite-hmr-tchmi
|
|
2
2
|
|
|
3
3
|
A utility library to enable Hot Module Replacement (HMR) for Beckhoff TwinCAT HMI (TcHmi) Framework Controls when using Vite.
|
|
4
4
|
|
|
@@ -23,7 +23,7 @@ This package provides the necessary logic to hot-reload TcHmi Controls without r
|
|
|
23
23
|
## Installation
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
npm install
|
|
26
|
+
npm install vite-hmr-tchmi --save-dev
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
---
|
|
@@ -32,7 +32,7 @@ npm install tchmi-vite-hmr --save-dev
|
|
|
32
32
|
|
|
33
33
|
In your TcHmi Control script file, import the handler and call it within the Vite HMR lifecycle:
|
|
34
34
|
```ts
|
|
35
|
-
import { handleTcHmiHmr } from '
|
|
35
|
+
import { handleTcHmiHmr } from 'vite-hmr-tchmi';
|
|
36
36
|
|
|
37
37
|
// ... Your Control Class Definition ...
|
|
38
38
|
export class MyCustomControl extends TcHmi.Controls.System.TcHmiControl {
|
|
@@ -45,10 +45,6 @@ if (import.meta.hot) import.meta.hot.accept((newModule) => handleTcHmiHmr(newMod
|
|
|
45
45
|
|
|
46
46
|
---
|
|
47
47
|
|
|
48
|
-
Hier ist der restliche Teil der README ab How it works im Markdown-Format zum Kopieren:
|
|
49
|
-
|
|
50
|
-
Markdown
|
|
51
|
-
|
|
52
48
|
## How it works
|
|
53
49
|
|
|
54
50
|
When a file change is detected, Vite provides the updated module. The `handleTcHmiHmr` function:
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function handleTcHmiHmr(newModule: any): void;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function isClassExtending(e, t) {
|
|
2
|
+
if (!e || !t) return !1;
|
|
3
|
+
let n = typeof t == "string" ? t : t.name, r = e;
|
|
4
|
+
for (; r != null;) {
|
|
5
|
+
if (r === t || r.constructor.name === n) return !0;
|
|
6
|
+
r = Object.getPrototypeOf(r);
|
|
7
|
+
}
|
|
8
|
+
return !1;
|
|
9
|
+
}
|
|
10
|
+
function handleTcHmiHmr(t) {
|
|
11
|
+
if (t) for (let [n, r] of Object.entries(t)) {
|
|
12
|
+
if (!isClassExtending(r, "TcHmi.Controls.System.TcHmiControl")) continue;
|
|
13
|
+
let t = r, n = Array.from(window.TcHmi.Controls.getMap()).filter(([n, r]) => isClassExtending(r, t));
|
|
14
|
+
console.groupCollapsed(`🔥 HMR: Updated '${t.name}' with ${n.length} instances.`);
|
|
15
|
+
for (let [e, r] of n) {
|
|
16
|
+
r.__detach(), Object.setPrototypeOf(r, t.prototype), r.__attach();
|
|
17
|
+
let n = {
|
|
18
|
+
type: r.getType(),
|
|
19
|
+
dom: r.getElement()[0],
|
|
20
|
+
instance: r,
|
|
21
|
+
[Symbol.toStringTag]: `✅ Patched & Reattached: '${e}'`
|
|
22
|
+
};
|
|
23
|
+
console.dir(n);
|
|
24
|
+
}
|
|
25
|
+
console.groupEnd();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export { handleTcHmiHmr };
|
package/package.json
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vite-hmr-tchmi",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
6
11
|
"scripts": {
|
|
7
12
|
"dev": "tsc --watch",
|
|
8
|
-
"build": "
|
|
13
|
+
"build": "vite build && tsc"
|
|
9
14
|
},
|
|
10
15
|
"repository": {
|
|
11
16
|
"type": "git",
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
name: Publish to npm
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
release:
|
|
5
|
-
types: [published]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
build-and-publish:
|
|
9
|
-
runs-on: ubuntu-latest
|
|
10
|
-
steps:
|
|
11
|
-
- uses: actions/checkout@v4
|
|
12
|
-
|
|
13
|
-
- name: Setup Node.js
|
|
14
|
-
uses: actions/setup-node@v4
|
|
15
|
-
with:
|
|
16
|
-
node-version: '20'
|
|
17
|
-
registry-url: 'https://registry.npmjs.org'
|
|
18
|
-
|
|
19
|
-
- name: Install dependencies
|
|
20
|
-
run: npm install
|
|
21
|
-
|
|
22
|
-
- name: Build project
|
|
23
|
-
run: npm run build
|
|
24
|
-
|
|
25
|
-
- name: Publish to npm
|
|
26
|
-
run: npm publish
|
|
27
|
-
env:
|
|
28
|
-
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/src/index.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
function isClassExtending(targetClass: any, baseClass: any) {
|
|
2
|
-
if (!targetClass || !baseClass) return false;
|
|
3
|
-
|
|
4
|
-
const baseName = typeof baseClass === 'string' ? baseClass : baseClass.name;
|
|
5
|
-
|
|
6
|
-
let current = targetClass;
|
|
7
|
-
while (current !== null && current !== undefined) {
|
|
8
|
-
if (current === baseClass) return true;
|
|
9
|
-
if (current.constructor.name === baseName) return true;
|
|
10
|
-
|
|
11
|
-
current = Object.getPrototypeOf(current);
|
|
12
|
-
}
|
|
13
|
-
return false;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function handleTcHmiHmr(newModule: any) {
|
|
17
|
-
|
|
18
|
-
if (!newModule) return;
|
|
19
|
-
|
|
20
|
-
for (const [_, newModuleElement] of Object.entries(newModule)) {
|
|
21
|
-
if (!(isClassExtending(newModuleElement, "TcHmi.Controls.System.TcHmiControl"))) continue;
|
|
22
|
-
const newControl = newModuleElement as any;
|
|
23
|
-
|
|
24
|
-
const instances = Array.from((window as any).TcHmi.Controls.getMap())
|
|
25
|
-
.filter(([_, inst]: any) => isClassExtending(inst, newControl)) as any[];
|
|
26
|
-
|
|
27
|
-
console.groupCollapsed(`🔥 HMR: Updated '${newControl.name}' with ${instances.length} instances.`);
|
|
28
|
-
|
|
29
|
-
for (const [id, instance] of instances) {
|
|
30
|
-
instance.__detach();
|
|
31
|
-
Object.setPrototypeOf(instance, newControl.prototype);
|
|
32
|
-
instance.__attach();
|
|
33
|
-
|
|
34
|
-
const logHelper = {
|
|
35
|
-
type: instance.getType(),
|
|
36
|
-
dom: instance.getElement()[0],
|
|
37
|
-
instance: instance,
|
|
38
|
-
[Symbol.toStringTag]: `✅ Patched & Reattached: '${id}'`
|
|
39
|
-
}
|
|
40
|
-
console.dir(logHelper);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
console.groupEnd();
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"useDefineForClassFields": true,
|
|
5
|
-
"module": "ESNext",
|
|
6
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
-
"types": ["vite/client"],
|
|
8
|
-
"skipLibCheck": true,
|
|
9
|
-
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"allowImportingTsExtensions": true,
|
|
12
|
-
"verbatimModuleSyntax": true,
|
|
13
|
-
"moduleDetection": "force",
|
|
14
|
-
|
|
15
|
-
"noEmit": false,
|
|
16
|
-
"outDir": "dist",
|
|
17
|
-
"declaration": true,
|
|
18
|
-
"emitDeclarationOnly": true,
|
|
19
|
-
|
|
20
|
-
"strict": true,
|
|
21
|
-
"noUnusedLocals": true,
|
|
22
|
-
"noUnusedParameters": true,
|
|
23
|
-
"erasableSyntaxOnly": true,
|
|
24
|
-
"noFallthroughCasesInSwitch": true,
|
|
25
|
-
"noUncheckedSideEffectImports": true
|
|
26
|
-
},
|
|
27
|
-
"include": ["src"]
|
|
28
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from 'vite';
|
|
2
|
-
import { resolve } from 'path';
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
build: {
|
|
6
|
-
ssr: true,
|
|
7
|
-
lib: {
|
|
8
|
-
entry: resolve(__dirname, 'src/index.ts'),
|
|
9
|
-
name: 'ViteHmrTcHmi',
|
|
10
|
-
fileName: 'index',
|
|
11
|
-
formats: ['es']
|
|
12
|
-
},
|
|
13
|
-
rollupOptions: {
|
|
14
|
-
external: [
|
|
15
|
-
'vite',
|
|
16
|
-
],
|
|
17
|
-
output: {
|
|
18
|
-
globals: {
|
|
19
|
-
vite: 'Vite'
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
minify: true
|
|
24
|
-
}
|
|
25
|
-
});
|