CH-J Toolsserverhåndtering over SSH
Menu
Offentliggjort kilde

CH-J Tools

Gennemse mapper og filer til en specifik applikationsudgivelse.

Download kilde ZIP
CH-J / Server Manager 406 filer
core-20261024T135205Z-7c487d719de2 Tilføjet: · Bygget:
generateThirdPartyNotices.js Tilføjet: Dato ikke registreret 7,6 KB · 139 linjer
Kode Download fil
1"use strict";
3const fs = require("node:fs");
4const path = require("node:path");
5const crypto = require("node:crypto");
6const AdmZip = require("adm-zip");
8const projectRoot = path.resolve(__dirname, "..");
9const lock = JSON.parse(fs.readFileSync(path.join(projectRoot, "package-lock.json"), "utf8"));
10const outputPath = path.join(projectRoot, "THIRD_PARTY_NOTICES.txt");
11const packages = new Map();
13// Electron 43 downloads its runtime lazily. The build copies license files from
14// that runtime, so make the documented `npm ci` -> `npm run build:*` flow
15// deterministic on every supported OS without a platform-specific shell step.
16const electronExecutable = require("electron");
17if (!fs.statSync(electronExecutable, { throwIfNoEntry: false })?.isFile()) {
18 throw new Error("Electron runtime is unavailable after dependency installation.");
21function declaredLicense(value) {
22 if (typeof value === "string") return value;
23 if (Array.isArray(value)) return value.map(declaredLicense).filter(Boolean).join(" OR ");
24 if (value && typeof value === "object") return String(value.type || value.name || "See included text");
25 return "See included text";
28function readLicense(directory) {
29 const entries = fs.readdirSync(directory, { withFileTypes: true });
30 const candidates = entries
31 .filter((entry) => entry.isFile() && /^(licen[cs]e|copying|notice)(\..*)?$/i.test(entry.name))
32 .sort((left, right) => left.name.localeCompare(right.name));
33 if (candidates.length) {
34 return candidates.map((entry) => ({ source: entry.name, text: fs.readFileSync(path.join(directory, entry.name), "utf8").trim() }));
35 }
36 const readme = entries.find((entry) => entry.isFile() && /^readme(?:\..*)?$/i.test(entry.name));
37 if (readme) {
38 const text = fs.readFileSync(path.join(directory, readme.name), "utf8");
39 const match = text.match(/^#{1,3}\s+licen[cs]e\s*$[\s\S]*/im);
40 if (match) return [{ source: `${readme.name} (License section)`, text: match[0].trim() }];
41 }
42 return [];
45for (const [relative, metadata] of Object.entries(lock.packages || {})) {
46 if (!relative.startsWith("node_modules/") || metadata.dev === true) continue;
47 const directory = path.join(projectRoot, relative);
48 const packagePath = path.join(directory, "package.json");
49 if (!fs.statSync(packagePath, { throwIfNoEntry: false })?.isFile()) continue;
50 const manifest = JSON.parse(fs.readFileSync(packagePath, "utf8"));
51 const key = `${manifest.name}@${manifest.version}`;
52 if (packages.has(key)) continue;
53 const texts = readLicense(directory);
54 if (!texts.length) throw new Error(`No distributable license text found for ${key}.`);
55 packages.set(key, { key, license: declaredLicense(manifest.license || metadata.license), texts });
57const bundledTigerLicense = path.join(projectRoot, "src", "main", "hashing", "vendor", "fbTiger", "LICENSE.txt");
58packages.set("fb-tiger-hash@1.0.0 (bundled source)", {
59 key: "fb-tiger-hash@1.0.0 (bundled source)",
60 license: "MIT",
61 texts: [{ source: "src/main/hashing/vendor/fbTiger/LICENSE.txt", text: fs.readFileSync(bundledTigerLicense, "utf8").trim() }]
62});
63const bundledCityHashLicense = path.join(projectRoot, "src", "main", "hashing", "vendor", "cityHash", "LICENSE.txt");
64packages.set("google-cityhash (ported source)", {
65 key: "google-cityhash (ported source)",
66 license: "MIT",
67 texts: [{ source: "src/main/hashing/vendor/cityHash/LICENSE.txt", text: fs.readFileSync(bundledCityHashLicense, "utf8").trim() }]
68});
69const bundledLucideLicense = path.join(projectRoot, "src", "renderer", "vendor", "lucide", "LICENSE.txt");
70packages.set("lucide-static@1.52.0 (bundled navigation icons)", {
71 key: "lucide-static@1.52.0 (bundled navigation icons)",
72 license: "ISC",
73 texts: [{ source: "src/renderer/vendor/lucide/LICENSE.txt", text: fs.readFileSync(bundledLucideLicense, "utf8").trim() }]
74});
76const separator = "=".repeat(78);
77const sections = [...packages.values()]
78 .sort((left, right) => left.key.localeCompare(right.key))
79 .map((entry) => {
80 const body = entry.texts.map((item) => `Source: ${item.source}\n\n${item.text}`).join("\n\n");
81 return `${separator}\n${entry.key}\nDeclared license: ${entry.license}\n${separator}\n\n${body}`;
82 });
83const header = [
84 "CH-J Server Manager — Third-Party Notices",
85 "",
86 "This file lists license texts for production Node.js dependencies bundled",
87 "with the application. Electron and Chromium license files are distributed",
88 "separately in the application's resources/licenses directory.",
89 ""
90].join("\n");
91fs.writeFileSync(outputPath, `${header}\n${sections.join("\n\n")}\n`, "utf8");
93const bundleDocuments = [
94 { name: "THIRD_PARTY_NOTICES.txt", path: outputPath, description: "Production Node.js dependency licenses" },
95 { name: "ELECTRON_LICENSE.txt", path: path.join(projectRoot, "node_modules", "electron", "dist", "LICENSE"), description: "Electron license" },
96 { name: "CHROMIUM_LICENSES.html", path: path.join(projectRoot, "node_modules", "electron", "dist", "LICENSES.chromium.html"), description: "Chromium and embedded component licenses" },
97 { name: "MONACO_LICENSE.txt", path: path.join(projectRoot, "node_modules", "monaco-editor", "LICENSE"), description: "Monaco Editor license" },
98 { name: "MONACO_THIRD_PARTY_NOTICES.txt", path: path.join(projectRoot, "node_modules", "monaco-editor", "ThirdPartyNotices.txt"), description: "Monaco Editor third-party notices" },
99 { name: "GOOGLE_CITYHASH_LICENSE.txt", path: bundledCityHashLicense, description: "Ported CityHash implementation license" },
100 { name: "FB_TIGER_HASH_LICENSE.txt", path: bundledTigerLicense, description: "Bundled Tiger/Tiger2 implementation license" },
101 { name: "LUCIDE_ICONS_LICENSE.txt", path: bundledLucideLicense, description: "Bundled Lucide navigation icons license" }
102];
103const nativeLicenseRoot = path.join(projectRoot, "scripts", "native", "licenses");
104if (fs.existsSync(nativeLicenseRoot)) {
105 for (const platform of fs.readdirSync(nativeLicenseRoot)) {
106 const dir = path.join(nativeLicenseRoot, platform);
107 for (const name of fs.readdirSync(dir)) bundleDocuments.push({ name: `native/${platform}/${name}`, path: path.join(dir, name), description: "Bundled native HTTP transport license/provenance" });
108 }
110for (const document of bundleDocuments) {
111 if (!fs.statSync(document.path, { throwIfNoEntry: false })?.isFile()) throw new Error(`Missing third-party license document: ${document.path}`);
112 document.data = fs.readFileSync(document.path);
113 document.sha512 = crypto.createHash("sha512").update(document.data).digest("hex");
115const bundleReadme = [
116 "CH-J Server Manager — Complete Third-Party License Package",
117 "",
118 "This archive contains the license texts and notices for third-party software",
119 "distributed by CH-J Server Manager Core and its bundled source components.",
120 "This application edition is licensed separately under the CH-J Proprietary Software License, version 1.14.",
121 "",
122 "Contents:",
123 ...bundleDocuments.map((document) => `- ${document.name}: ${document.description}`),
124 ""
125].join("\n");
126const checksums = bundleDocuments.map((document) => `${document.sha512} ${document.name}`).join("\n") + "\n";
127const zip = new AdmZip();
128for (const document of [
129 { name: "README.txt", data: Buffer.from(bundleReadme, "utf8") },
130 { name: "SHA512SUMS.txt", data: Buffer.from(checksums, "utf8") },
131 ...bundleDocuments
132]) {
133 zip.addFile(document.name, document.data, "", 0o644);
134 const entry = zip.getEntry(document.name);
135 if (entry) entry.header.time = new Date("2000-01-01T00:00:00Z");
137const bundlePath = path.join(projectRoot, "THIRD_PARTY_LICENSES.zip");
138zip.writeZip(bundlePath);
139console.log(`Generated ${path.basename(outputPath)} for ${sections.length} package versions and ${path.basename(bundlePath)} with ${bundleDocuments.length} complete license documents.`);
SHA-256a5b9bc9253152a4a501b393e633edd7e0ef935bd5dc027b1ebed7a57005fbcca

CH-J Proprietary Software License 1.14 · Kilden leveres under CH-J Proprietary Software License 1.14. Dens tilgængelighed ændrer ikke licensbetingelserne eller giver yderligere rettigheder.

Arkiv SHA-256476ed8aef0f1e96a5acdf223127b6692acdf4492eeaf5d0816b6e2a634fbbda6
Filer