iobroker.eos-admin 7.9.95 → 7.9.96
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/INSTALL_TEST_V7.9.96.md +11 -0
- package/MERGE_UPDATE_README_V7.9.96.md +5 -0
- package/NEXOWATT_EOS_BUILD_INFO.json +18 -23
- package/NexoWatt_EOS_Admin_EMS_OVERVIEW_MERGE_VALIDATION.md +44 -0
- package/PUBLISH_STABLE_V7.9.96.md +10 -0
- package/RC73_EOS_ADMIN_MERGE_VALIDATION.md +78 -0
- package/README_EMS_OVERVIEW_MERGE.md +45 -0
- package/README_STABILITY_V7.9.96.md +11 -0
- package/RELEASE_ACCEPTANCE_V7.9.96.md +10 -0
- package/RELEASE_NOTES_V7.9.96.md +12 -0
- package/VALIDATION_EMS_OVERVIEW_MERGE.md +35 -0
- package/adminWww/assets/Intro-DkwRiz1n-v84.js +2 -2
- package/adminWww/assets/index-D2ymscJA-v84.js +1 -1
- package/adminWww/css/eos-ems-overview.css +62 -0
- package/adminWww/css/nexowatt-native-shell.css +111 -13
- package/adminWww/index.html +15 -13
- package/adminWww/js/eos-assistant.js +1 -1
- package/adminWww/js/eos-ems-overview.js +140 -0
- package/adminWww/js/eos-role-bootstrap.js +4 -4
- package/adminWww/js/eos-role-ui.js +34 -38
- package/adminWww/js/nexowatt-native-shell.js +11 -6
- package/adminWww/static/js/nexowatt-stable-login.js +12 -12
- package/adminWww/static/js/nexowatt-stable-v96.js +82 -0
- package/io-package.json +10 -5
- package/package.json +38 -12
- package/tools/nexowatt-account-management-selftest.cjs +60 -0
- package/tools/nexowatt-apply-ems-overview.cjs +115 -0
- package/tools/nexowatt-clean-legacy-runtime.cjs +151 -0
- package/tools/nexowatt-ems-overview-selftest.cjs +35 -0
- package/tools/nexowatt-ensure-release-defaults.cjs +72 -0
- package/tools/nexowatt-generate-eos-admin-repo-entry.cjs +37 -0
- package/tools/nexowatt-generate-repo-entry.cjs +3 -0
- package/tools/nexowatt-internal-reserve-selftest.cjs +55 -0
- package/tools/nexowatt-login-layout-selftest.cjs +83 -0
- package/tools/nexowatt-merge-update-selftest.cjs +69 -0
- package/tools/nexowatt-modern-ui-selftest.cjs +49 -0
- package/tools/nexowatt-patch-repo.cjs +54 -0
- package/tools/nexowatt-publish-channel-guard.cjs +58 -0
- package/tools/nexowatt-release-defaults-selftest.cjs +29 -0
- package/tools/nexowatt-runtime-cleanup-selftest.cjs +47 -0
- package/tools/nexowatt-stable-v96-selftest.cjs +13 -0
- package/tools/nexowatt-sync-release-version.cjs +181 -0
- package/tools/nexowatt-ui-overview-runtime-selftest.cjs +16 -0
- package/tools/nexowatt-validate-package.cjs +277 -0
- package/tools/nexowatt-version-sync-selftest.cjs +86 -0
- package/INSTALL_TEST_V7.9.95.md +0 -15
- package/NEXOWATT_EOS_STABLE_7.9.94.md +0 -16
- package/PUBLISH_STABLE_V7.9.95.md +0 -16
- package/README_STABILITY_V7.9.95.md +0 -12
- package/RELEASE_ACCEPTANCE_V7.9.95.md +0 -11
- package/RELEASE_NOTES_V7.9.95.md +0 -12
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const path = require('node:path');
|
|
6
|
+
|
|
7
|
+
function readJson(file) {
|
|
8
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function writeJson(file, value) {
|
|
12
|
+
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function setValue(changes, label, object, key, value) {
|
|
16
|
+
if (object[key] !== value) {
|
|
17
|
+
changes.push({ label, previous: object[key], value });
|
|
18
|
+
object[key] = value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function syncReleaseVersion(rootDir) {
|
|
23
|
+
const root = path.resolve(rootDir);
|
|
24
|
+
const packageFile = path.join(root, 'package.json');
|
|
25
|
+
if (!fs.existsSync(packageFile)) {
|
|
26
|
+
throw new Error(`package.json not found in ${root}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const pkg = readJson(packageFile);
|
|
30
|
+
const version = String(pkg.version || '').trim();
|
|
31
|
+
if (!/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) {
|
|
32
|
+
throw new Error(`Invalid package.json version: ${version || '<missing>'}`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const releaseNo = version.match(/^7\.9\.(\d+)/)?.[1] || version.replace(/[^0-9A-Za-z]+/g, '-');
|
|
36
|
+
const expectedBase = `https://unpkg.com/iobroker.eos-admin@${version}`;
|
|
37
|
+
const changes = [];
|
|
38
|
+
|
|
39
|
+
// Keep the human-readable release policy aligned with the package version.
|
|
40
|
+
if (pkg.nexowattReleasePolicy && typeof pkg.nexowattReleasePolicy === 'object') {
|
|
41
|
+
const purpose = String(pkg.nexowattReleasePolicy.purpose || '');
|
|
42
|
+
const nextPurpose = purpose
|
|
43
|
+
? purpose.replace(/\b7\.9\.\d+(?:-[0-9A-Za-z.-]+)?\b/g, version)
|
|
44
|
+
: `accepted NexoWatt EOS release ${version}`;
|
|
45
|
+
setValue(changes, 'package.json nexowattReleasePolicy.purpose', pkg.nexowattReleasePolicy, 'purpose', nextPurpose);
|
|
46
|
+
if (version.includes('-')) {
|
|
47
|
+
setValue(changes, 'package.json nexowattReleasePolicy.acceptedPrerelease', pkg.nexowattReleasePolicy, 'acceptedPrerelease', version);
|
|
48
|
+
} else if (Object.prototype.hasOwnProperty.call(pkg.nexowattReleasePolicy, 'acceptedPrerelease')) {
|
|
49
|
+
changes.push({
|
|
50
|
+
label: 'package.json nexowattReleasePolicy.acceptedPrerelease',
|
|
51
|
+
previous: pkg.nexowattReleasePolicy.acceptedPrerelease,
|
|
52
|
+
value: '<removed>',
|
|
53
|
+
});
|
|
54
|
+
delete pkg.nexowattReleasePolicy.acceptedPrerelease;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
writeJson(packageFile, pkg);
|
|
58
|
+
|
|
59
|
+
const jsonTargets = [
|
|
60
|
+
{
|
|
61
|
+
file: 'package-lock.json',
|
|
62
|
+
update(json) {
|
|
63
|
+
setValue(changes, 'package-lock.json version', json, 'version', version);
|
|
64
|
+
if (json.packages?.['']) {
|
|
65
|
+
setValue(changes, 'package-lock.json packages[""] version', json.packages[''], 'version', version);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
file: 'io-package.json',
|
|
71
|
+
update(json) {
|
|
72
|
+
setValue(changes, 'io-package.json top-level version', json, 'version', version);
|
|
73
|
+
json.common ||= {};
|
|
74
|
+
setValue(changes, 'io-package.json common.version', json.common, 'version', version);
|
|
75
|
+
setValue(changes, 'io-package.json common.extIcon', json.common, 'extIcon', `${expectedBase}/admin/admin.svg`);
|
|
76
|
+
setValue(changes, 'io-package.json common.readme', json.common, 'readme', `${expectedBase}/README.md`);
|
|
77
|
+
setValue(changes, 'io-package.json common.meta', json.common, 'meta', `${expectedBase}/io-package.json`);
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
file: 'src-admin/package.json',
|
|
82
|
+
update(json) {
|
|
83
|
+
setValue(changes, 'src-admin/package.json version', json, 'version', version);
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
file: 'src-admin/package-lock.json',
|
|
88
|
+
update(json) {
|
|
89
|
+
setValue(changes, 'src-admin/package-lock.json version', json, 'version', version);
|
|
90
|
+
if (json.packages?.['']) {
|
|
91
|
+
setValue(changes, 'src-admin/package-lock.json packages[""] version', json.packages[''], 'version', version);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
file: 'src-admin/src/version.json',
|
|
97
|
+
update(json) {
|
|
98
|
+
setValue(changes, 'src-admin/src/version.json version', json, 'version', version);
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
file: 'NEXOWATT_EOS_BUILD_INFO.json',
|
|
103
|
+
update(json) {
|
|
104
|
+
setValue(changes, 'NEXOWATT_EOS_BUILD_INFO.json version', json, 'version', version);
|
|
105
|
+
setValue(changes, 'NEXOWATT_EOS_BUILD_INFO.json label', json, 'label', `v${releaseNo}`);
|
|
106
|
+
setValue(
|
|
107
|
+
changes,
|
|
108
|
+
'NEXOWATT_EOS_BUILD_INFO.json repositoryEntry',
|
|
109
|
+
json,
|
|
110
|
+
'repositoryEntry',
|
|
111
|
+
`nexowatt-eos-admin-repository-entry-v${releaseNo}.json`,
|
|
112
|
+
);
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
for (const target of jsonTargets) {
|
|
118
|
+
const file = path.join(root, target.file);
|
|
119
|
+
if (!fs.existsSync(file)) {
|
|
120
|
+
throw new Error(`${target.file} is missing`);
|
|
121
|
+
}
|
|
122
|
+
const json = readJson(file);
|
|
123
|
+
target.update(json);
|
|
124
|
+
writeJson(file, json);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Keep one canonical repository entry for the current release. When a new
|
|
128
|
+
// patch version is merged over an older folder, the entry is created from
|
|
129
|
+
// the previous canonical entry and then normalized.
|
|
130
|
+
const buildInfo = readJson(path.join(root, 'NEXOWATT_EOS_BUILD_INFO.json'));
|
|
131
|
+
const targetEntryName = buildInfo.repositoryEntry;
|
|
132
|
+
const targetEntryFile = path.join(root, targetEntryName);
|
|
133
|
+
let entry;
|
|
134
|
+
if (fs.existsSync(targetEntryFile)) {
|
|
135
|
+
entry = readJson(targetEntryFile);
|
|
136
|
+
} else {
|
|
137
|
+
const candidates = fs
|
|
138
|
+
.readdirSync(root)
|
|
139
|
+
.filter(name => /^nexowatt-eos-admin-repository-entry-v.+\.json$/.test(name))
|
|
140
|
+
.sort((a, b) => fs.statSync(path.join(root, b)).mtimeMs - fs.statSync(path.join(root, a)).mtimeMs);
|
|
141
|
+
if (!candidates.length) {
|
|
142
|
+
throw new Error('No repository entry template found');
|
|
143
|
+
}
|
|
144
|
+
entry = readJson(path.join(root, candidates[0]));
|
|
145
|
+
changes.push({ label: targetEntryName, previous: '<missing>', value: 'created' });
|
|
146
|
+
}
|
|
147
|
+
entry['eos-admin'] ||= {};
|
|
148
|
+
setValue(changes, `${targetEntryName} version`, entry['eos-admin'], 'version', version);
|
|
149
|
+
setValue(changes, `${targetEntryName} meta`, entry['eos-admin'], 'meta', `${expectedBase}/io-package.json`);
|
|
150
|
+
setValue(changes, `${targetEntryName} icon`, entry['eos-admin'], 'icon', `${expectedBase}/admin/admin.png`);
|
|
151
|
+
setValue(changes, `${targetEntryName} extIcon`, entry['eos-admin'], 'extIcon', `${expectedBase}/admin/admin.svg`);
|
|
152
|
+
setValue(changes, `${targetEntryName} readme`, entry['eos-admin'], 'readme', `${expectedBase}/README.md`);
|
|
153
|
+
writeJson(targetEntryFile, entry);
|
|
154
|
+
|
|
155
|
+
return { root, version, changes, repositoryEntry: targetEntryName };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (require.main === module) {
|
|
159
|
+
const args = process.argv.slice(2);
|
|
160
|
+
const quiet = args.includes('--quiet');
|
|
161
|
+
const rootArg = args.find(arg => !arg.startsWith('--'));
|
|
162
|
+
try {
|
|
163
|
+
const result = syncReleaseVersion(rootArg || path.resolve(__dirname, '..'));
|
|
164
|
+
if (!quiet) {
|
|
165
|
+
if (result.changes.length) {
|
|
166
|
+
console.log(
|
|
167
|
+
`[NexoWatt EOS version sync] repaired ${result.changes.length} release value(s) for ${result.version}: ${result.changes
|
|
168
|
+
.map(change => change.label)
|
|
169
|
+
.join(', ')}`,
|
|
170
|
+
);
|
|
171
|
+
} else {
|
|
172
|
+
console.log(`[NexoWatt EOS version sync] OK (${result.version}; all release files match)`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
} catch (error) {
|
|
176
|
+
console.error(`[NexoWatt EOS version sync] ${error instanceof Error ? error.message : String(error)}`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
module.exports = { syncReleaseVersion };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
const fs=require('node:fs');const path=require('node:path');const root=path.resolve(__dirname,'..');
|
|
4
|
+
const read=rel=>fs.readFileSync(path.join(root,rel),'utf8');const fail=msg=>{console.error(`[NexoWatt EOS UI overview runtime] ${msg}`);process.exit(1)};
|
|
5
|
+
const runtime=read('adminWww/js/eos-ems-overview.js');const source=read('src-admin/public/js/eos-ems-overview.js');const css=read('adminWww/css/eos-ems-overview.css');const index=read('adminWww/index.html');const role=read('adminWww/js/eos-role-ui.js');const shell=read('adminWww/js/nexowatt-native-shell.js');const intro=read('src-admin/src/tabs/Intro.tsx');const app=read('src-admin/src/App.tsx');const bundle=read('adminWww/assets/index-D2ymscJA-v84.js');
|
|
6
|
+
if(runtime!==source)fail('runtime source/build drift');
|
|
7
|
+
for(const marker of ['nexowatt-ems-overview-v1','nexowatt-ui.*.info.adminOverview.*','system.adapter.nexowatt-ui.*.alive','POLL_MS = 5000','STALE_MS = 20000','getForeignStates','Keine Kachel besitzt Schreibhoheit','currentDecisions','§14a-Fallback'])if(!runtime.includes(marker))fail(`runtime marker missing: ${marker}`);
|
|
8
|
+
for(const forbidden of ['setForeignState','setState(','sendToHost','writeFile','extendObject'])if(runtime.includes(forbidden))fail(`read-only runtime contains ${forbidden}`);
|
|
9
|
+
for(const marker of ['eos-ems-overview.css?v=96','eos-ems-overview.js?v=96','nexowatt-stable-v96.js?v=96'])if(!index.includes(marker))fail(`index marker missing: ${marker}`);
|
|
10
|
+
if(!css.includes('#eos-ems-overview-runtime')||!css.includes('.eos-ems-overview-metrics'))fail('EMS card CSS incomplete');
|
|
11
|
+
if(role.includes("overview.innerHTML = `")||!role.includes('never cover the real Admin Intro'))fail('obsolete role overview still active');
|
|
12
|
+
if(!shell.includes("label: 'Installateur'")||!shell.includes("label: 'Endkunde'"))fail('native hero is not role-aware');
|
|
13
|
+
if(!intro.includes('<NexoWattEmsOverview')||!intro.includes('getOverviewRoleConfig')||!intro.includes('admin ? this.getButtons() : null'))fail('React Intro integration incomplete');
|
|
14
|
+
if(!app.includes('NEXOWATT_EOS_ADMIN_SOCKET = new Connection'))fail('source socket exposure missing');
|
|
15
|
+
if(!bundle.includes('window.NEXOWATT_EOS_ADMIN_SOCKET=new M({'))fail('prebuilt socket exposure missing');
|
|
16
|
+
console.log('[NexoWatt EOS UI overview runtime] OK');
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
const root = path.resolve(__dirname, '..');
|
|
7
|
+
const fail = msg => {
|
|
8
|
+
console.error(`[NexoWatt EOS package validation] ${msg}`);
|
|
9
|
+
process.exit(1);
|
|
10
|
+
};
|
|
11
|
+
const read = file => fs.readFileSync(path.join(root, file), 'utf8');
|
|
12
|
+
const readJson = file => JSON.parse(read(file));
|
|
13
|
+
const exists = file => fs.existsSync(path.join(root, file));
|
|
14
|
+
|
|
15
|
+
const pkg = readJson('package.json');
|
|
16
|
+
const pkgLock = readJson('package-lock.json');
|
|
17
|
+
const io = readJson('io-package.json');
|
|
18
|
+
const srcPkg = readJson('src-admin/package.json');
|
|
19
|
+
const srcPkgLock = readJson('src-admin/package-lock.json');
|
|
20
|
+
const srcVersion = readJson('src-admin/src/version.json');
|
|
21
|
+
const buildInfo = readJson('NEXOWATT_EOS_BUILD_INFO.json');
|
|
22
|
+
|
|
23
|
+
if (pkg.name !== 'iobroker.eos-admin') fail(`package.json name must be iobroker.eos-admin, got ${pkg.name}`);
|
|
24
|
+
if (pkg.private !== false) fail('package.json private must be false for npm publishing');
|
|
25
|
+
|
|
26
|
+
const prerelease = pkg.version.includes('-');
|
|
27
|
+
if (pkg.publishConfig?.tag !== 'latest') fail(`package must publish through npm latest, got ${pkg.publishConfig?.tag || '<unset>'}`);
|
|
28
|
+
if (!exists('.npmrc') || !/^\s*tag\s*=\s*latest\s*$/m.test(read('.npmrc'))) fail('repository must contain .npmrc with tag=latest');
|
|
29
|
+
if (prerelease) {
|
|
30
|
+
if (pkg.nexowattReleasePolicy?.distTag !== 'latest') fail('accepted prerelease must record distTag=latest');
|
|
31
|
+
if (pkg.nexowattReleasePolicy?.acceptedPrerelease !== pkg.version) fail('acceptedPrerelease must match the exact package version');
|
|
32
|
+
} else if (pkg.nexowattReleasePolicy?.acceptedPrerelease) {
|
|
33
|
+
fail(`stable package must remove stale acceptedPrerelease ${pkg.nexowattReleasePolicy.acceptedPrerelease}`);
|
|
34
|
+
}
|
|
35
|
+
if (pkg.scripts['prepare:eos-release-defaults'] !== 'node tools/nexowatt-ensure-release-defaults.cjs') fail('release-default preparation script is missing');
|
|
36
|
+
if (pkg.scripts['test:eos-release-defaults'] !== 'node tools/nexowatt-release-defaults-selftest.cjs') fail('release-default selftest script is missing');
|
|
37
|
+
if (pkg.scripts['check:eos-publish-channel'] !== 'node tools/nexowatt-publish-channel-guard.cjs') fail('publish channel guard script is missing');
|
|
38
|
+
|
|
39
|
+
if (pkg.scripts['sync:eos-version'] !== 'node tools/nexowatt-sync-release-version.cjs') fail('sync:eos-version script is missing or incorrect');
|
|
40
|
+
if (pkg.scripts['test:eos-version-sync'] !== 'node tools/nexowatt-version-sync-selftest.cjs') fail('version sync selftest script is missing or incorrect');
|
|
41
|
+
if (pkg.scripts['verify:eos-merge'] !== 'node tools/nexowatt-merge-update-selftest.cjs') fail('merge update selftest script is missing or incorrect');
|
|
42
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-version-sync-selftest.cjs')) fail('version sync selftest is not part of check:eos-stability');
|
|
43
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-merge-update-selftest.cjs')) fail('merge update selftest is not part of check:eos-stability');
|
|
44
|
+
if (pkg.scripts['check:eos-stable-v96'] !== 'node tools/nexowatt-stable-v96-selftest.cjs') fail('stable v96 selftest script is missing or incorrect');
|
|
45
|
+
if (!pkg.scripts.prepublishOnly?.startsWith('npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run check:eos-publish-channel')) fail('prepublishOnly must synchronize versions and normalize release defaults before the publish channel guard');
|
|
46
|
+
if (pkg.scripts['precheck:eos-package'] !== 'npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run clean:eos-runtime') fail('precheck:eos-package must synchronize versions, normalize release defaults and clean stale runtime files');
|
|
47
|
+
if (pkg.scripts['precheck:eos-stability'] !== 'npm run sync:eos-version && npm run prepare:eos-release-defaults && npm run clean:eos-runtime') fail('precheck:eos-stability must synchronize versions, normalize release defaults and clean stale runtime files');
|
|
48
|
+
if (pkg.scripts['test:eos-publish-channel'] !== 'node tools/nexowatt-publish-channel-selftest.cjs') fail('publish channel selftest script is missing');
|
|
49
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-publish-channel-selftest.cjs')) fail('stability check must execute the publish channel selftest');
|
|
50
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-release-defaults-selftest.cjs')) fail('stability check must execute the release-default selftest');
|
|
51
|
+
if (io.native?.auth !== true) fail('fresh sales installations must default to authenticated access');
|
|
52
|
+
if (io.native?.eosHideLegacyBackupFromNonAdmins !== true) fail('internal BackItUp reserve must default to Admin/Service visibility');
|
|
53
|
+
if (io.native?.nexowattHideLegacyBackupFromNonAdmins !== true) fail('NexoWatt backup visibility compatibility flag must default to true');
|
|
54
|
+
for (const [label, value] of [
|
|
55
|
+
['io-package common.version', io.common?.version],
|
|
56
|
+
['io-package top-level version', io.version],
|
|
57
|
+
['package-lock version', pkgLock.version],
|
|
58
|
+
['package-lock root version', pkgLock.packages?.['']?.version],
|
|
59
|
+
['src-admin package version', srcPkg.version],
|
|
60
|
+
['src-admin lock version', srcPkgLock.version],
|
|
61
|
+
['src-admin lock root version', srcPkgLock.packages?.['']?.version],
|
|
62
|
+
['src-admin source version', srcVersion.version],
|
|
63
|
+
['build-info version', buildInfo.version],
|
|
64
|
+
]) if (value !== pkg.version) fail(`${label} must match package.json (${pkg.version}), got ${value}`);
|
|
65
|
+
|
|
66
|
+
if (io.common?.name !== 'eos-admin') fail(`io-package common.name must be eos-admin, got ${io.common?.name}`);
|
|
67
|
+
if (io.common?.packetName !== 'iobroker.eos-admin') fail(`io-package common.packetName must be iobroker.eos-admin, got ${io.common?.packetName}`);
|
|
68
|
+
if (io.common?.npmPackage !== 'iobroker.eos-admin') fail(`io-package common.npmPackage must be iobroker.eos-admin, got ${io.common?.npmPackage}`);
|
|
69
|
+
if (io.native?.port !== 8081) fail(`EOS Admin default port must be 8081, got ${io.native?.port}`);
|
|
70
|
+
if (io.common?.stopBeforeUpdate !== false) fail('io-package common.stopBeforeUpdate must be false');
|
|
71
|
+
if (io.common?.dontDelete === true || io.common?.nondeletable === true) fail('adapter-level delete flags must not block updates');
|
|
72
|
+
|
|
73
|
+
const expectedBase = `https://unpkg.com/iobroker.eos-admin@${pkg.version}`;
|
|
74
|
+
for (const [field, expected] of Object.entries({
|
|
75
|
+
extIcon: `${expectedBase}/admin/admin.svg`,
|
|
76
|
+
readme: `${expectedBase}/README.md`,
|
|
77
|
+
meta: `${expectedBase}/io-package.json`,
|
|
78
|
+
})) if (io.common?.[field] !== expected) fail(`io-package common.${field} must be ${expected}, got ${io.common?.[field]}`);
|
|
79
|
+
|
|
80
|
+
const releaseNo = String(pkg.version).match(/^7\.9\.(\d+)/)?.[1];
|
|
81
|
+
const repositoryEntryFile = buildInfo.repositoryEntry || `nexowatt-eos-admin-repository-entry-v${releaseNo}.json`;
|
|
82
|
+
const repositoryEntry = readJson(repositoryEntryFile)['eos-admin'];
|
|
83
|
+
if (!repositoryEntry) fail(`${repositoryEntryFile} is missing eos-admin`);
|
|
84
|
+
if (repositoryEntry.version !== pkg.version) fail(`repository entry version must be ${pkg.version}, got ${repositoryEntry.version}`);
|
|
85
|
+
for (const [field, expected] of Object.entries({
|
|
86
|
+
meta: `${expectedBase}/io-package.json`,
|
|
87
|
+
icon: `${expectedBase}/admin/admin.png`,
|
|
88
|
+
extIcon: `${expectedBase}/admin/admin.svg`,
|
|
89
|
+
readme: `${expectedBase}/README.md`,
|
|
90
|
+
})) if (repositoryEntry[field] !== expected) fail(`repository entry ${field} must be ${expected}, got ${repositoryEntry[field]}`);
|
|
91
|
+
|
|
92
|
+
for (const file of [
|
|
93
|
+
'adminWww/index.html',
|
|
94
|
+
'adminWww/js/eos-manual-write-policy.js',
|
|
95
|
+
'adminWww/js/eos-role-bootstrap.js',
|
|
96
|
+
'adminWww/js/eos-branding-sanitizer.js',
|
|
97
|
+
'adminWww/js/eos-policy-client.js',
|
|
98
|
+
'adminWww/js/nexowatt-native-shell.js',
|
|
99
|
+
'adminWww/js/eos-native-security.js',
|
|
100
|
+
'adminWww/js/eos-basic-settings.js',
|
|
101
|
+
'adminWww/js/eos-role-ui.js',
|
|
102
|
+
'adminWww/js/eos-account-management.js',
|
|
103
|
+
'adminWww/js/eos-assistant.js',
|
|
104
|
+
'adminWww/css/nexowatt-native-shell.css',
|
|
105
|
+
'adminWww/img/eos/nexowatt-192.png',
|
|
106
|
+
'src-admin/src/components/NexoWattNavIcon.tsx',
|
|
107
|
+
'src-admin/src/components/Drawer.tsx',
|
|
108
|
+
'src-admin/src/components/DrawerItem.tsx',
|
|
109
|
+
'admin/admin.svg',
|
|
110
|
+
'LICENSE',
|
|
111
|
+
'NEXOWATT_PROPRIETARY_LICENSE.md',
|
|
112
|
+
'THIRD_PARTY_NOTICES.md',
|
|
113
|
+
'README_STABILITY_V7.9.96.md',
|
|
114
|
+
'RELEASE_NOTES_V7.9.96.md',
|
|
115
|
+
'PUBLISH_STABLE_V7.9.96.md',
|
|
116
|
+
'INSTALL_TEST_V7.9.96.md',
|
|
117
|
+
'RELEASE_ACCEPTANCE_V7.9.96.md',
|
|
118
|
+
'MERGE_UPDATE.ps1',
|
|
119
|
+
'MERGE_UPDATE.cmd',
|
|
120
|
+
'MERGE_UPDATE_README_V7.9.96.md',
|
|
121
|
+
'tools/nexowatt-patch-built-frontend.cjs',
|
|
122
|
+
'tools/nexowatt-native-shell-selftest.cjs',
|
|
123
|
+
'tools/nexowatt-clean-legacy-runtime.cjs',
|
|
124
|
+
'tools/nexowatt-runtime-cleanup-selftest.cjs',
|
|
125
|
+
'tools/nexowatt-esm-syntax-selftest.cjs',
|
|
126
|
+
'tools/nexowatt-import-integrity-selftest.cjs',
|
|
127
|
+
'tools/nexowatt-entrypoint-smoke-selftest.cjs',
|
|
128
|
+
'tools/nexowatt-role-access-selftest.cjs',
|
|
129
|
+
'tools/nexowatt-first-login-selftest.cjs',
|
|
130
|
+
'tools/nexowatt-account-management-selftest.cjs',
|
|
131
|
+
'tools/nexowatt-modern-ui-selftest.cjs',
|
|
132
|
+
'tools/nexowatt-login-layout-selftest.cjs',
|
|
133
|
+
'tools/nexowatt-internal-reserve-selftest.cjs',
|
|
134
|
+
'tools/nexowatt-branding-selftest.cjs',
|
|
135
|
+
'tools/nexowatt-sync-release-version.cjs',
|
|
136
|
+
'tools/nexowatt-version-sync-selftest.cjs',
|
|
137
|
+
'tools/nexowatt-merge-update-selftest.cjs',
|
|
138
|
+
'tools/nexowatt-stable-v96-selftest.cjs',
|
|
139
|
+
'tools/nexowatt-ems-overview-selftest.cjs',
|
|
140
|
+
'tools/nexowatt-ui-overview-runtime-selftest.cjs',
|
|
141
|
+
'adminWww/js/eos-ems-overview.js',
|
|
142
|
+
'adminWww/css/eos-ems-overview.css',
|
|
143
|
+
'adminWww/static/js/nexowatt-stable-v96.js',
|
|
144
|
+
'src-admin/src/components/Intro/NexoWattEmsOverview.tsx',
|
|
145
|
+
'tools/nexowatt-publish-channel-guard.cjs',
|
|
146
|
+
'tools/nexowatt-publish-channel-selftest.cjs',
|
|
147
|
+
'tools/nexowatt-ensure-release-defaults.cjs',
|
|
148
|
+
'tools/nexowatt-release-defaults-selftest.cjs',
|
|
149
|
+
'tools/nexowatt-default-port-selftest.cjs',
|
|
150
|
+
'.npmrc',
|
|
151
|
+
repositoryEntryFile,
|
|
152
|
+
]) if (!exists(file)) fail(`missing required file: ${file}`);
|
|
153
|
+
|
|
154
|
+
for (const file of pkg.files || []) {
|
|
155
|
+
const normalized = String(file).replace(/\\/g, '/').replace(/\/\*\*\/\*$/, '');
|
|
156
|
+
if (!/[?*]/.test(normalized) && !exists(normalized.replace(/\/$/, ''))) fail(`package.json files entry does not exist: ${file}`);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const index = read('adminWww/index.html');
|
|
160
|
+
const refs = [...index.matchAll(/(?:src|href)="\.\/([^"?#]+)(?:\?[^"#]*)?"/g)].map(m => m[1]);
|
|
161
|
+
const missing = refs.filter(ref => !exists(path.join('adminWww', ref)));
|
|
162
|
+
if (missing.length) fail(`adminWww/index.html references missing files:\n${missing.join('\n')}`);
|
|
163
|
+
|
|
164
|
+
const runtime = buildInfo.runtimeEntry;
|
|
165
|
+
const runtimeNumber = Number(String(runtime).replace(/^v/, ''));
|
|
166
|
+
const shellCache = Number(buildInfo.shellCacheVersion ?? buildInfo.nativeShellVersion ?? runtimeNumber);
|
|
167
|
+
const shellTag = String(buildInfo.shellCacheTag || shellCache);
|
|
168
|
+
if (!runtime || !Number.isFinite(runtimeNumber)) fail(`invalid runtimeEntry ${runtime}`);
|
|
169
|
+
if (!Number.isFinite(shellCache)) fail(`invalid shellCacheVersion ${buildInfo.shellCacheVersion}`);
|
|
170
|
+
for (const marker of [
|
|
171
|
+
`hostInit-${runtime}.js?v=${runtimeNumber}`,
|
|
172
|
+
`index-CQZugZ1z-${runtime}.js?v=${runtimeNumber}`,
|
|
173
|
+
`eos-manual-write-policy.js?v=${shellTag}`,
|
|
174
|
+
`nexowatt-native-shell.css?v=${shellTag}`,
|
|
175
|
+
`nexowatt-native-shell.js?v=${shellTag}`,
|
|
176
|
+
`eos-native-security.js?v=${shellTag}`,
|
|
177
|
+
]) if (!index.includes(marker)) fail(`adminWww/index.html missing ${marker}`);
|
|
178
|
+
|
|
179
|
+
if (!index.includes(`eos-role-bootstrap.js?v=${shellTag}`)) fail('role bootstrap cache key mismatch');
|
|
180
|
+
if (!index.includes(`eos-branding-sanitizer.js?v=${shellTag}`)) fail('branding sanitizer cache key mismatch');
|
|
181
|
+
if (!index.includes(`eos-role-ui.js?v=${shellTag}`)) fail('role UI cache key mismatch');
|
|
182
|
+
if (!index.includes(`eos-account-management.js?v=${shellTag}`)) fail('account management cache key mismatch');
|
|
183
|
+
if (!index.includes(`eos-assistant.js?v=${shellTag}`)) fail('EOS Assist cache key mismatch');
|
|
184
|
+
if (!index.includes(`eos-ems-overview.js?v=${shellTag}`)) fail('EMS overview cache key mismatch');
|
|
185
|
+
if (!index.includes(`eos-ems-overview.css?v=${shellTag}`)) fail('EMS overview CSS cache key mismatch');
|
|
186
|
+
if (!index.includes(`nexowatt-stable-v96.js?v=${shellTag}`)) fail('stable v96 cache key mismatch');
|
|
187
|
+
if (index.indexOf(`eos-manual-write-policy.js?v=${shellTag}`) > index.indexOf(`hostInit-${runtime}.js?v=${runtimeNumber}`)) fail('manual-write policy must load before the React runtime');
|
|
188
|
+
if (!index.includes('class="eos-native-shell"')) fail('native NexoWatt shell class missing');
|
|
189
|
+
for (const legacy of ['eos-branding.js', 'eos-security-ui.js', 'eos-console-quiet.js', 'eos-objects-state-tools.js']) {
|
|
190
|
+
if (index.includes(legacy)) fail(`legacy browser overlay still loaded: ${legacy}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const activeBootstrapFile = `adminWww/assets/bootstrap-COulQZax-${runtime}.js`;
|
|
194
|
+
for (const file of [
|
|
195
|
+
`adminWww/assets/hostInit-${runtime}.js`,
|
|
196
|
+
`adminWww/assets/index-CQZugZ1z-${runtime}.js`,
|
|
197
|
+
activeBootstrapFile,
|
|
198
|
+
`adminWww/assets/Objects-DPan0bzw-${runtime}.js`,
|
|
199
|
+
`adminWww/assets/index-D2ymscJA-${runtime}.js`,
|
|
200
|
+
`adminWww/remoteEntry-${runtime}.js`,
|
|
201
|
+
]) if (!exists(file)) fail(`missing active runtime file ${file}`);
|
|
202
|
+
|
|
203
|
+
const bootstrap = read(activeBootstrapFile);
|
|
204
|
+
if (!bootstrap.includes('window.adapterName="eos-admin"')) fail('frontend bootstrap does not set window.adapterName="eos-admin"');
|
|
205
|
+
if (bootstrap.includes('window.adapterName="admin"')) fail('frontend bootstrap still contains window.adapterName="admin"');
|
|
206
|
+
for (const marker of ['NEXOWATT_TAB_ICON', 'nexowatt-native-nav-item', 'nexowatt-native-nav-icon', 'tabName:h.name', 'NexoWatt EOS', 'Zugänge & Rechte']) {
|
|
207
|
+
if (!bootstrap.includes(marker)) fail(`active bootstrap missing native navigation marker ${marker}`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const drawer = read('src-admin/src/components/Drawer.tsx');
|
|
211
|
+
const drawerItem = read('src-admin/src/components/DrawerItem.tsx');
|
|
212
|
+
const navIcon = read('src-admin/src/components/NexoWattNavIcon.tsx');
|
|
213
|
+
for (const marker of ['getNexoWattTabTitle', 'getNexoWattTabIcon', "'tab-intro': 'Übersicht'", "'tab-users': 'Zugänge & Rechte'", 'System-Notfallsicherung', 'NexoWatt Sicherung']) {
|
|
214
|
+
if (!drawer.includes(marker)) fail(`Drawer source missing ${marker}`);
|
|
215
|
+
}
|
|
216
|
+
if (!drawerItem.includes('className="nexowatt-native-nav-item"') || !drawerItem.includes('data-eos-tab={tabName}')) fail('DrawerItem is not native-shell aware');
|
|
217
|
+
if (!navIcon.includes('eos-native-nav-icon-source') || !navIcon.includes('nexowatt-native-nav-icon')) fail('native SVG navigation icon component is incomplete');
|
|
218
|
+
|
|
219
|
+
const shell = read('adminWww/js/nexowatt-native-shell.js');
|
|
220
|
+
const shellCss = read('adminWww/css/nexowatt-native-shell.css');
|
|
221
|
+
const nativeSecurity = read('adminWww/js/eos-native-security.js');
|
|
222
|
+
const accountManagement = read('adminWww/js/eos-account-management.js');
|
|
223
|
+
if (!shell.includes(`const VERSION = 'v${shellCache}-nexowatt-native-shell`)) fail(`native shell version marker v${shellCache} missing`);
|
|
224
|
+
if (!shell.includes('Navigation labels and') || !shell.includes('rendered natively by Drawer.tsx')) fail('native shell ownership guard missing');
|
|
225
|
+
if (shell.includes('innerHTML = cfg.svg') || shell.includes('textNode.textContent = cfg.label')) fail('native shell still rewrites navigation icons or labels after render');
|
|
226
|
+
if (!shell.includes('NEXOWATT_EOS_DOM_COORDINATOR')) fail('native shell does not use the shared DOM coordinator');
|
|
227
|
+
if (!shellCss.includes('.nexowatt-native-nav-item') || !shellCss.includes('.eos-native-nav-icon') || !shellCss.includes('.nexowatt-native-nav-icon')) fail('native shell CSS lacks React navigation selectors');
|
|
228
|
+
if (!nativeSecurity.includes('shouldBlockInstanceDelete')) fail('minimal native security API missing instance protection');
|
|
229
|
+
if (/addEventListener\(['"]click['"]/.test(nativeSecurity)) fail('native security must not globally intercept clicks');
|
|
230
|
+
if (!accountManagement.includes('NEXOWATT_EOS_ACCOUNT_MANAGEMENT') || !accountManagement.includes('X-NexoWatt-EOS-Account-Reset') || !accountManagement.includes('ensureEntrySurface')) fail('account-management runtime is incomplete');
|
|
231
|
+
if (accountManagement.includes("launcher.className = 'eos-account-management-launcher'")) fail('account management must not create a separate launcher');
|
|
232
|
+
if (accountManagement.includes('new MutationObserver')) fail('account-management runtime adds a second broad DOM observer');
|
|
233
|
+
if (read('src-admin/public/js/eos-account-management.js') !== accountManagement) fail('account-management source/build drift');
|
|
234
|
+
const roleBootstrap = read('adminWww/js/eos-role-bootstrap.js');
|
|
235
|
+
if (!roleBootstrap.includes('installIntegratedFirstLogin') || !roleBootstrap.includes('v96 compact normal-login first activation')) fail('compact integrated first-login is incomplete');
|
|
236
|
+
if (/data-eos-account=|selector\.innerHTML/.test(roleBootstrap)) fail('login role buttons must not enlarge the normal login card');
|
|
237
|
+
if (!roleBootstrap.includes('nexowatt/account/passwordless-status') || !roleBootstrap.includes('eligibility.allowed')) fail('server-checked first-login eligibility is incomplete');
|
|
238
|
+
if (roleBootstrap.includes('installPasswordlessFirstLoginLauncher')) fail('old first-login launcher remains active');
|
|
239
|
+
const assistant = read('adminWww/js/eos-assistant.js');
|
|
240
|
+
if (!assistant.includes('NEXOWATT_EOS_ASSIST_DISABLED')) fail('EOS Assist must be disabled in stable');
|
|
241
|
+
|
|
242
|
+
const mf = read('adminWww/mf-manifest.json');
|
|
243
|
+
if (!mf.includes(`remoteEntry-${runtime}.js`) || !mf.includes(`index-D2ymscJA-${runtime}.js`)) fail('module federation manifest is not on the active runtime');
|
|
244
|
+
|
|
245
|
+
const webBuild = read('build/lib/web.js');
|
|
246
|
+
if (!webBuild.includes('refreshLifetime: 60 * 60 * 24 * 7')) fail('build/lib/web.js must keep upstream-compatible refresh lifetime');
|
|
247
|
+
if (!webBuild.includes('Follow upstream admin semantics again')) fail('build/lib/web.js lacks session compatibility fix');
|
|
248
|
+
const mainBuild = read('build/main.js');
|
|
249
|
+
if (!mainBuild.includes('v37 BackItUp/runtime-adapter compatibility')) fail('build/main.js lacks BackItUp compatibility guard');
|
|
250
|
+
|
|
251
|
+
if (!pkg.scripts['nexowatt:patch-built-frontend']) fail('missing nexowatt:patch-built-frontend script');
|
|
252
|
+
if (pkg.scripts['check:eos-esm'] !== 'node tools/nexowatt-esm-syntax-selftest.cjs') fail('check:eos-esm script is missing or incorrect');
|
|
253
|
+
if (pkg.scripts['check:eos-imports'] !== 'node tools/nexowatt-import-integrity-selftest.cjs') fail('check:eos-imports script is missing or incorrect');
|
|
254
|
+
if (pkg.scripts['check:eos-entry'] !== 'node tools/nexowatt-entrypoint-smoke-selftest.cjs') fail('check:eos-entry script is missing or incorrect');
|
|
255
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-esm-syntax-selftest.cjs')) fail('ESM syntax selftest is not part of check:eos-stability');
|
|
256
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-import-integrity-selftest.cjs')) fail('import integrity selftest is not part of check:eos-stability');
|
|
257
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-entrypoint-smoke-selftest.cjs')) fail('entrypoint smoke selftest is not part of check:eos-stability');
|
|
258
|
+
if (pkg.scripts['clean:eos-runtime'] !== 'node tools/nexowatt-clean-legacy-runtime.cjs') fail('clean:eos-runtime script is missing or incorrect');
|
|
259
|
+
if (pkg.scripts.prepack !== 'node tools/nexowatt-sync-release-version.cjs --quiet && node tools/nexowatt-clean-legacy-runtime.cjs --quiet') fail('prepack must silently synchronize versions and clean stale runtime files');
|
|
260
|
+
if (!pkg.scripts.build?.includes('npm run clean:eos-runtime')) fail('build must finish with runtime cleanup');
|
|
261
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-role-access-selftest.cjs')) fail('role access selftest is not part of check:eos-stability');
|
|
262
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-first-login-selftest.cjs')) fail('first-login selftest is not part of check:eos-stability');
|
|
263
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-account-management-selftest.cjs')) fail('account-management selftest is not part of check:eos-stability');
|
|
264
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-modern-ui-selftest.cjs')) fail('modern-UI selftest is not part of check:eos-stability');
|
|
265
|
+
if (pkg.scripts['test:eos-login-layout'] !== 'node tools/nexowatt-login-layout-selftest.cjs') fail('login-layout selftest script is missing or incorrect');
|
|
266
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-login-layout-selftest.cjs')) fail('login-layout selftest is not part of check:eos-stability');
|
|
267
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-internal-reserve-selftest.cjs')) fail('internal reserve selftest is not part of check:eos-stability');
|
|
268
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-branding-selftest.cjs')) fail('branding selftest is not part of check:eos-stability');
|
|
269
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-native-shell-selftest.cjs')) fail('native shell selftest is not part of check:eos-stability');
|
|
270
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-assistant-separation-selftest.cjs')) fail('assistant separation selftest is not part of check:eos-stability');
|
|
271
|
+
if (!exists('adminWww/img/eos/nexowatt-eos-brand-wide.png')) fail('new NexoWatt EOS brand logo asset missing');
|
|
272
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-runtime-cleanup-selftest.cjs')) fail('runtime cleanup selftest is not part of check:eos-stability');
|
|
273
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-ems-overview-selftest.cjs')) fail('EMS React overview selftest is not part of check:eos-stability');
|
|
274
|
+
if (!pkg.scripts['check:eos-stability']?.includes('nexowatt-ui-overview-runtime-selftest.cjs')) fail('EMS runtime selftest is not part of check:eos-stability');
|
|
275
|
+
if (!read('tasks.mts').includes('patchNexoWattBuiltFrontend')) fail('tasks.mts does not execute the EOS post-build frontend patch');
|
|
276
|
+
|
|
277
|
+
console.log('[NexoWatt EOS package validation] OK');
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('node:fs');
|
|
5
|
+
const os = require('node:os');
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
const { syncReleaseVersion } = require('./nexowatt-sync-release-version.cjs');
|
|
8
|
+
|
|
9
|
+
const root = path.resolve(__dirname, '..');
|
|
10
|
+
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'nexowatt-eos-version-sync-'));
|
|
11
|
+
const fail = message => {
|
|
12
|
+
console.error(`[NexoWatt EOS version sync selftest] ${message}`);
|
|
13
|
+
fs.rmSync(temp, { recursive: true, force: true });
|
|
14
|
+
process.exit(1);
|
|
15
|
+
};
|
|
16
|
+
const readJson = file => JSON.parse(fs.readFileSync(path.join(temp, file), 'utf8'));
|
|
17
|
+
const writeJson = (file, value) => {
|
|
18
|
+
const target = path.join(temp, file);
|
|
19
|
+
fs.mkdirSync(path.dirname(target), { recursive: true });
|
|
20
|
+
fs.writeFileSync(target, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const currentPkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8'));
|
|
25
|
+
const version = currentPkg.version;
|
|
26
|
+
writeJson('package.json', currentPkg);
|
|
27
|
+
writeJson('package-lock.json', { name: currentPkg.name, version: '7.9.92', packages: { '': { version: '7.9.92' } } });
|
|
28
|
+
writeJson('io-package.json', {
|
|
29
|
+
version: '7.9.92',
|
|
30
|
+
common: {
|
|
31
|
+
version: '7.9.92',
|
|
32
|
+
extIcon: 'https://unpkg.com/iobroker.eos-admin@7.9.92/admin/admin.svg',
|
|
33
|
+
readme: 'https://unpkg.com/iobroker.eos-admin@7.9.92/README.md',
|
|
34
|
+
meta: 'https://unpkg.com/iobroker.eos-admin@7.9.92/io-package.json',
|
|
35
|
+
},
|
|
36
|
+
native: {},
|
|
37
|
+
});
|
|
38
|
+
writeJson('src-admin/package.json', { name: 'src-rx', version: '7.9.92' });
|
|
39
|
+
writeJson('src-admin/package-lock.json', { name: 'src-rx', version: '7.9.92', packages: { '': { version: '7.9.92' } } });
|
|
40
|
+
writeJson('src-admin/src/version.json', { version: '7.9.92' });
|
|
41
|
+
writeJson('NEXOWATT_EOS_BUILD_INFO.json', { version: '7.9.92', label: 'v92', repositoryEntry: 'nexowatt-eos-admin-repository-entry-v92.json' });
|
|
42
|
+
writeJson('nexowatt-eos-admin-repository-entry-v92.json', {
|
|
43
|
+
'eos-admin': {
|
|
44
|
+
version: '7.9.92',
|
|
45
|
+
meta: 'https://unpkg.com/iobroker.eos-admin@7.9.92/io-package.json',
|
|
46
|
+
icon: 'https://unpkg.com/iobroker.eos-admin@7.9.92/admin/admin.png',
|
|
47
|
+
extIcon: 'https://unpkg.com/iobroker.eos-admin@7.9.92/admin/admin.svg',
|
|
48
|
+
readme: 'https://unpkg.com/iobroker.eos-admin@7.9.92/README.md',
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
const result = syncReleaseVersion(temp);
|
|
53
|
+
if (result.version !== version) fail(`expected ${version}, got ${result.version}`);
|
|
54
|
+
|
|
55
|
+
const io = readJson('io-package.json');
|
|
56
|
+
const lock = readJson('package-lock.json');
|
|
57
|
+
const src = readJson('src-admin/package.json');
|
|
58
|
+
const srcLock = readJson('src-admin/package-lock.json');
|
|
59
|
+
const srcVersion = readJson('src-admin/src/version.json');
|
|
60
|
+
const build = readJson('NEXOWATT_EOS_BUILD_INFO.json');
|
|
61
|
+
const entry = readJson(build.repositoryEntry)['eos-admin'];
|
|
62
|
+
const expectedBase = `https://unpkg.com/iobroker.eos-admin@${version}`;
|
|
63
|
+
|
|
64
|
+
for (const [label, actual] of [
|
|
65
|
+
['io top-level', io.version],
|
|
66
|
+
['io common', io.common.version],
|
|
67
|
+
['lock', lock.version],
|
|
68
|
+
['lock root', lock.packages[''].version],
|
|
69
|
+
['src package', src.version],
|
|
70
|
+
['src lock', srcLock.version],
|
|
71
|
+
['src lock root', srcLock.packages[''].version],
|
|
72
|
+
['src version', srcVersion.version],
|
|
73
|
+
['build version', build.version],
|
|
74
|
+
['entry version', entry.version],
|
|
75
|
+
]) {
|
|
76
|
+
if (actual !== version) fail(`${label} was not synchronized: ${actual}`);
|
|
77
|
+
}
|
|
78
|
+
if (io.common.meta !== `${expectedBase}/io-package.json`) fail('io-package URL was not synchronized');
|
|
79
|
+
if (entry.meta !== `${expectedBase}/io-package.json`) fail('repository entry URL was not synchronized');
|
|
80
|
+
if (!fs.existsSync(path.join(temp, build.repositoryEntry))) fail('current repository entry was not created');
|
|
81
|
+
|
|
82
|
+
fs.rmSync(temp, { recursive: true, force: true });
|
|
83
|
+
console.log(`[NexoWatt EOS version sync selftest] OK (${version}; stale 7.9.92 merge repaired)`);
|
|
84
|
+
} catch (error) {
|
|
85
|
+
fail(error instanceof Error ? error.stack || error.message : String(error));
|
|
86
|
+
}
|
package/INSTALL_TEST_V7.9.95.md
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
# Installationstest 7.9.95
|
|
2
|
-
|
|
3
|
-
```bash
|
|
4
|
-
cd /opt/iobroker
|
|
5
|
-
iobroker stop eos-admin.0
|
|
6
|
-
npm install --no-save --omit=dev iobroker.eos-admin@7.9.95
|
|
7
|
-
iobroker upload eos-admin
|
|
8
|
-
iobroker restart eos-admin.0
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
Version prüfen:
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
node -p "require('/opt/iobroker/node_modules/iobroker.eos-admin/package.json').version"
|
|
15
|
-
```
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# NexoWatt EOS Admin 7.9.94 – Stable candidate
|
|
2
|
-
|
|
3
|
-
## Stable scope
|
|
4
|
-
|
|
5
|
-
- Standard port 8081 and authentication enabled.
|
|
6
|
-
- Initial commissioning credentials for `installer`, `guest`, and `user`: password `nexowatt`.
|
|
7
|
-
- A personal password is mandatory immediately after the first successful login.
|
|
8
|
-
- The old passwordless activation flow is disabled.
|
|
9
|
-
- Admin/Service credentials are never changed by the bootstrap.
|
|
10
|
-
- EOS Assist is disabled in this stable release and will return only after its separate read-only redesign and acceptance.
|
|
11
|
-
- The login card remains fully usable when validation or authentication errors are shown.
|
|
12
|
-
- Customer-visible publisher: NexoWatt; technical npm identity remains `iobroker.eos-admin` for update compatibility.
|
|
13
|
-
|
|
14
|
-
## Security note
|
|
15
|
-
|
|
16
|
-
The shared commissioning password is only an initial credential. Commissioning is not complete until installer and customer accounts have replaced it with personal passwords. Shipping a system with the initial credential still active is not permitted.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# npm-Veröffentlichung 7.9.95
|
|
2
|
-
|
|
3
|
-
Nach dem Entpacken der Merge-ZIP zuerst `MERGE_UPDATE.cmd` ausführen. Danach:
|
|
4
|
-
|
|
5
|
-
```powershell
|
|
6
|
-
npm login
|
|
7
|
-
npm whoami
|
|
8
|
-
npm publish --dry-run --tag latest
|
|
9
|
-
npm publish --tag latest
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
Kontrolle:
|
|
13
|
-
|
|
14
|
-
```powershell
|
|
15
|
-
npm view iobroker.eos-admin@latest version
|
|
16
|
-
```
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# NexoWatt EOS Admin 7.9.95 – Stabilität
|
|
2
|
-
|
|
3
|
-
Version 7.9.95 ist ein packaging-only Stable-Update. Die produktive Laufzeit, Rollenlogik, Erstanmeldung mit dem Startpasswort `nexowatt`, Standardport 8081 und die Deaktivierung des EOS Assist bleiben gegenüber 7.9.94 unverändert.
|
|
4
|
-
|
|
5
|
-
Neu ist die mergesichere Release-Vorbereitung: Alle versionsführenden Dateien werden vor Prüfung, Packen und npm-Veröffentlichung automatisch an `package.json` angeglichen.
|
|
6
|
-
|
|
7
|
-
Die npm-Dateiliste wird nun zusätzlich gegen das reale Dateisystem geprüft. Nicht vorhandene oder nicht gepackte Pflichtdateien brechen die Veröffentlichung vor dem Upload ab.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Zusätzlich werden die Rootmetadaten der Lockdateien gegen die zugehörigen `package.json`-Dateien geprüft. Dadurch können veraltete `prepublishOnly`-, `prepack`- oder Stabilitätsskripte nicht mehr unbemerkt in einer gemischten Arbeitskopie verbleiben.
|
|
11
|
-
|
|
12
|
-
Die Merge-Datei für bestehende Arbeitsordner wird ohne übergeordneten Versionsordner erzeugt. `package.json`, `io-package.json` und `MERGE_UPDATE.cmd` liegen unmittelbar auf der ersten ZIP-Ebene.
|