CH-J Server Managerserver management over SSH
Menu
Published source

CH-J Server Manager

Browse directories and files for a specific application release.

Download source ZIP
CH-J Proprietary Software License 1.14

Source is provided under the CH-J Proprietary Software License 1.14. Its availability does not change the license terms or grant additional rights.

6,7 KB · 125 linesDownload file
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});
70const separator = "=".repeat(78);
71const sections = [...packages.values()]
72 .sort((left, right) => left.key.localeCompare(right.key))
73 .map((entry) => {
74 const body = entry.texts.map((item) => `Source: ${item.source}\n\n${item.text}`).join("\n\n");
75 return `${separator}\n${entry.key}\nDeclared license: ${entry.license}\n${separator}\n\n${body}`;
76 });
77const header = [
78 "CH-J Server Manager — Third-Party Notices",
79 "",
80 "This file lists license texts for production Node.js dependencies bundled",
81 "with the application. Electron and Chromium license files are distributed",
82 "separately in the application's resources/licenses directory.",
83 ""
84].join("\n");
85fs.writeFileSync(outputPath, `${header}\n${sections.join("\n\n")}\n`, "utf8");
87const bundleDocuments = [
88 { name: "THIRD_PARTY_NOTICES.txt", path: outputPath, description: "Production Node.js dependency licenses" },
89 { name: "ELECTRON_LICENSE.txt", path: path.join(projectRoot, "node_modules", "electron", "dist", "LICENSE"), description: "Electron license" },
90 { name: "CHROMIUM_LICENSES.html", path: path.join(projectRoot, "node_modules", "electron", "dist", "LICENSES.chromium.html"), description: "Chromium and embedded component licenses" },
91 { name: "MONACO_LICENSE.txt", path: path.join(projectRoot, "node_modules", "monaco-editor", "LICENSE"), description: "Monaco Editor license" },
92 { name: "MONACO_THIRD_PARTY_NOTICES.txt", path: path.join(projectRoot, "node_modules", "monaco-editor", "ThirdPartyNotices.txt"), description: "Monaco Editor third-party notices" },
93 { name: "GOOGLE_CITYHASH_LICENSE.txt", path: bundledCityHashLicense, description: "Ported CityHash implementation license" },
94 { name: "FB_TIGER_HASH_LICENSE.txt", path: bundledTigerLicense, description: "Bundled Tiger/Tiger2 implementation license" }
95];
96for (const document of bundleDocuments) {
97 if (!fs.statSync(document.path, { throwIfNoEntry: false })?.isFile()) throw new Error(`Missing third-party license document: ${document.path}`);
98 document.data = fs.readFileSync(document.path);
99 document.sha512 = crypto.createHash("sha512").update(document.data).digest("hex");
101const bundleReadme = [
102 "CH-J Server Manager — Complete Third-Party License Package",
103 "",
104 "This archive contains the license texts and notices for third-party software",
105 "distributed by CH-J Server Manager Core and its bundled source components.",
106 "This application edition is licensed separately under the CH-J Proprietary Software License, version 1.14.",
107 "",
108 "Contents:",
109 ...bundleDocuments.map((document) => `- ${document.name}: ${document.description}`),
110 ""
111].join("\n");
112const checksums = bundleDocuments.map((document) => `${document.sha512} ${document.name}`).join("\n") + "\n";
113const zip = new AdmZip();
114for (const document of [
115 { name: "README.txt", data: Buffer.from(bundleReadme, "utf8") },
116 { name: "SHA512SUMS.txt", data: Buffer.from(checksums, "utf8") },
117 ...bundleDocuments
118]) {
119 zip.addFile(document.name, document.data, "", 0o644);
120 const entry = zip.getEntry(document.name);
121 if (entry) entry.header.time = new Date("2000-01-01T00:00:00Z");
123const bundlePath = path.join(projectRoot, "THIRD_PARTY_LICENSES.zip");
124zip.writeZip(bundlePath);
125console.log(`Generated ${path.basename(outputPath)} for ${sections.length} package versions and ${path.basename(bundlePath)} with ${bundleDocuments.length} complete license documents.`);

SHA-256: aad5c90c9d1b53deb2abd3ff26215ed99f009566ee0b629452d18e8c1f4003b1

Archive SHA-256: 5ac91caf4fa32a6fdb114f2430deed486fbe7489d5eea343d1f034169fafb5e0